Checkpoints and interrupts
A checkpoint after every super-step: a run that crashes and resumes, a human interrupt, an edit, and time travel that forks the thread, on a timeline of checkpoints.
Loading the animation…
Concept
With a checkpointer, LangGraph saves a checkpoint after every super-step: the state, the nodes due to run next, and, as tasks finish, their writes. A thread's checkpoints form a history you can list, resume and branch. The animation plays five sessions on the engine's runtime; each is also one of the conformance sessions run in real LangGraph.
- A crash, then resume.
loadfans out toenrichandscore; the worker runningenrichdies. No checkpoint is written for that step, butscorehad finished, and its writes are kept on the last checkpoint as pending writes.invoke(None)resumes: onlyenrichruns again. The side-effects list shows the price:enrichcalled its API twice (3 effects in all for 5 node runs). - A human interrupt. The
asknode callsinterrupt(…)with the draft; the run pauses and returns the question. Its siblingcheckfinished, and is kept. When the human answers withCommand(resume="yes"),askruns again from its first line, so the notification it sent before the interrupt goes out twice. LangGraph's documentation says exactly this: the node restarts from the beginning, and code beforeinterruptshould be idempotent. - A static interrupt and an edit. Compiled with
interrupt_before=["execute"], the run stops before a risky step. A person corrects the plan withupdate_state(…, as_node="planner"), which writes a newupdatecheckpoint as ifplannerhad written the change, and the run continues from it (resuming never stops at the same static interrupt twice). - Time travel.
update_stateon an earlier checkpoint starts a branch: the old run stays in the history, and the new one runscalculatorinstead ofsearch. Replaying an earlier checkpoint (invoke(None, config)with itscheckpoint_id) copies it to aforkcheckpoint and runs the nodes after it again: LangGraph's time-travel page says replay "re-executes nodes", it does not read them from a cache.
Maths
A checkpoint is : the state after step , the tasks due next and the pending writes of those that have finished. A step either completes, giving , or stops on a failure or an interrupt, leaving with more pending writes. Resuming runs only and applies the union, as in the equation; so a step whose tasks have side effects pays them once per attempt of each unfinished task, and an interrupted node pays everything before its interrupt call once per resume.
The history is a tree. update_state on adds a child with step whose state is with the edit applied through the reducers; replaying adds and runs from it. The thread's "latest" checkpoint is the newest one, wherever it hangs, so the next invoke(None) continues the newest branch: in the fork session, 8 checkpoints over 3 operations.
Code
Resuming: a task whose result is already on the checkpoint is not run again; time travel copies the checkpoint into a fork (cut from the vendored engine, graph.ts):
if (first && reuse && rec.result !== null) {
keyed.push([key, t, clone(rec.result)]);
continue;
}
else cur = this.put(base.id, base.step + 1, "fork", base.values, base.pull, base.barriers, base.ready, base.sends);
The interrupt in the real LangGraph node the conformance check builds (conformance/langgraph_graphs.py):
out[op["key"]] = interrupt(op["payload"])