A single-shot chatbot call either returns or it does not, and if it fails you just try again. An agent doing real work is different. A task might run for minutes across many steps: plan, edit, run tests, fix, open a pull request. Somewhere in the middle of that, something will interrupt it. The question is not whether, it is what happens next.
The naive answer is to start the task over from the top. That feels safe and is usually the worst option available. Resumable agent workflows are the alternative: design the task so that when it is interrupted, it picks up from the last step it finished rather than redoing the whole thing. It is an old idea from distributed systems, rediscovered by anyone who runs agents long enough.
Interruptions are the normal case
It helps to stop treating interruption as an exotic failure and start treating it as routine, because it is. A long agent task gets cut off by all the ordinary things that happen in production: a process crashes, a machine restarts, a model call times out, a rate limit pauses the run, a deploy rolls the worker mid-task, someone cancels the job. None of these are bugs. They are Tuesday.
If your agent only works when nothing interrupts it, you do not have a production system. You have a demo that has not met reality yet. So the design goal is not to prevent interruptions, which you cannot, but to make them cheap to recover from.
Restarting from scratch is expensive twice over
Restarting a half-finished task costs you in two ways, and the second is the dangerous one.
The obvious cost is waste. Everything the agent already did, the planning, the reading, the first three edits, gets thrown away and paid for again in tokens and time. For a task that was 80 percent done, a restart is a large bill for zero new progress.
The subtler cost is duplicated side effects. If the agent already opened a pull request, already pushed a commit, already sent a message, restarting from the top can do all of that a second time. Now you have two pull requests, or a migration that ran twice, and a mess that is worse than the interruption you were recovering from. This is exactly why resumability and idempotency and retries are two halves of the same problem: you cannot safely resume work that is not safe to repeat, and you cannot cheaply repeat work you did not record.
Record the result of every meaningful step
The foundation of resumability is boring: write down what you did as you go. After each meaningful step completes, record its output to durable storage under a stable identifier for that step. The plan is step one, the first implementation is step two, and so on, each with a result you can read back later.
The record is what turns a restart into a resume. When the task starts again, it does not re-run step two. It looks up whether step two already has a recorded result, finds it, and moves on. The expensive model call that produced that result happens once, no matter how many times the task is interrupted and restarted around it.
The key property is that the record must be durable and outlive the process. An in-memory cache disappears with the crash that made you need it. The whole point is that the state survives the thing that killed the run.
Make resume the default path, not a special mode
The mistake teams make next is treating resume as a separate recovery routine, a different code path you invoke after a failure. That path rots, because it runs rarely and is tested less. The durable-execution pattern avoids it entirely: there is only one code path, and it happens to be resumable.
The shape is simple. Each step, before it does its work, asks the durable store whether it already has a result. If yes, it returns the recorded result and does nothing. If no, it does the work, records the result, and continues. On a first run, every step misses the cache and executes normally. On a resume, the completed steps all hit and are skipped, and execution flows to the first step that never finished. First run and resume are the same code, which means the resume path is exercised constantly and cannot quietly break.
Modeling the task as an explicit sequence of steps is what makes this tractable, which is why it pairs naturally with state machines for agent workflows: a well-defined state is a well-defined place to resume from.
Decide what to checkpoint, and what not to
Not everything deserves a checkpoint. Recording state has a cost of its own, and checkpointing trivial pure computation just adds overhead. The rule of thumb is to checkpoint the steps that are expensive or that touch the outside world: model calls, test runs, anything that writes to a repository or an external system. A cheap, deterministic transformation between two of those can just re-run.
Two details save you pain later. Keep records immutable, so a resume reads exactly what the first run wrote rather than something a later step mutated. And pin the workflow version, so that if you change the step sequence and then resume an old task, you do not read a step-two record into what is now a differently-shaped step three. Resuming into changed code is a classic way to turn a recovery into a corruption.
The honest limitation
Resumability makes an interrupted task cheap to recover. It does not make the task correct, and it does not make every step resumable. Some work genuinely cannot be resumed cleanly: a step whose external world changed while the task was paused may need to be redone rather than replayed, and a nondeterministic step will not reproduce its exact intermediate state. The durable store is also real state that you now have to manage, secure, and expire, which is not free.
So treat resumability as a way to bound the cost of the interruptions you know are coming, not as a guarantee that nothing is ever lost. The steps that cannot be resumed are exactly the ones to make safe to repeat instead, which loops back to preventing duplicate work when a task fires twice.
This is a property we build into Loopsfinity, because delivery work runs long enough that interruptions are certain: a task that is cut off resumes from its last completed step rather than starting over, so an interrupted run costs the step it was on, not the whole job. The mechanics of how we record and resume that are ours. The principle is not, and any agent doing multi-step work in production should be able to answer one question without flinching: when this gets interrupted halfway, what happens? If the answer is "it starts over," you have work to do. The wider set of choices lives in AI agent architecture.