Agent rollback and checkpoint patterns are the difference between an autonomous agent you can trust with real work and one you babysit. The uncomfortable truth this reference is built around: there is no universal undo. Some side effects reverse cleanly, some can only be compensated, and some — a sent email, a captured payment, a webhook delivered to a third party — cannot be taken back by any mechanism that exists.
Why this matters now: agents in 2026 routinely touch three state layers in a single task — the filesystem they edit, the database behind the product, and external systems reached through tool calls. Each layer has its own mature rollback literature (git and session checkpoints; sagas and the transactional outbox; idempotency keys and approval gates), but the sources document each pattern in isolation. Saga write-ups never mention git checkpoints; harness docs never mention compensating transactions.
This reference stitches them into one frame: three reversibility tiers, each demanding a different class of control. We cover what a shipping checkpoint system actually captures (and its documented blind spots), how sagas and the outbox pattern handle database state, why the external tier has no undo at all, and a side-effect-by-side-effect matrix mapping each class to its required control.
- 01Undo has three tiers, and they don’t interchange.Filesystem changes are cheaply reversible via checkpoints and git. Database writes need explicitly coded compensating transactions. External side effects — email, payments, webhooks, partner CRM records — are frequently irreversible, full stop.
- 02Shipping checkpoint systems have documented blind spots.Claude Code snapshots code before every prompt and retains the 100 most recent checkpoints per session — but bash-command changes, subagent edits, and symlinked paths sit outside what /rewind restores. Its own docs call checkpoints ‘local undo’, not version control.
- 03Sagas have a formal point of no return.Microsoft’s saga guidance names the pivot transaction: once it succeeds, compensation is no longer valid and every later step must be retried forward to completion. Rollback design is really about knowing where your pivot sits.
- 04Isolation is a mitigation, not a guarantee.Git worktrees are the dominant agent-isolation primitive, but git’s own docs warn against multiple checkouts of submodule superprojects, and GuardFall defeated command filters in 10 of 11 open-source agents tested — with no CVE, because it’s a design-convention failure.
- 05For irreversible actions, the only controls run before the action.Approval gates, dry-run modes, transactional outboxes, and idempotency keys don’t undo anything — they make the irreversible step deliberate, previewable, and safe to retry without double-executing. That’s the whole toolbox.
01 — The FrameThree tiers of undo, three classes of control.
Every tool call an agent makes lands in one of three places, and the place determines what “rollback” can even mean. Inside the sandbox — the working directory, the branch — undo is a solved problem. One layer out, in the application database, undo becomes an engineering project: each write needs a semantically matching compensating write, designed in advance. One layer further, past the API boundary, undo stops existing. The receiving system has its own state, its own users, and no obligation to forget what it saw.
Most rollback failures in agent systems trace to a tier confusion: treating a database write like a file edit (assuming something will snapshot it), or treating an external call like a database write (assuming a compensation exists). The three-tier frame below is the corrective.
Filesystem
Edits inside the working tree. Session checkpoints, git commits, and branch isolation make this tier nearly free to reverse — with specific, documented exceptions covered in section 02.
Database
Rows written across one or more services. No automatic rollback spans the whole task — the saga pattern demands an explicitly designed compensating transaction per step, plus outbox discipline for anything that publishes events.
External side effects
Email sent, payment captured, webhook delivered, record pushed to a partner system. Nothing un-sends these. The only real controls run before the action: approval gates, dry-run modes, idempotency keys.
02 — Filesystem TierWhat a shipping checkpoint system actually captures.
The most instructive filesystem-tier example is one you can check against live documentation: Claude Code’s checkpointing. Per its docs, the harness automatically captures a checkpoint — the code snapshot, not just the conversation — before every user prompt, and /rewind can return the session to a prior file state without touching git. Crucially, the design treats “undo the chat” and “undo the files” as separable: four independent restore actions cover code and conversation together, conversation only, code only, or a context-compressing summary that touches no files at all.
The retention envelope is explicit: file snapshots for the 100 most recent checkpoints per session, with checkpoints and their sessions auto-cleaned after 30 days (configurable via cleanupPeriodDays). And the docs draw the boundary themselves — “Checkpoints are designed for quick, session-level recovery... Think of checkpoints as ‘local undo’ and Git as ‘permanent history.’” Checkpoints are not a version-control replacement, and the vendor says so.
Checkpoints per session
File snapshots are kept for the 100 most recent checkpoints per session; checkpoints and their sessions auto-clean after 30 days, configurable via cleanupPeriodDays.
Independent /rewind modes
Restore code and conversation, conversation only, code only, or summarize without touching files. Since v2.1.191 (June 24, 2026), /rewind can also resume a conversation from before /clear was run.
What rewind won’t catch
Bash-command changes (rm, mv, cp via a shell tool), subagent edits (except foreground-forked skills, which edit the working tree during the invoking turn and are captured), and symlinked or hard-linked paths all sit outside checkpoint restore scope — each documented by the vendor itself.
The blind spots matter more than the feature list, because they define what your agent can destroy without a session-level undo. First: checkpointing does not track file changes made by bash commands — a rm or mv executed through a shell tool is invisible to it; only edits made through the harness’s own file-editing tools are captured. Second: edits a subagent applies land outside the parent session’s checkpoints — with the exception of foreground-forked skills, which edit the working tree during the invoking turn and are captured — so a background fix-up run is not reversible from the parent’s /rewind. Third: as of v2.1.216 (July 20, 2026), a code restore skips any tracked path that is a symlink or hard link and warns, rather than silently writing through the link as earlier versions did.
The engineering lesson generalizes to any harness you build: a checkpoint system is defined by its exclusions. If the snapshot layer only sees one class of mutation (editor-tool writes) and the agent has access to a second class (shell commands), the second class needs its own control — typically commit-per-step git discipline, so that permanent history catches what session undo cannot.
03 — IsolationWorktree isolation — and its documented escape routes.
The second filesystem-tier control is isolation: don’t let the agent touch the checkout you care about in the first place. Git worktree is the dominant primitive here — per git’s official documentation, a repository can check out more than one branch at a time into separate directories that share a single .git object store. Linked worktrees share refs but keep private per-worktree state (HEAD, the index), which is exactly the shape you want for running an autonomous agent against its own branch: full repo access, zero contact with your working copy, and rollback that costs one branch delete.
Two caveats keep this honest. Git’s own docs state the boundary condition plainly: “Multiple checkout in general is still experimental, and the support for submodules is incomplete. It is NOT recommended to make multiple checkouts of a superproject.” On submodule-heavy repos, naive worktree-per-agent isolation breaks. And isolation leaks when the agent can redirect git itself outside the sandboxed directory — Claude Code’s v2.1.216 release closed exactly this class of escape, where a worktree-isolated subagent could point git at the shared checkout via git -C, --git-dir, or the GIT_DIR/GIT_WORK_TREE environment variables. The same release closed a symlink escape in scheduled and workflow writes. We cover the full escape taxonomy in our companion piece on agent sandbox escapes.
04 — Database TierSagas: rollback you have to write yourself.
The moment an agent task spans more than one database — or a database plus an API plus a repo — no single ACID transaction can cover it. The canonical answer is the saga pattern: break the business transaction into a sequence of local transactions, each completing atomically within one service and triggering the next step via an event or message. The catch is what happens on failure. There is no automatic rollback. Each compensating action must be designed and coded explicitly, per step, in advance — that is the core engineering cost of the pattern, and it is exactly the cost teams skip when they assume “the framework handles it.”
"If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions."— microservices.io, Saga pattern
Microsoft’s saga guidance adds the concept that matters most for agent design: the pivot transaction, the formal point of no return. After the pivot succeeds, compensating transactions are no longer valid — “irreversible or noncompensable transactions can’t be undone or retried” — and every subsequent step must be pushed forward to completion rather than undone. Those post-pivot retryable steps must be idempotent, which is where the saga literature hands off directly to the idempotency-key discipline in section 06. For an agent, the design question becomes: which tool call in this task is the pivot? Every call before it needs a compensation; every call after it needs a safe retry.
Two coordination models exist: choreography, where services react to each other’s events with no central controller, and orchestration, where a central orchestrator directs each step and handles compensation. Orchestration trades a single point of failure for traceability — a trade that usually favors agents, because the orchestrator is literally the coordinating agent, and its step log is your audit trail. Microsoft’s guidance also names the concurrency anomalies sagas invite (lost updates, dirty reads, fuzzy reads) and their countermeasures (semantic locks, commutative updates, pessimistic views, rereading values, version files) — plus a risk-based rule of thumb: sagas for low-risk changes, distributed transactions where the stakes justify them.
05 — Outbox & ReplayThe outbox, event sourcing, and the replay trap.
Two more database-tier patterns complete the kit. The transactional outbox solves the “commit then send” gap: if a service updates a row and then publishes an event as two separate operations, a crash between them loses the message. The fix is to store the outgoing message in the same local database transaction as the business-entity update — in microservices.io’s words, “the solution is for the service that sends the message to first store the message in the database as part of the transaction that updates the business entities.” A separate relay (a polling publisher or transaction-log tailing) publishes what’s in the outbox table later. For rollback purposes the outbox has a bonus property: a message still sitting in the outbox is Tier 2 state — deletable, fully reversible. The same message after relay is Tier 3 — gone.
Event sourcing is the resume-side pattern: capture all state changes as an ordered sequence of events rather than persisting only current state. That allows full rebuild by replaying the log from empty, and reconstruction of state at any historical point — the mechanism a checkpoint/resume design borrows for “resume mid-task instead of restart.” Martin Fowler’s original write-up also names its sharpest edge, which happens to be exactly the edge agents live on: replaying events against external systems. His mitigation — wrap every external call in a gateway that can distinguish a live run from a replay — is precisely the boundary an autonomous agent’s tool calls cross dozens of times per task. His caveat on snapshotting cuts the same way: caching computed state so you don’t replay from the beginning is a performance optimization with its own infrastructure cost, which is the same trade-off as “how often should an agent checkpoint.”
06 — External TierThe irreversible class: no undo exists.
Now the tier this reference exists for. A sent email. A captured payment. A webhook delivered to a third party. A record pushed into a partner’s CRM. These are not “hard to reverse” — they are a separate, non-overlapping category from difficult database state. The receiving system saw the action, and nothing you run on your side changes that. A refund is a new, compensating transaction — a second visible event — not an undo. Once that’s accepted, the control set clarifies: everything that works runs before or around the action, never after.
Idempotency keys make retries safe. Stripe’s implementation is the canonical public reference: a client-generated key in the Idempotency-Key header lets a retried POST return the cached result of the original attempt instead of re-executing it — including replaying a cached 500 error, so a caller must actively generate a new key to intentionally retry after a genuine failure. Keys are retained for a minimum of 24 hours, capped at 255 characters, accepted on POST only (GET and DELETE are idempotent by definition), and a reused key with different parameters returns an error rather than silently executing the new call. One honest limit: a key alone does not guarantee exactly-once execution. As standard engineering practice has it — corroborated by Stripe’s own atomic-check behavior — the key must be checked and claimed atomically (a unique constraint, a compare-and-set, an operation-id table), or two concurrent retries can both slip past the check and both execute. We go deeper in our webhook reliability and idempotency reference.
Minimum key lifetime
Stripe retains idempotency keys for at least 24 hours; after that, a reused key is treated as a brand-new request. Retry windows longer than a day need their own dedup layer.
Maximum key size
Stripe recommends V4 UUIDs or comparably random strings — and never embedding customer PII in the key itself.
Only POST is covered
GET and DELETE are excluded as already idempotent. A retried request whose parameters differ from the original call on the same key returns an error, never a silent execution.
Approval gates put a human (or a stricter policy) between the agent and the pivot. The gate belongs at the tier boundary: an agent can draft freely, stage database writes behind a saga, queue messages into an outbox — and then stop for approval exactly once, where the task crosses into Tier 3. Our approval-gate framework covers gate placement in depth. Dry-run modes are the complementary control: execute the full plan with external calls simulated, inspect the would-be side effects, then re-run live. And “verify before you act” is now shipping in agent harnesses themselves — Amp’s event-driven orbs (July 23, 2026) verify inbound webhook requests by cryptographic signature and validate payloads before spawning a thread with trusted metadata, with Amp’s docs stating plainly that “webhook URLs function as credentials.” Which is the adjacent problem: irreversible-action control assumes you know who is acting — the subject of our companion playbook on giving agents their own identity.
This tier is where most business risk concentrates, because it’s where agents touch customers and partners. If your agents write into a CRM that sales teams and partner systems read from, the dry-run-then-gate sequence isn’t optional hygiene — it’s the control that stands between an agent bug and a duplicate record in someone else’s system of record. It’s the pattern we implement first in CRM automation engagements.
07 — The MatrixSide-effect reversibility matrix.
The table below is the reference card this post exists to provide — original synthesis, because no single source publishes this cross-tabulation. Saga documentation doesn’t mention git checkpoints; harness docs don’t mention compensating transactions. Every cell is grounded in the named, documented mechanisms cited above. Read it row by row before designing any agent task that writes anywhere.
| Side-effect class | Reversibility | Native undo | Required control | Failure if unhandled |
|---|---|---|---|---|
| Tier 1 · Filesystem | ||||
| File edit via agent editor tools | Fully reversible | Checkpoint restore (/rewind) · git | Session checkpoints + git as permanent history | Lost session work |
| File change via shell command (rm, mv) | Reversible only via git | None in checkpoint scope — bash untracked | Commit-per-step · isolated worktree | Silent local data loss |
| Git commit on an agent branch | Fully reversible | git revert · branch delete | Worktree isolation (watch submodules + git-redirect escapes) | Polluted shared history |
| Tier 2 · Database | ||||
| Row insert / update | Compensable | Saga compensating transaction (hand-coded) | Per-step compensations · idempotent post-pivot retries | Inconsistent cross-service state |
| Row delete | Compensable only if prior state was captured | Re-insert from captured prior state | Soft delete or capture-before-delete + saga | Permanent data loss |
| Outbox message, not yet relayed | Fully reversible | Delete the outbox row in-transaction | Transactional outbox | Lost or phantom events (commit-then-send gap) |
| Tier 3 · External side effects | ||||
| Webhook delivered to a third party | Irreversible | None | Signature verification · idempotency keys · approval gate | Duplicate downstream processing |
| Email / SMS sent | Irreversible | None | Approval gate before send · dry-run preview | Unrecallable message to a real recipient |
| Payment captured | Irreversible (a refund is a new transaction, not an undo) | None | Idempotency key + atomic reservation · approval gate | Double charge |
| Record pushed to a partner CRM | Irreversible (partner owns the state) | None | Dry-run / simulate mode · idempotency key · approval gate | Orphaned or duplicate partner records |
Two reading notes. First, the outbox row is the hinge of the whole table: it is the last moment a would-be external side effect is still fully reversible, which is why the outbox pattern earns its place in agent architecture far beyond its microservices origins. Second, “required control” is cumulative down the table — a payment-capturing agent still needs the filesystem and database controls above it, because a task that can’t be resumed cleanly (Tier 1–2 failure) is a task that gets retried blindly, and blind retries are how Tier 3 disasters happen.
08 — Design GuideCheckpoint design: persist the tool-call log, not just final state.
If you’re building checkpointing into your own agent system, the single most consequential decision is what you persist. Snapshotting final state tells you where the agent ended up; persisting the ordered tool-call log — inputs, outputs, timestamps, and which tier each call touched — tells you how it got there, which is what resume actually requires. This is event sourcing’s core insight applied to agents: the log is the source of truth, and any state snapshot is a derived optimization.
A concrete design checklist, each item traceable to a pattern above:
- Checkpoint before every step, not every task. The shipping precedent (a snapshot before every user prompt) exists because mid-task granularity is what makes resume-mid-task possible. Restarting a 40-step task from step 1 re-executes 39 side effects.
- Record the tier of every tool call. On resume, Tier 1 calls can be re-run freely, Tier 2 calls need their saga state consulted, and Tier 3 calls must never re-execute without their idempotency key — Fowler’s replay gateway, expressed as a resume policy.
- Attach idempotency keys at plan time, not call time. If the key is generated when the step is planned and persisted in the checkpoint, a crashed-and-resumed agent retries with the same key and gets the cached result instead of a second execution.
- Mark the pivot explicitly. Before the pivot, failure means run compensations backward. After it, failure means push retries forward. An agent that doesn’t know where its pivot is can’t choose correctly.
- Log for audit, not just recovery. The same tool-call log that powers resume powers accountability — our agent audit-trail design guide covers the schema.
Agent edits inside a repo
Session checkpoints for fast local undo, an isolated worktree per agent, commit-per-step so shell-command changes have permanent history even where checkpoints are blind.
Repo + database + API in one task
No single transaction spans the task. Orchestrated saga with hand-coded compensations per step, an explicitly marked pivot, and idempotent retries after it.
Anything the task must publish
Write the message in the same transaction as the business update; let a relay publish it. Queued-but-unrelayed messages stay fully reversible — the last cheap undo point.
Email, payments, partner CRM
No undo exists. Gate the step behind approval, preview it with dry-run mode, and attach an idempotency key at plan time so a retry can never double-execute.
The forward-looking read: through 2026, checkpoint-and-resume has been moving from bespoke agent-framework code into the harnesses and platforms themselves — session checkpointing shipping as a default, isolation escapes being patched at the harness level, event-driven triggers arriving with signature verification built in. We expect that direction to continue, and it changes where engineering effort should go: less on rebuilding Tier 1 undo, more on the parts no platform can generalize — your compensation logic, your pivot placement, and your approval-gate policy, because those encode business semantics only your team knows. Mapping those controls onto real workflows is core to our AI transformation engagements.
09 — ConclusionDesign for the tier, not for the fantasy of universal undo.
Rollback is a property you design in, tier by tier — never a feature you get for free.
The patterns in this reference are old by software standards — sagas, outboxes, idempotency keys, and event logs all predate autonomous agents. What’s new is the forcing function: an agent crosses all three reversibility tiers in a single task, at machine speed, without a human pausing to ask “can I take this back?” before each step. The tier frame answers that question structurally instead of per-step.
The honest summary: filesystem undo is cheap and largely solved, with blind spots you must know (shell commands, subagent edits, symlinks). Database undo is real but never free — every compensating transaction is code someone writes, and every saga has a pivot past which there is no going back. External side effects have no undo at all, and pretending otherwise is how agents double-charge customers and orphan records in partner systems. Approval gates, dry-run modes, the outbox, and idempotency keys aren’t optional add-ons — they are the only mitigations that exist for that tier.
Start with the matrix in section 07. Classify every tool call your agent can make into a tier, verify each row’s required control exists in your stack, and mark the pivot in every multi-step task. That exercise takes an afternoon, and it converts “we think the agent is safe to run unattended” into a claim you can defend line by line.