Resumability Is Decided Before the Interruption, Not After It

A long-running agent will be interrupted. This is not an edge case to defend against at the margins; it is the ordinary weather of any task that runs long enough to matter. The process is killed by a deploy. A rate limit stalls a tool call past its timeout. A downstream service returns an error the agent cannot get past. A person pauses the run to look at something and comes back an hour later. Because the interruption is guaranteed, it is not where the design attention should go. What matters is what the agent has left when it comes back, and whether that remainder is enough to continue from where it stopped rather than starting over or getting stuck.

Resumability is the property that decides which of those happens. An agent has it when a saved point is enough to carry the task forward after an interruption: the finished work stays finished and is not redone, and the results that work produced are still in hand. That sounds like a recovery behavior, something the agent does after a failure, and framing it that way is the first mistake. Resumability is not a recovery you attempt after the interruption. It is a structure you commit to before it, because everything the agent will need to resume has to have been written to durable storage while the agent was still running normally. By the time the interruption arrives, the decision that determines whether the run is recoverable has already been made or missed. An agent whose progress lives only in the context it is reading loses that progress the instant the context is gone, and no cleverness at restart can reconstruct what was never persisted.

What “where it left off” actually requires

Picking up where a task stopped is a concrete requirement, not a vague one, and it decomposes into three things that must all be present when the agent restarts. There is position: a trustworthy record of which steps are finished and confirmed, so nothing already done gets run a second time. There are the live inputs the next step will consume, without which knowing the position buys nothing, because the agent can locate itself perfectly and still have nothing to act on. And there is the carried-forward output of earlier steps that later phases read, because a phase built on an upstream result is dead in the water when that result is gone, however exactly it understands where it sits.

Miss any one of the three and the agent is not merely slowed, it is stuck in a specific and costly way. Without the record of what completed, it either repeats finished work, which can fire side effects a second time, or it cannot tell what is safe to skip and restarts from the beginning to be sure. Without the next step’s inputs, it knows its position and can do nothing with it. Without the accumulated results, the position and the inputs are both intact and the work still cannot continue because its dependencies are gone. This is why resumability is a design obligation rather than a feature: it is the guarantee that all three are durably recorded before any interruption could plausibly land, and that guarantee has to hold continuously, at every point the run could stop, not just at the points a designer happened to anticipate.

Checkpoint at phase boundaries, not at every tool call

A checkpoint is a persisted snapshot of task progress taken at a defined point, and it is the mechanism that makes the three requirements durable. The design questions it raises are what to capture and when to capture it, and the useful answers pull against the instinct to be thorough.

What a checkpoint should hold follows directly from what resumption needs: an identifier for the phase reached and a count of the steps completed within it, so recovery knows where to land; the outputs of completed steps that later phases depend on, so those dependencies survive; and the original task inputs, so the full working context can be rebuilt rather than inferred. That is enough to reconstruct a known good state, and holding much more than that turns the checkpoint into a second copy of everything, with its own drift and its own maintenance cost.

When to write it is the sharper question, and the right default is coarser than most people reach for. A checkpoint belongs at the close of a major phase, once its work has settled, and not on the heels of every tool call. The temptation runs the other way, toward checkpointing after every step so that a failure loses as little as possible, and that instinct is worth resisting because it trades a rare cost for a constant one. Coarse checkpoints written at phase boundaries mean fewer writes, simpler state to reason about, and a recovery path that is easy to restore from. Their downside is real but bounded: a failure mid-phase forces the agent to redo the work done since the last boundary. For the large majority of workflows that redo is cheap enough to accept, and buying it down is not worth the standing complexity of fine-grained state.

Fine-grained checkpointing earns its cost only under specific conditions, and naming them keeps the decision honest. Three things move the needle: a step whose recomputation is genuinely costly, a step that reaches outside the agent and leaves a mark that must not be left twice, and a step landing in a system that offers no safe way to repeat the call. When a single step sends a payment or provisions a resource or mutates an external record, the cost of redoing it is not wasted compute, it is a wrong outcome in the world, and there the finer granularity earns its cost. Everywhere else, coarse is the better engineering, and the discipline is to add the finer state only where a concrete step forces it rather than as a blanket policy that makes every run slower to protect against a case that does not apply.

The checkpoint has to precede the irreversible action

The single ordering rule that separates a system that resumes correctly from one that resumes into a mess is this: write the checkpoint before taking any irreversible action in the next phase, never after. The reasoning is short and unforgiving. If the agent performs an irreversible action and then records that it did so, an interruption in the gap between the two leaves a checkpoint that does not know the action happened. Recovery reads that checkpoint, sees the action as still pending, and does it again. A charge that already cleared goes out a second time, and whatever the action touched in the world now carries a duplicate it was never meant to have. The agent believed it was resuming cleanly and instead it duplicated an effect that could not be taken back.

Getting the order right does not eliminate the hazard on its own, because the interruption can also land after the action and before the record no matter how tightly the two are sequenced. Past a certain point, resumability stops being a question about saved state and becomes one about how the action itself behaves when it runs a second time. Where an action can be made idempotent, so that performing it twice has the same effect as performing it once, replay is safe by construction and the checkpoint ordering is a cost optimization rather than a correctness requirement. Where an action cannot be made idempotent, the checkpoint ordering is doing the load-bearing work, and it does that work well only when the record of completion is committed in a way that cannot be separated from the effect it describes. An agent that takes irreversible actions and treats resumption as a matter of reloading state, without confronting how those actions behave under replay, has a latent double-execution bug that will surface exactly when an interruption happens to fall in the wrong place, which over a long enough run it will.

