Guarded Automation: Agents That Run Operations Module 3 · Before and After

Compensate or Stop

Last reviewed · content updated

Intermediate

What you'll learn

~18 min
  • Tell apart three outcomes of a failed verification by their exit code: fully restored, restored except a declared cost, and no inverse at any price
  • Read a compensation receipt row and name what it adds that the original action's row does not
  • Explain why a standing deny is worth more in an audit than an action the agent simply never had

Before the detail — Decision: when verification fails, either run a declared inverse or refuse the action outright — never guess and never round a partial fix up to “fixed.” Outcome: a result that names exactly which of three things happened, with any cost that did not come back written down in units. Artifact: the compensation receipt, chained to the action it corrects. Status of what follows: binding.

Prompt first: is this action actually reversible, or just assumed to be?

For one action your automation can take unattended, answer three
questions before it runs again:
1. If verification fails after execution, does the target actually
HAVE an inverse for it, or are you assuming one exists because
the opposite verb sounds like it should work?
2. If the inverse runs, does it fully restore the prior state, or
does it cost something that does not come back - time, a
resource, a record? Name the cost in units, not "small" or
"minor."
3. Is there a version of this action for which the honest answer to
#1 is "there is no inverse at any price"? If so, name it and
stop treating it like the reversible ones.
Do not write "reversible" for any action whose inverse you have not
actually run against the real target at least once.

An assistant can draft this checklist and even propose candidate inverses. It cannot tell you whether cancel_the_thing has ever actually been executed against production, or whether it is a function name someone wrote and never called. The target owner supplies that evidence.

Three words, one committed proof

This training keeps three words apart that operations vocabulary usually mashes together, and each one has a command behind it rather than a definition. All three appear in one committed run, on three actions, with three different exit codes.

Reversible means the inverse restores the prior state completely. update_work_order_priority asks for P1; the work-management system clamps it to P2 and returns success anyway (3.2’s clamp pattern, on a different field); verification fails, the guard runs the declared inverse, and the state hash returns to exactly what it was before. Exit 5.

Compensable means the inverse runs and the world does not fully come back. pre_position_crew sends three crews to a feeder that already has three staged — the target declares this verb non-idempotent, because pre-positioning twice leaves six, not three. Verification fails, the guard runs recall_crew, and the transcript records exactly what happened: “3 crew(s) recalled from F-2291; 45 min of crew time spent, unrecoverable (45 min total).” The action receipt records compensated-with-residual-impact, and the compensation row links back with compensates_receipt_id; the current JSON rows do not quantify the 45-minute cost. Exit 6, compensated-with-residual-impact — a name chosen on purpose to be different from plain “compensated,” because a reviewer scanning a chain for cost should not have to open every row to find the ones that had any.

Irreversible means no inverse exists at any price. send_dispatch_notice reaches crew handsets; there is no unsend. The envelope declares its compensator as null and requires two named approvers on two distinct keys before the notice goes out at all — one approval is refused with exit 4, before anything irreversible happens, rather than after.

Compensation is declared, not automatic

Nothing about recall_crew running automatically follows from pre_position_crew existing; the pairing, and the fields the inverse is allowed to leave changed, are written into the policy file ahead of time. This is not a house invention: the underlying model — a compensating action is a real operation with its own effects, not a snapshot restore — comes from Garcia-Molina and Salem’s 1987 paper on sagas, which established that long-running actions in a system nobody can lock end-to-end get undone by running something, not by rewinding time.

That declared inverse also writes its own row. The original pre_position_crew attempt gets a receipt; the recall that follows it gets a second receipt, chained to the first and labeled as a compensation, with its own hash, its own timestamp, and its own outcome. An incident record built from this chain does not see one ambiguous entry that says “handled” — it sees the failed attempt and the correction as two separate, ordered facts, which is what “receipted where the agent cannot write” (M3’s thesis line) actually buys a reviewer during a later review: nobody has to take anyone’s word for what the fix was, because the fix is its own row.

This lesson owns reversal of one agent-initiated action, nothing broader. Cloud Modernization 4.3 (a separate training in this series) puts rollback before debugging, and DevSecOps 4.3 makes that rollback one person’s operation — both are rules for taking a release backward. Neither describes recall_crew, which corrects one action rather than a release.

When compensation itself fails

A fourth outcome exists, and it is not a variant of success: exit 8, compensation-failed. This is what the receipt records when the compensator itself errors, or when it leaves something changed that the envelope never declared as an acceptable residual, or when no inverse was declared for the action at all. Exit 6 and exit 8 look similar from a distance — both mean the original action did not simply work — but they are not the same claim. Exit 6 says: the world is fully known, and here is exactly what it cost. Exit 8 says: the world is now somewhere nobody planned for, and a human has to go look, not a retry loop.

Notice what none of this training ever states: a time target for how fast a compensation must complete. There is no promised duration anywhere in a receipt — only what happened and what it cost. A rollback that takes longer than expected but is fully declared and fully receipted is a known fact; a rollback rushed to hit a number is exactly the kind of unverified claim 3.2 built a postcondition to catch.

Stop and escalate when a receipt shows exit 8. Compensation-failed is not a state a retry resolves — the compensator errored, or the residual left behind was never declared as acceptable. Exit 8 routes to the on-call owner.

The action with no compensator at all

Some actions get neither a compensator nor an approval path — only a standing refusal. delete_backup is declared in the policy file as an outright deny, on purpose, rather than simply left out of the file. The reason is in the policy’s own comment: a declared deny produces a receipt that names the standing decision by its actual reason, where an omitted tool would just be denied by the generic default with no story behind it. “We decided this agent never does this” is a stronger line in an audit than “nothing matched” — it shows a decision was made, not that nobody thought to write the rule. That is the fourth word this training keeps apart from the other three: never-delegated actions carry no inverse to declare and no signer count to satisfy, because the answer was decided in advance and receipted every time it is asked for again.

KNOWLEDGE CHECK

MU-AI-011 (Meridian's crew-dispatch agent) pre-positions 3 crews at feeder F-2291 a second time, verification finds 6 rather than 3, and the guard recalls 3. What do the transcript and linked receipts show?

Key takeaway

The committed proof keeps the outcomes distinct: exit 5 restores the pre-state, exit 6 leaves a quantified residual in the transcript, and exit 4 refuses the irreversible action because only one of two required approvals was presented. Exit 8 is compensation-failed when the inverse errors or leaves an undeclared difference. The next lesson raises the stakes on that irreversible class: what it takes for two people, not one, to authorize the action that cannot be undone.

LEADERSHIP DECISION every action ships with one of four declared
outcomes before its first unattended run:
restore, restore-with-cost, no-inverse, or
never-delegated - never "we'll see"
PRACTITIONER ACTION for each compensable action, name its residual
fields in the policy file before deployment,
and route every compensation-failed receipt to
a human, not a retry
SUCCESS MEASURE every residual-impact receipt traces by run
and request id to a committed execution record
that quantifies the cost - assessor-hours
saved per reviewed incident
Search lessons