Recovery Starts With State Continuity

Long-running agent recovery depends on preserving execution state, pending decisions, artifacts, and side-effect history rather than simply retrying the last request.

Close-up of a fractured ceramic vessel repaired with solid kintsugi-style seams.
The repair remembers what the reset would erase.

IN BRIEF

Retry works when a request is the whole unit of work and is safe to repeat. Once an agent has called tools, created artifacts, paused for a human decision, or caused external side effects, recovery depends on preserving continuity across the run. The system needs to know where it can resume, what already succeeded, which artifacts and decisions still matter, and whether outside actions may already have happened. Checkpoints help, but they are not enough on their own: side effects may need idempotency, deduplication, or confirmation, and resumed work needs enough durable identity and evidence to show that the next action still belongs to the same run.

A retry is easy to reason about when the request is the whole unit of work. It fails, you try again, and — provided the operation is safe to repeat — nothing particularly complicated has happened.

Long-running agent work is where that model starts lying by omission.

By the time an agent has called tools, written artifacts, paused for a human decision, or changed something in an external system, the last request is only one piece of the run. If the process dies there, I don't think the useful recovery question is Can I send that request again?

The useful question is: what has to survive for the next action to still belong to the same work?

That is a state-continuity problem.


The recovery unit gets bigger than the request

Retrying assumes there is very little history worth preserving. The input is known, the operation can run again, and the desired output has not changed.

That is still the right model for some work. A bounded, idempotent request that failed before taking effect may need nothing more sophisticated than another attempt.

But a long-running run accumulates decisions and consequences. A tool call may already have succeeded. A file may already exist. A human may be halfway through an approval. An external API may have accepted a mutation even if the local process crashed before recording the response. A generated artifact may have become an input to later work.

At that point, blindly repeating the latest request can duplicate work, contradict a decision that already happened, or quietly replace an artifact that later steps were supposed to keep using.

The unit of recovery has expanded.

I find it more useful to think in terms of a continuity envelope: the minimum durable state required to determine what has already happened, what is still pending, and what the run is allowed to do next.


What belongs in a continuity envelope

For most long-running agent workflows, five kinds of state deserve explicit treatment.

1. A continuation point

The run needs a durable answer to a basic question: where can this work legitimately continue?

LangGraph's persistence model is one concrete implementation. It stores graph state as checkpoints associated with a thread identity, so execution can recover from recorded state instead of reconstructing the run from a fresh prompt. Its documented fault-tolerance behavior can restart work from the last successful step after a failure.

That is a LangGraph mechanism, not a universal agent-runtime contract. The more transferable requirement is simpler: a resumed process needs a continuation point that belongs to the same logical run.

Without that, resume, replay, and start again become three names for whatever the system happens to do.

2. Work that already counts as done

Recovery also needs to distinguish computation that can safely happen again from work whose result should survive.

Re-running a reasoning step may be harmless. Re-running a tool call that opened an issue, wrote a file, sent a message, or changed a record may not be.

LangGraph documents pending writes and persisted task results as ways to retain successful work across a partially failed execution. Again, those are implementation-specific primitives. The broader point is that recovery has to know which results are reusable and which effects have already crossed the process boundary.

Those are not the same thing.

3. Pending human decisions

A human-in-the-loop pause is state, not empty time between two model calls.

If execution stops for approval, the system needs to retain more than the eventual reply. It needs to know what question was asked, which run asked it, what branch or action the decision governs, and where that answer is supposed to re-enter execution.

LangGraph's interrupt model is one example: execution pauses, state persists, and the run later resumes against the same thread and checkpoint context.

Lose that context and the words of the human answer can survive while their meaning does not.

That is a particularly unpleasant class of bug because the recovered run can look coherent while continuing the wrong branch.

4. Durable artifacts

Files, plans, reports, code changes, generated datasets, and other outputs become part of the run's state once later work depends on them.

Recovery needs a rule for each one: reuse it, validate it, regenerate it, or deliberately supersede it.

Regeneration is not automatically neutral. With probabilistic generation, the same prompt does not guarantee the same intermediate result. If a later decision referenced version A, silently creating version B during recovery can produce a run that is internally consistent and historically wrong.

The artifact needs identity once the workflow starts depending on it.

5. External side effects

This is the part that makes recovery dangerous rather than merely inconvenient.

A crash does not prove an external action failed. An email may have been sent. A ticket may have been created. A database row may have changed. A deployment may have started. The local process can die in the gap between the external system accepting an action and the runtime recording that acceptance.

