Skip to content
awesome-applied-ai
← Design problems

18Orchestration & Protocols

Compensation when an agent fails mid-flight

An agent with write access to CRM, billing and email failed after step 3 of 5. It had already issued a refund and sent a customer notification. What should the architecture have been?

The constraint. Agents perform side effects in external systems that share no transaction boundary. There is no rollback. You cannot unsend an email, and a refund reverses only as a new business decision.

Classify every tool at registration time, not at failure time.

ClassExampleCompensation
ReversibleCRM field updateRestore the prior value, captured before the write
CompensableRefundA counter-transaction, which is a business decision with its own approval
IrreversibleEmail sent, payment settled, message postedNone. Only prevention and escalation

The main design lever is ordering, and it is free. Do all reversible work first, checkpoint, and commit the irreversible tail last. Most agent workflows can be reordered this way and most are not, purely because nobody classified the tools. In the stated failure, sending the email before the workflow completed was the error, not the failure itself.

Then, in order of cost.

  1. 01Two-phase the irreversible actions. Prepare, then commit. A failure between phases leaves a draft rather than a sent message and a pre-authorization rather than a settlement.
  2. 02Idempotency keys on every write. Retry is the default recovery, and without keys retry means a second refund. This is now sharper under MCP revision 2026-07-28, which removed SSE resumability — a broken stream means re-issuing the request with a new request ID, so the server side must deduplicate or you will double-execute.
  3. 03Capture prior state before every reversible write. Compensation for a field update requires the old value, and it is unavailable after the fact.
  4. 04Human escalation is a legitimate compensation. For the irreversible-and-failed case, open a ticket carrying full workflow state. Attempting automated repair on an irreversible action is how one incident becomes two.

Never let the model author the compensation. Asked to fix its own failure, it will invent a plausible remedy and execute it. Compensations are code, registered alongside the tool, reviewed like any other write path.

Stack. Temporal — sagas, compensation handlers, durable state and deterministic replay are precisely its purpose, and this problem is the canonical case for it. Restate as the lighter alternative. Building this on a queue and a state table means reimplementing Temporal without its testing story.

Where answers fail. Proposing a try/except around the agent loop. The failure is not the exception; it is the three completed side effects in three systems that do not know about each other.