You’ve probably done this with Claude Code. You start a long task, close the laptop, and come back the next morning. You run claude --continue, and it picks up the conversation where you left it. Nice. Nobody thinks twice about it.
Now picture your own agent. It’s processing a refund. It has looked up the order, called the payment API, and is about to email the customer when the pod gets restarted. Your job runner sees a failed job and starts it again.
So what survives? Does it know the refund already went through? Or does it pay twice?
Before we answer that, a word about the tools that promise to handle it for you.
Framework, harness, runtime
Once you decide to build your own agent, you’ll find a crowded shelf of frameworks, with more every month. It helps to separate three words.
A framework is a library. It gives you building blocks for the loop, the tools and the control flow, so you don’t write them from scratch. As of October 2026, two I’d look at first are LangGraph, which describes itself as a low-level orchestration framework and runtime for long-running, stateful agents, and Microsoft Agent Framework, which reached 1.0 in April 2026 and brings together what Microsoft previously had in Semantic Kernel and AutoGen.
The harness, from article 01b, is what you end up with: your prompts, your tools, your rules about what runs. A framework helps you build a harness. It doesn’t hand you one. You own it either way.
A runtime is where the thing actually runs and keeps its state between steps. Sometimes it’s your own process plus a database. Sometimes it’s managed. Anthropic’s Claude Managed Agents, for example, is a pre-built harness that runs in Anthropic’s infrastructure, with sessions that keep history and a sandbox on the server side. It’s in beta as I write. You trade control for not having to run the loop, the sandbox or the storage yourself.
The harness is where model behavior becomes controlled runtime behavior.
You’ll also hear “graph” a lot. Don’t let it sound exotic. A graph here is a state machine. Nodes are steps (call the model, run a tool, ask a human), edges say what comes next, and a shared state object travels through it. Both LangGraph and Microsoft Agent Framework’s workflows work this way. If you’ve drawn an order lifecycle as states and transitions, you’ve already done this.
Here’s roughly how I’d choose.
| If you need | Reach for |
|---|---|
| A short task inside one request, one provider | that provider’s SDK, or plain code |
| Long runs, pause and resume, human approvals | a framework with checkpointing (LangGraph, Microsoft Agent Framework) |
| An agent without running the loop and sandbox yourself | a managed runtime, if the data rules allow it |
| Strict steps that must finish no matter what | the workflow engine you already trust |
Honestly, the framework matters less than people think. I ran the same governance patterns on LangGraph and Microsoft Agent Framework and wrote about it in Your Framework Choice Matters Less Than You Think.
State, checkpoints, durable execution
Back to the refund. In article 02a we saw the model API is stateless. Your app keeps the history. An agent run is the same, only longer. If the state lives only in memory, a crash loses it.
So the frameworks save it. LangGraph’s checkpointer writes a snapshot of the graph state after each step, grouped under a thread ID. Microsoft Agent Framework does the same at the end of each step in its workflows. On a restart, you load the last checkpoint and carry on. If you know databases, it’s the write-ahead log idea. Write down where you are before you move on, so recovery is a replay.
Human approval works the same way. In LangGraph you call interrupt() inside a step. The state is saved and the graph waits, for hours if it has to, until someone answers. Then you resume it with their answer. An approval is just a pause with the state on disk.
What survives a crash, and which step runs again?
Now the catch. What do you think happens to the step that was running when it crashed?
It runs again. LangGraph’s docs say that when you resume after an interrupt, the node restarts from the beginning, so any code before the interrupt runs again. Crash recovery works the same way. Checkpoints make resume cheap, and they do nothing to stop a payment from going out twice. That’s at-least-once execution, the same thing you deal with in any message queue. So anything with a side effect, like paying, emailing or creating a ticket, needs an idempotency key, and you record the intent before you do the effect. I wrote this up in The Retry That Paid The Invoice Twice.
If you need stronger guarantees than a framework’s checkpointer, there are durable execution engines built just for this. Temporal is the well-known one. It records an event history for each workflow so it can resume after crashes and outages.
One security point. A checkpoint holds the whole conversation, tool results and all. Microsoft’s docs call checkpoint storage a trust boundary, and I’d treat it like any database with customer data in it.
Context inside your own harness
When you use Claude Code, the harness handles context for you. In your own harness, that’s your job now. In 03b we had prune, summarise and persist, and LangChain’s four words: write, select, compress, isolate. Write things that must survive to a file or store. Select only what this step needs, like the two relevant files instead of the whole repo. Compress old turns and big tool results, or offload a large result to a file and keep only the path. Isolate noisy work in a subagent with its own context. Managed harnesses and provider APIs will compact for you, which is fine until you need control over what the summary keeps, like the fact that a human said no. More on that in Context Rot: When Your Agent Forgets It Was Denied.
When not to use any of this
So when shouldn’t you use an agent framework? Or an agent at all?
If one model call does the job, make one model call. Classifying a ticket, extracting fields from a document, drafting a summary. A function and a retry are enough.
If the steps are known, write them as plain code. You’ll debug it with the tools you already have.
If your company already runs a workflow engine or a durable job queue, put the model calls inside it as steps. You get retries, monitoring and on-call runbooks that already work.
Frameworks also cost you something. They change fast, they add their own abstractions over the model APIs, and when something goes wrong you end up reading their source to find out what was actually sent. That’s a leaky abstraction, and moving off one later is real work. My rule is simple. Start plain. Reach for a framework when you genuinely need checkpoints, interrupts and resume, and not before.
Next, when the answers aren’t good enough: do you change the model, or change the context?