The Interface Reached the Physical World carries the same problem past the point where compensation is cheap: when the effect is a dispensed volume or a moved arm, the system still has to establish what already happened before it may safely repeat anything.

This is why idempotency keeps appearing in durable-execution guidance. LangGraph explicitly warns that code before an interrupt may execute again on resume and recommends idempotent operations or isolating side effects. Its functional API guidance makes the same basic point for operations that may be re-executed.

The general rule is not "make everything exactly once." That guarantee is often unavailable or much more expensive than it sounds.

The rule is: before repeating an external effect, recovery needs a way to determine whether that effect already happened.


Resume, replay, restart, and retry should mean different things

A surprising amount of recovery ambiguity disappears once the verbs stop being interchangeable.

  • Retry repeats a bounded operation because the previous attempt failed or is believed not to have completed.
  • Restart begins the work again from its initial state.
  • Replay intentionally re-executes from an earlier recorded point, with the possibility that later computation or effects will run again unless controlled.
  • Resume continues the same logical run from durable state, preserving whatever continuity is supposed to survive the interruption.

They can share machinery. They should not share semantics by accident.

LangGraph's checkpoint model makes this visible because replaying from an earlier checkpoint can cause downstream nodes to execute again. LLM calls, API requests, and human interrupts are not guaranteed to reproduce the same result merely because the system reached them before.

If the operator cannot tell which of these four operations is happening, the recovery contract is underspecified.


The better design question

"What should we persist?" is a useful question, but it tends to produce either a tiny answer — usually chat history — or a giant one — save everything forever.

I prefer a harsher test:

What would make this resumed run incorrect if it were lost?

That usually reveals the real durability boundary much faster.

For a given workflow, I would want explicit answers to these:

  • Which identifier proves that this is the same logical run?
  • What is the latest safe continuation point?
  • Which intermediate results must be reused instead of regenerated?
  • Which external effects may already have happened?
  • Which operations are idempotent, and which need deduplication or confirmation?
  • Is a human decision pending, and what exact branch or action does it govern?
  • Which artifacts have become dependencies for later work?
  • What evidence would let someone explain why the resumed run took its next action?

That is a recovery contract. "The agent has memory" is not.


Continuity is also an evidence problem

A correct resume should be explainable.

I don't mean every agent needs a heavyweight audit platform. I mean there should be enough durable identity to connect the resumed execution to what came before it: a stable run or thread identity, a known continuation point, the state loaded at resume, and the status of any external effects that must not be duplicated.

If a human decision is pending, that decision needs to remain attached to the same work identity too.

This evidence serves two different purposes. The runtime uses it to choose the next valid action. A human uses it to distinguish a legitimate continuation from a new run that merely looks similar.

Those two needs start converging as the work lasts longer and produces more durable objects.


Checkpoints are necessary. They are not the contract.

A system can persist state and still recover incorrectly.

A checkpoint can be stale. An external side effect can succeed without being recorded. The outside world can change while a run is paused. A human can answer after the assumptions behind the pending plan have expired. A replay can execute a non-idempotent tool again.

So I would not treat "we have checkpoints" as evidence that recovery is solved.

The stronger contract is closer to this: resume the same logical run from a known continuation point, preserve the decisions and artifacts that are supposed to survive, control or verify side effects before repeating them, and retain enough evidence to decide whether the continuation is still valid.

That sentence is synthesis, not a vendor guarantee. Different runtimes implement the pieces differently.

Temporal's durable-execution documentation is useful corroboration at a broader distributed-systems level: stateful workflow execution is designed to continue across crashes and infrastructure failures instead of disappearing with the process. Temporal is not equivalent to an agent runtime, and agent workflows add their own complications — probabilistic model calls, tools, human interrupts, evolving context — but the underlying continuity problem is not unique to agents.


The architecture consequence

Once recovery is framed this way, a few design decisions become difficult to avoid.

The run needs stable identity. Continuation points need semantics. Human pauses need to survive as pending work rather than loose messages. External effects need idempotency, deduplication, or confirmation rules. Artifacts that later work depends on need durable identity. The system needs enough traceable evidence to connect a resumed action to the same chain of work.

None of this means every agent needs a workflow engine. If the entire task is one safe, repeatable request, ordinary retry may still be the simplest correct design.

The boundary appears when the work starts accumulating irreversible or decision-bearing state.

At that point, recovery is no longer about getting another response from the model.

It is about preserving the continuity of the work.


// End of transmission. The effect may already exist. — ZYANE