← All packs

Designing reversible actions for autonomous agents — undo, not just retry-safety

Idempotency answers "what happens if this call runs twice." It says nothing about a different question: what happens if the call was wrong the first time. A tool can be perfectly idempotent — calling it five times in a row does exactly what calling it once does — and still be irreversible, because the one call it made was the wrong one and there's no path back from it. Reversibility is a separate design property from retry-safety, and it's the one that determines how bad an agent's mistake is allowed to get before a human notices and steps in.

Prefer soft state changes to hard ones by default

A delete that flips a status flag and an actual DROP or rm produce the same visible result on the happy path and completely different outcomes when the agent acted on a wrong premise. Soft deletes, archive-instead-of-purge, and move-to-trash-instead-of-unlink cost almost nothing when the agent was right and buy back the entire mistake when it wasn't. The asymmetry only runs one way — a hard delete that turns out to have been correct saves you no more than a soft one would have — so the default should be the reversible form unless there's a specific reason (storage cost, compliance deletion requirement) that forces the irreversible one.

Snapshot before mutation, not after detecting a problem

By the time an agent's action is recognized as wrong, the pre-action state is usually already gone — overwritten, deleted, or superseded by whatever happened next. The only reliable time to capture it is immediately before the mutation, as a cheap, unconditional step baked into the tool itself: copy the file before overwriting it, tag the git commit before a force-push, export the row before an update. This is strictly cheaper than trying to reconstruct prior state forensically after the fact, and it's the mechanism that turns "we think this is what it looked like before" into "here is exactly what it looked like before."

Irreversible-by-default actionReversible equivalent
rm filemove to a timestamped trash directory, prune on a schedule
overwrite a config in placewrite new version alongside, symlink the active one
git push --forcepush to a new branch, or tag the old tip first
UPDATE ... SET with no backupwrite old row to an audit table in the same transaction

Make dry-run the thing the agent sees first, not an opt-in flag

A dry-run mode that exists but has to be deliberately requested gets skipped under the same pressure that causes mistakes in the first place — an agent moving fast on a plausible-looking plan has no built-in reason to reach for the safer path unless the tool design pushes it there. Tools for irreversible-leaning actions read better when the default call previews the effect and a second, explicit step commits it, rather than the reverse. This costs one extra round trip on the actions that matter and nothing at all on the ones that don't, since a preview of an already-correct action just confirms what was going to happen anyway.

Put the confirmation gate at the point of no return, not earlier

A gate placed too early — confirm before planning, confirm before reading — trains whoever approves it to click through without reading, because most of what's being confirmed at that point is harmless. A gate placed exactly at the last reversible moment, right before the action that can't be taken back, is the one point where a human's attention is both necessary and proportionate to the risk. Fewer, better-placed gates produce more real scrutiny than many gates scattered across every step, because reviewer attention is a limited resource that flat distribution wastes on the steps that didn't need it.

Reversibility is a property of the system, not a promise in the prompt

Telling an agent "be careful with destructive operations" in a system prompt is not a substitute for the underlying action actually being undoable — instructions shape behavior probabilistically, while a soft-delete flag or a pre-mutation snapshot works even on the run where the instruction gets missed. The same discipline that applies to designing tools safe to call twice applies here one level further: build the safety property into what the tool does, and treat any prompt-level caution as a second layer on top of it, never the only layer. When something does go wrong despite that, a full audit trail is what tells you which reversible path to actually take.

The test for whether an action is reversible: after it runs, can someone who wasn't watching restore the prior state without reconstructing it from memory or a different system entirely? If the honest answer is "only if we're lucky," the action needs a cheaper way back built into the tool, not a promise to be more careful next time.

Related: the same reversibility argument applies to how a change itself gets shipped, not just to what the agent does once live — see canary and shadow rollouts for agent changes for making the rollout mechanism itself fast to reverse.