Rollback Strategies for Agents That Changed Things
An agent stopped halfway through eleven changes. Checkpoints, compensating actions, staging areas and the undo plan you should require before it acts.
The agent was asked to migrate a module. It edited seven files, ran a migration, updated a config, called a deployment endpoint, and then hit a rate limit and stopped.
Nothing crashed. There is simply no longer a coherent state to be in — the code expects the new schema, the config points somewhere half-real, and the deployment is in a state that matches neither. Someone now has to work out what happened and undo the right subset by hand.
Undo is not a feature you add after an incident. It is a constraint on how the agent is allowed to act in the first place, and the systems that recover well are the ones that decided this before writing the first tool.
Make actions reversible before you make them recoverable
The cheapest rollback strategy is not needing one. Before building compensation machinery, ask whether the action can be made naturally undoable.
Work in a branch rather than the main line. Write to a new version rather than overwriting. Create a draft rather than publishing. Soft-delete rather than deleting. Each of these turns rollback from a procedure into a pointer change, and pointer changes do not fail halfway.
Where reversibility is impossible — a sent email, a charged card, an external API call with no undo — that is exactly the boundary worth gating. An agent that can do eleven reversible things and one irreversible one should need confirmation for the one, which is the practical core of human-in-the-loop design.
Checkpoints and the working copy
For filesystem work, version control is the rollback mechanism and you should lean on it rather than reinventing it. Commit before the agent starts, let it work on a branch, and discard the branch if the run fails.
Checkpoint between logical phases rather than every step. A checkpoint per step is expensive and produces a history nobody can read; a checkpoint per phase gives you meaningful restore points that correspond to states a human would recognise.
Record what the agent believed at each checkpoint alongside the state — the objective, the plan, the step it was on. Restoring files without restoring the reasoning gives you a directory you cannot interpret, and the same argument applies to resuming, since a resumed agent needs the reasoning more than it needs the diff.
Isolation makes all of this easier. An agent working in its own worktree or container can be discarded wholesale, which is one of the practical benefits of agent sandboxing beyond the security case.
Compensating actions
When state lives outside your control, rollback means doing something new that reverses the effect rather than restoring a snapshot. Refund the charge, delete the created record, send the correction.
Every mutating tool should ship with its compensator defined at the same time, in the same place. If nobody can name the undo when the tool is written, nobody will invent it during an incident.
Compensators can fail too, which is the part people forget. They need their own retries, their own logging, and an escalation path when they exhaust it. A failed compensation is a state that requires a human, and it should page rather than log.
Order matters: compensate in reverse. Undoing step two before step three is how you end up in a state neither the forward nor the backward path anticipated. Keep an explicit stack of completed actions with their compensators and unwind it, which also depends on those compensators being safe to repeat — see idempotency in agent actions.
Stage, then commit
Often the best answer is to stop the agent from touching live state at all. Let it build a complete proposal — a diff, a set of records, a plan — and apply the whole thing in one controlled step at the end.
This collapses eleven partial-failure windows into one, and the single application step is code you wrote, which can be transactional in a way an agent loop cannot. A run that dies mid-way leaves nothing but an abandoned proposal.
It also gives you a natural review point. A staged change can be inspected by a human, or by a reviewing agent with fresh context, before anything real happens. That check is far more valuable than the same review applied after the fact.
The trade-off is honest: staged work cannot observe the effects of its own changes, so tasks whose next step depends on the result of the previous one do not fit. That is the case for keeping the loop live and paying for real rollback machinery.
Deciding when to roll back
Not every failure warrants an unwind. Rolling back a run that failed on step ten of eleven can discard a large amount of correct, expensive work.
The test is whether the completed steps are independently valid. Seven files correctly refactored are useful even if the eighth failed; a half-applied schema migration is not useful at all. Independently valid work should usually be kept and flagged, not reverted.
Where it is not independently valid, unwind promptly and completely. The worst outcome is a partial rollback that leaves the system in a third state, distinct from both start and finish, which is exactly what ad hoc manual recovery tends to produce. The classification work in partial failure recovery is what makes this call quickly.
Whatever you decide, record the decision and the resulting state. An incident where nobody can say whether the rollback completed is worse than one where it visibly did not.
Do not let the agent run its own rollback unsupervised
An agent that has just failed is not the most reliable actor to perform recovery. It may be confused about what it did, its context may be full of the failure, and its record of completed actions may already have been compacted.
Drive rollback from the action log, in code, not from the model's recollection. The log is the source of truth about what happened; the agent's summary is a lossy account of it. This is one of the strongest practical arguments for logging every tool call with its arguments and result, as agent observability and tracing sets out.
Where judgement is genuinely needed, give a fresh agent the action log and ask it to propose an unwind plan for a human to approve. That is a very different task from asking the failed agent to fix itself.
The requirement to adopt
Before any agent is allowed to mutate anything, require an answer to one question: how does this get undone, and who runs the undo? If the answer is that a human will work it out from the logs, the logs had better be good enough — and if they are, you are most of the way to automating it anyway.
Prefer naturally reversible actions, stage where you can, define compensators alongside the tools that need them, and drive the unwind from the log rather than the model. That set of habits turns a failed run into an inconvenience rather than an afternoon of forensic archaeology.
Common questions
Should an agent always roll back after a failure?
No. If the completed steps are independently valid, keeping and flagging them preserves expensive correct work. Unwind when the partial state is incoherent, such as a half-applied migration, and unwind completely rather than partially.
What is the simplest rollback mechanism for coding agents?
Version control. Commit before the run, work on a branch, discard the branch on failure. Combined with an isolated worktree or container it makes rollback a pointer change rather than a procedure that can itself fail.
Can the agent perform its own rollback?
Drive it from the action log in code rather than from the model. An agent that just failed may be confused about what it completed, and its record of early actions may already have been compacted out of context.