Recovery is the normal way a session starts

The most common way a system that could resume fails to is quiet: it never checks. A run starts, begins fresh execution, and never asks whether a checkpoint from a prior attempt is sitting there waiting. The fix is to make the check part of the standard session start, so that recovery is not a special mode entered after a detected crash but the ordinary opening move of every run.

The sequence is small and should be invariant. Every run opens by asking the same question: is there a checkpoint waiting? Absent one, the agent simply starts empty, which is the same code path as a resume with nothing yet saved, not a separate branch. When one is found, the next move is not to trust it but to test it, because a checkpoint that was corrupted or only half-written is more dangerous than an empty slate. A missing checkpoint forces an honest restart; a broken one lures the agent into resuming from a state that looks sound, is not, and gets carried forward with full confidence. Only after that integrity test passes does the agent read the saved state in, treat every phase it marks done as done, and take up execution at the earliest phase still open, with that phase’s inputs and the results it depends on already in place. Treating this as the universal start sequence, rather than a branch taken only when something is known to have gone wrong, is what turns resumability from a capability the system has in principle into one it actually exercises. A run that reaches for fresh execution without first asking whether it is a continuation will restart from scratch every time it fails, and the checkpoints it dutifully wrote will never once be read.

Resuming onto a world that has moved

Restoring the agent’s own state correctly is necessary and not sufficient, because the agent does not run in a vacuum, and the world it depends on can change in the interval between when a checkpoint was written and when it is read back. A record the task was updating gets rewritten by another writer; a resource the plan counted on is decommissioned while the run sits paused. The agent’s saved state is internally perfect and now describes a situation that no longer exists, and if it resumes on that basis it will act on stale premises with exactly the same confidence it would bring to correct ones. That confidence is the danger. A crash announces itself. A resumption onto quietly outdated state produces plausible, well-formed, wrong behavior that nothing flags.

State versioning is the guard against this specific failure. At checkpoint write time, record not only the task state but a marker of the environment it was written against: a timestamp, and a hash or version identifier of the external conditions the task depends on. On resume, compare the current environment to the saved marker before proceeding. When they match, the saved state is still trustworthy and the agent continues. When they diverge, the agent has detected that the ground moved, and the correct response is to stop and surface the conflict for a decision rather than to silently proceed as if nothing changed. The two failure modes are not symmetric, and that asymmetry decides the whole question. A version mismatch that halts a run costs a pause: the event is visible the moment it happens, and its cause is sitting right there in the mismatch. A resume onto stale state costs a wrong outcome that nobody sees form, that may travel through several downstream steps before it surfaces, and that is expensive to trace back once it does. An agent tuned to halt a little too eagerly wastes some pauses; one tuned to proceed too eagerly ships damage. The eager halt is the error you can afford.

Partial state beats no state

The last design choice is what the agent does when its recovered state is incomplete rather than absent or intact. The brittle answer is to require everything: an agent that can only proceed with its full state reconstructed will fail entirely whenever any single piece is missing, which makes the whole run hostage to the least reliable fragment of its own persistence. The resilient answer is graceful degradation, where the agent continues with reduced capability on partial state instead of refusing to run.

Making that possible is a property of how phases are designed, not a behavior bolted on at recovery time. A phase has to name the floor it can run on, the inputs below which it truly cannot start, and specify how it behaves when recovery hands it less than the full set. Given that, a checkpoint that covers the first several phases but is missing a later one does not force a total restart; the agent resumes from the frontier it can trust, acknowledges the gap it cannot fill, and proceeds from there rather than throwing away the state it does have. This extends to keeping the persisted state clean over a long run: state that has served its purpose and will not be read again is worth pruning so it cannot mislead a later resumption or bloat the snapshot, but the pruning decision carries its own obligation, which is to confirm before removing anything that the content either has no future value or has already been written somewhere durable. The governing instinct in both cases is the same. Design the degraded path at every boundary, treat partial state as something to continue from rather than something to reject, and the run becomes resilient in the way that actually survives contact with production, where state is lost in fragments far more often than all at once or not at all.

What makes a run recoverable is built while it is still running

Resumability reduces to a handful of commitments, and none of them can be made after the interruption they protect against. Persist the three things resumption needs, which steps completed, what the next step requires, and the results later phases depend on, and persist them at phase boundaries where the cost is bounded and the state stays simple. Write the checkpoint before the irreversible action, and where the action cannot be made replay-safe by ordering, make it idempotent, because those are the only two ways a resumed run avoids doing twice what must happen once. Make the check for a prior checkpoint the ordinary first move of every session, so that a fresh start is just the empty case of a resume and the recovery path is exercised as a matter of course rather than discovered in an emergency. Version the environment the checkpoint was written against, and stop rather than act when the two disagree, because acting on stale state with full confidence is the worst outcome and the hardest to see. And design each phase to run on the state it can recover rather than demanding all of it, so that partial loss degrades the run instead of ending it. Do these while the agent is running well, and an interruption becomes a pause. Skip them, and the same interruption becomes the moment the work quietly disappears, or worse, the moment it silently happens twice.