agent·interface

Undo for agents: reversibility as the safety net

Undo for agents: reversibility as the safety net

An approval gate asks permission before an action happens. Undo is what you fall back on when the gate opened for something that turned out to be wrong anyway — a bad diff, a rushed refactor, a step the agent decided on its own. Both matter, but they get very different amounts of attention. Most teams building agent products spend weeks on the approval prompt and almost no time on what happens after someone clicks yes and regrets it.

That's changing, mostly because coding agents ran into the problem first. If an agent can edit forty files in one turn, "are you sure?" isn't much of a safety mechanism — the human can't meaningfully evaluate forty files before approving. What they can evaluate is the result, and revert it if it's wrong. That's the whole argument for undo as a primitive: it moves the safety check from before the action to after, where it's actually tractable.

What undo means for a software agent

For a person, undo is one keystroke because there's one linear history. For an agent, "undo" has to answer three separate questions: undo the file changes, undo the conversation that led to them, or undo both? Do you undo to a point in time, or past a point, keeping some later changes? And critically — does undo cover only what the agent's own tools touched, or everything that happened while it was running, including a shell command it ran on the side?

Every product answers these slightly differently, and the differences tell you a lot about where each one draws its safety boundary.

Three products, three implementations

Claude Code's checkpointing captures a file-state snapshot before every user prompt; pressing Esc twice opens a menu to restore code, conversation, or both, and checkpoints survive a session restart, cleaned up after 30 days by default (Claude Code docs). The same docs are unusually candid about the edges: checkpointing only tracks edits made through Claude's own file-editing tools, so a rm or mv run via bash isn't undone by rewinding, and edits a background subagent makes land outside the session's checkpoints entirely — you're back to git for those.

Cursor's checkpoints work on the same principle — automatic snapshots before agent edits, restorable from the chat timeline — but keep the store deliberately separate from git history so experimental agent runs don't clutter your commit log, retaining the 100 most recent snapshots per session with a configurable cleanup window (Cursor docs). Like Claude Code, it only captures agent-made edits; changes you make by hand aren't part of the undo chain.

Replit goes further because its agent operates a whole environment, not just files. A checkpoint snapshots code, project configuration, and the AI conversation context together, and rollback uses git underneath to revert the code; a database rollback is available but off by default, since reverting a database has consequences a file revert doesn't (Replit docs). Replit also supports rolling forward again if you undo too far — treating the checkpoint history as a timeline you can move along in either direction, not just a single undo stack.

ProductUndo unitLives inCovers non-tool changes?
Claude Codecode, conversation, or bothsession store, 30-day cleanupno — bash-modified files and subagent edits are excluded
Cursoragent-made file editslocal store, separate from gitno — manual edits aren't tracked
Replitcode + conversation + optional DBgit-backed, roll forward supporteddatabase only if explicitly opted in

The pattern across all three: undo is scoped to what the agent's own tools did, on purpose. None of them try to be a general-purpose time machine for the whole environment, and all three explicitly point back to git or a database backup as the real safety net for anything outside that scope.

The framework layer treats it as a primitive, not a feature

One level down, LangGraph builds the same idea into the execution engine itself rather than the UI. A checkpointer snapshots the entire graph state at each step, and get_state_history exposes the full list of past checkpoints; from any of them you can replay — retry forward from that point — or fork, branching off with modified state to try a different path (LangGraph time-travel docs). It's the same restore-versus-branch distinction Claude Code offers through its /branch command, just exposed as an API instead of a keyboard shortcut. If you're building an agent on a framework rather than shipping a chat UI, this is the layer to build your own undo on top of, instead of reinventing snapshotting.

Where the idea comes from

The academic framing predates most of these products. A 2024 paper out of UC Berkeley's Gorilla project, GoEx, argued that verifying an LLM's proposed action after it runs is a much easier problem than trying to validate the plan beforehand, and proposed a runtime built around exactly two primitives: undo, and "damage confinement" — bounding how much an action can affect before it's reviewed (GoEx paper). The paper's core move was classifying actions by whether they're reversible at all, which is the same question every product table above is implicitly answering when it decides what to snapshot.

That classification has since been generalized into a tiering idea: instead of a binary reversible/not, sort actions into tiers — auto-execute the cheaply reversible ones, checkpoint the moderately reversible ones, and route anything irreversible to a human gate before it runs at all (tiered autonomy by reversibility). That's a more honest model than "undo covers it," because it admits some actions don't belong in the undo bucket in the first place.

What undo doesn't fix

The tiering framing points at the real gap: reversibility isn't a fixed property of an action, it's a property of an action plus everything that's happened since. A file revert is clean. A database row reverted to its old value is technically clean but not actually clean if another system already read the new value and acted on it — the state is back, but the consequences aren't. None of the checkpoint systems above touch that problem, and none claim to; it's why Replit ships database rollback as an explicit opt-in rather than a default, and why Windows' experimental Agent Workspace tries to shrink the blast radius up front — a low-privilege account with folder-scoped access — rather than promise to undo whatever happens inside it (Windows agentic features).

Undo is the right complement to an approval gate, not a replacement for one. The gate should still catch anything that can't be cleanly reversed; undo is what makes it sane to let an agent move fast on everything else.

More protocols and patterns like this are tracked at /tracker.


Tracking this space daily on the agent-interface tracker. Start at the hub if you're new to the term.