DevelopmentFramework14 min readPublished July 26, 2026

Three reversibility tiers · checkpoints, sagas & idempotency keys · where rollback ends

Agent Rollback and Checkpoint Patterns: An Engineering Reference

When an autonomous agent makes a mistake, “undo” means three very different things depending on where the mistake landed. File edits are cheap to reverse. Database writes need hand-coded compensating transactions. And a sent email, a captured payment, or a record pushed to a partner CRM cannot be rolled back at all — only prevented. This reference maps each tier to the named pattern that actually covers it.

DA
Digital Applied Team
Senior strategists · Published Jul 26, 2026
PublishedJul 26, 2026
Read time14 min
Sources8 primary docs
Reversibility tiers
3
filesystem · database · external
Checkpoint retention
100
most recent per session
30-day auto-clean
GuardFall bypass
10/11
open-source agents defeated
disclosed Jun 30
Stripe key retention
24h
minimum, then key expires

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.

Key takeaways
  1. 01
    Undo 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.
  2. 02
    Shipping 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.
  3. 03
    Sagas 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.
  4. 04
    Isolation 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.
  5. 05
    For 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.

01The 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.

Tier 1
Filesystem
cheap · fully reversible

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.

checkpoints · git · worktrees
Tier 2
Database
compensable · hand-coded

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.

sagas · outbox · event sourcing
Tier 3
External side effects
often irreversible

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.

gates · dry-run · idempotency

02Filesystem 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.

Retention
Checkpoints per session
100

File snapshots are kept for the 100 most recent checkpoints per session; checkpoints and their sessions auto-clean after 30 days, configurable via cleanupPeriodDays.

30-day auto-clean
Restore actions
Independent /rewind modes
4

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.

code · chat · both · summary
Blind spots
What rewind won’t catch
3

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.

bash · subagents · links

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.

03IsolationWorktree 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.

Isolation is not a guarantee
GuardFall, disclosed June 30, 2026 by Adversa AI, defeated command filters in 10 of 11 open-source coding and computer-use agents tested — only Continue defended — via a shell-interpretation bypass class. It carries no CVE because it is a design-convention failure, not a patchable bug. Treat worktrees, sandboxes, and command filters as mitigations with documented gaps, never as an airtight boundary that makes rollback planning optional.

04Database 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.

05Outbox & 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.”

The replay trap, in Fowler’s words
“Things will go wrong because those external systems don’t know the difference between real processing and replays.” A replayed agent run that re-executes its tool-call log will re-send every email and re-fire every webhook in it — unless every external call is wrapped in a gateway that knows it’s a replay. This is the single most common way a well-intentioned recovery mechanism causes the double-execution it was built to prevent. The same at-least-once logic governs background jobs and queues.

06External 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.

Key retention
Minimum key lifetime
24h

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.

then treated as new
Key length
Maximum key size
255chars

Stripe recommends V4 UUIDs or comparably random strings — and never embedding customer PII in the key itself.

V4 UUID recommended
Scope
Only POST is covered
POST

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.

param mismatch = error

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.

07The 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 reversibility matrix mapping each class of agent side effect to its reversibility, native undo mechanism, required control, and failure mode if unhandled, grouped by filesystem, database, and external tiers.
Side-effect classReversibilityNative undoRequired controlFailure if unhandled
Tier 1 · Filesystem
File edit via agent editor toolsFully reversibleCheckpoint restore (/rewind) · gitSession checkpoints + git as permanent historyLost session work
File change via shell command (rm, mv)Reversible only via gitNone in checkpoint scope — bash untrackedCommit-per-step · isolated worktreeSilent local data loss
Git commit on an agent branchFully reversiblegit revert · branch deleteWorktree isolation (watch submodules + git-redirect escapes)Polluted shared history
Tier 2 · Database
Row insert / updateCompensableSaga compensating transaction (hand-coded)Per-step compensations · idempotent post-pivot retriesInconsistent cross-service state
Row deleteCompensable only if prior state was capturedRe-insert from captured prior stateSoft delete or capture-before-delete + sagaPermanent data loss
Outbox message, not yet relayedFully reversibleDelete the outbox row in-transactionTransactional outboxLost or phantom events (commit-then-send gap)
Tier 3 · External side effects
Webhook delivered to a third partyIrreversibleNoneSignature verification · idempotency keys · approval gateDuplicate downstream processing
Email / SMS sentIrreversibleNoneApproval gate before send · dry-run previewUnrecallable message to a real recipient
Payment capturedIrreversible (a refund is a new transaction, not an undo)NoneIdempotency key + atomic reservation · approval gateDouble charge
Record pushed to a partner CRMIrreversible (partner owns the state)NoneDry-run / simulate mode · idempotency key · approval gateOrphaned 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.

08Design 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.
Local code work
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.

Checkpoints + worktree + commit-per-step
Cross-service writes
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.

Orchestrated saga + compensations
Messages & events
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.

Transactional outbox + idempotent consumers
Irreversible actions
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.

Approval gate + dry-run + idempotency key

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.

09ConclusionDesign for the tier, not for the fantasy of universal undo.

The engineering posture, July 2026

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.

Build agents you can actually trust

Some side effects can never be rolled back — the engineering is knowing which ones.

Our team designs agent systems with rollback, checkpointing, and irreversibility controls built in from the first tool call — sagas, outboxes, approval gates, and idempotency done properly, delivered in days not quarters.

Free consultationExpert guidanceTailored solutions
What we work on

Agent reliability engagements

  • Side-effect audits — classify every tool call by tier
  • Saga + compensation design for multi-system tasks
  • Approval-gate and dry-run policy implementation
  • Idempotency-key and outbox architecture reviews
  • Checkpoint/resume design for long-running agents
FAQ · Agent rollback patterns

The questions we get every week.

The three tiers are defined by where an agent’s side effect lands. Tier 1 is the filesystem: edits inside a working tree, cheaply reversible via session checkpoints, git, and worktree isolation. Tier 2 is the database: rows written across services, reversible only through explicitly coded compensating transactions (the saga pattern), the transactional outbox, and event-sourcing replay. Tier 3 is external side effects: a sent email, a captured payment, a delivered webhook, a record pushed to a partner CRM — actions no mechanism can take back once a third party has seen them. The frame matters because the tiers don’t interchange: most agent-rollback failures come from applying a Tier 1 assumption (something will snapshot this) to a Tier 2 or Tier 3 action, where no snapshot can help.
Related dispatches

Continue exploring agent engineering.