Sagacity¶
Your agent charged the card, reserved the inventory, then failed on step four. Sagacity undoes what already happened — and produces the evidence.
@Tool(description = "Charge the customer")
@Compensable(by = "refundCharge")
public String chargeCard(String amount, String customerId) {
return payments.charge(customerId, amount);
}
@Compensation
public void refundCharge(CompensationContext ctx) {
payments.refund(ctx.result());
}
That is the whole developer-facing idea. One annotation names the undo.
Compensation¶
Declare an undo per tool. On failure, compensations run in reverse order of execution, each outcome journaled. A failing compensation is recorded and the run continues — partial cleanup beats none.
Approval gates¶
Tools marked IRREVERSIBLE suspend the saga until a human approves. The approval
is bound to the exact payload the approver saw, so a re-planning agent cannot
substitute a different one.
The distinction that matters
Compensation is not durability¶
Temporal, Restate and DBOS solve durability — resuming a workflow after a crash. That is a different problem from compensation — undoing effects that already happened and cannot be replayed away.
A workflow that resumes perfectly still leaves you with a charged card when the business logic says the order must be abandoned. A refund is not a retry.
Sagacity solves compensation and evidence. It is not a workflow engine, not an agent framework, and does not replace the above — it sits inside Spring AI's tool-calling path and records what happened.
Install
Add the dependency¶
<dependency>
<groupId>io.github.sumitvairagar</groupId>
<artifactId>sagacity-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
Requires Java 17+, Spring AI 2.0.0, Spring Boot 4.0.x.
Spring Boot 4 is required, not optional
Spring AI 2.0.0 compiles against Spring Framework 7. Spring Boot 3.5.x
resolves Spring Framework 6.2 and will downgrade spring-core underneath
Spring AI, failing at runtime with
NoClassDefFoundError: org/springframework/core/Nullness.
Before you rely on it
Status¶
0.1.0 is a first release. The compensation, approval and audit paths are
covered by 88 unit tests and 18 integration tests against real Postgres, but the
library has not been battle-tested in production by anyone yet.
Read the threat model before relying on the audit trail for anything that matters — it states plainly what the hash chain does and does not defend against, including the parts that are unflattering.
Known gaps: no streaming tool-call support, no LangChain4j adapter, no UI. See the roadmap.