How to store agent states across restarts?
TL;DR
- A restart must preserve four things: run state, the agent's current plan, tool calls in flight, and what the agent learned. In the LangGraph, Google ADK, and OpenAI Agents SDK documentation read on 1 November 2026, the in-memory storage option loses state at restart, while each framework documents a persistent alternative (LangGraph, ADK, OpenAI Agents SDK).
- An operation that started but did not report completion has an unknown outcome. It should not be retried blindly or allowed to block later work. Changes in Codex and Hy-Memory separated that condition from ordinary retryable failure in October 2026.
- A retry is safe only when the called service enforces an idempotency key derived from stable intent. ADK says resumed tools run “at least once” and may run more than once (ADK Resume).
- Run state belongs in the framework's persistent execution facility. Learned memory belongs outside one run. LangGraph documents these as separate systems: checkpointers persist graph state, while stores hold application-defined data outside it (LangGraph persistence).
Mnemoverse, which publishes this library, makes a memory layer of the kind described in the section on what an agent learned.
What does an agent have to keep across a restart?
Adam Lewis framed the practical problem this way on 30 September 2026: “Where does the halfway state live when you close the terminal, is it in the message list or reconstructed from the repo each time it starts?” He then identified the difficult part: “saving the transcript is easy and the plan the agent was carrying is hard. If the plan is implied by the files it has already touched, restarting is re-deriving it.” (comment)
The answer requires four distinct records.
Run state is the durable record of where one execution is, including the data needed to continue it.
A checkpoint is a persisted snapshot of run state from which execution can continue or replay. LangGraph describes the mechanism directly: “Checkpointers persist a thread's graph state as checkpoints.” (source)
A side effect is an externally visible change caused by a tool call, such as sending a message or writing to another service.
An unknown outcome is a call state in which the agent knows an operation started but cannot tell whether its side effect committed.
An idempotency key is a stable operation identifier that the called service checks to prevent the same intended effect from being applied twice. Temporal notes that such protection is enforced by the called service, “not by the Activity itself.” (source)
Learned memory is information retained for later threads or sessions rather than for continuing one current execution.
These records answer different recovery questions:
- Where should execution continue?
- What plan was the agent following?
- Which external actions completed, failed, or remain uncertain?
- What should the agent still know in a later session?
A Hugging Face forum question from 2 January 2026 asked whether developers “struggle with preserving deterministic agent state across restarts?” (thread). The difficulty is not one missing database. It is the need to represent each state explicitly.
If the agent is a coding tool you use rather than one you build, see What survives when AI agents restart?.
Persistent agent state APIs: where do LangGraph, ADK and the OpenAI Agents SDK keep run state?
The three frameworks document both in-memory options and persistent options.
| Framework and documentation | What in-memory storage loses at restart | Documented persistent facility | What else matters |
|---|---|---|---|
| Google ADK, read 1 November 2026 | InMemorySessionService: “All conversation data is lost if the application restarts.” InMemoryMemoryService: “None, data is lost on restart”. | DatabaseSessionService: “Data survives application restarts.” | temp: state is discarded after an invocation. user: and app: state stored in memory is lost at restart. Resume is available in ADK Python 1.16 and higher, reinstates completed events, and continues from partially completed state. Resume is not supported by default for Custom Agents. (session, memory, state, resume) |
| LangGraph, read 1 November 2026 | “MemorySaver and InMemorySaver store checkpoints in RAM. When the process restarts, all checkpoints are lost.” | A database-backed checkpointer for run state and a database-backed store for cross-thread data. | A checkpointer saves graph state at each super-step. Cooperative shutdown can finish the current super-step and save a resumable checkpoint. A node already running finishes before draining takes effect. (persistence, memory, fault tolerance) |
| OpenAI Agents SDK, read 1 November 2026 | SQLiteSession without a file path uses an “In-memory database (lost when process ends)”. | SQLiteSession with a file uses a “Persistent file-based database”. A suspended run can be represented by durable RunState. | Serialized RunState includes approval decisions, pending tool calls, and tool arguments. The documentation says loading does “not authenticate the snapshot or the person submitting it.” (sessions, human in the loop) |
From each framework's own documentation, read on 1 November 2026. Examples, not a full list of backends.
The row order is alphabetical, not evaluative.
Anis Meziani described the operational default in his own ADK-based system: “And if you don't configure where sessions live, ADK falls back to an in-memory session service.” In a later comment, he wrote that his system encountered three in-memory defaults covering sessions, long-term memory, and artifacts. That second statement describes his reading and system, not an independent claim here about every ADK facility (article, comment).
Persistence also changes security behavior. A checkpointed thread may carry information obtained under earlier access into a later turn. See What happens to chat history after access is revoked?.
Why is saving the conversation not enough to resume an agent?
A persistent conversation database solves only part of recovery. Meziani put the boundary plainly: “Postgres alone doesn't save the half-finished task. It saves the conversation. The run that was in flight still dies with the pod.” (comment)
A conventional workflow can resume from a named step because its control path is explicit. An agent may choose its next action from model output and current context. Meziani wrote, “With an LLM agent, there is no step 3.” Max Quimby made the related point that “you can't cleanly resume a non-deterministic trajectory” (article, comment).
The practical response is to persist the plan explicitly. Record the current objective, completed step identifiers, pending branches, and required inputs in run state. Update that record at each durable boundary. ADK's guidance for resumable custom logic says to “generate and save the agent state for each completed step of the agent's overall task.” (source)
Do not put a resumable plan in ADK temp: state. ADK says that state is “Discarded after the invocation completes and does not carry over to the next one.” (source)
Without the original input and explicit plan, recovery has to infer intent from the transcript and observed effects. Meziani summarized his own incident: “What was missing wasn't observability. It was the input.” (source)
What happens to a tool call that was running when the agent restarted?
The dangerous interval is after the external service commits but before the agent records success.
Temporal gives a direct example: “The Activity function completes successfully, but the Worker crashes just before it notifies the Temporal Service.” The event history then lacks completion, “so the Activity will be retried.” Completed activities do not execute again during workflow replay, and failed workflow execution continues from the last recorded event (activity definition, workflow execution).
LangGraph documents a related boundary at graph-node level. If one node fails during a super-step, pending writes from other nodes that completed successfully are stored. Resuming that super-step does not rerun those successful nodes. By contrast, replay from an earlier checkpoint re-executes later nodes, “including any LLM calls, API requests, or interrupts”. LangGraph also records failure provenance (checkpointers, fault tolerance).
ADK states that Resume runs tools “at least once, and may run more than once when resuming a workflow.” It tells developers whose tools can cause harmful duplicates to make the tool check for and prevent them (source).
Meziani's system records invocation rather than waiting for a response: “We count the call, not the response.” Its tools_executed field distinguishes no call, confirmed calls, and uncertain calls. He treats an uncertain call as “probably something” because the cost of the two errors differs: “Refusing a safe relaunch costs a click. Approving an unsafe one costs a duplicate email to a customer.” (Fix 7)
Changes in two projects in October 2026 show how that status becomes operational:
- On 16 October, Codex PR #54664 distinguished transient errors “known to be safe to retry” from writes “that may already have committed.” It also states: “Recovery remains the operation owner's responsibility; neither category automatically triggers retries.”
- A Hy-Memory issue opened on 17 October described extraction tasks left as
unknownafter a network interruption. The reporter expected the endpoint'sbacklog_pendingvalue to match the database and reported reinstallation as the only recovery they had found. A maintainer linked PR #27 and closed the issue that day. - PR #27 preserved unknown rows for reconciliation so one uncertain write would not freeze later writes from the same source. It retried an unresolved first attempt once after reconciliation, then parked a second unknown result for explicit recovery. The PR says: “This does not blindly treat unknown as definitely unsent.”
- Hy-Memory PR #63, merged on 18 October, separated waiting for model activation from timed retry. Its prior path returned the backlog to pending every minute without attempting a provider call. The change readmitted those rows after successful activation.
A durable write record therefore needs at least four states: completed, safe to retry, outcome unknown, and waiting for an event. Each needs a separate recovery branch. A queue counter that cannot represent unknown work can look empty while progress has stopped.
How do I make a retried step safe to run twice?
Temporal recommends idempotent activities. Its suggested key combines Workflow Run ID and Activity ID because that pair remains stable across retry attempts while differing between workflow executions (source).
The key must identify intent, not whichever arguments the model generated this time. Quimby described effectful tools that compute a key from arguments. Meziani identified the failure mode: “a key hashed from the args breaks when the LLM rewrites them on replay. The key has to come from stable intent, never from generated content.” He cited provider message identity, a content digest for dataset imports, and human approval for outbound campaigns as examples from his system (discussion).
A forum respondent described another useful pattern: “I store the outputs of anything nondeterministic, like tool calls and external requests, so a replay reads the stored result rather than calling the outside world again.” The same system gives each step an identifier so retries do not duplicate side effects (thread).
Retries can also hide inside transport code. Meziani reported that the ApowerB runtime built on ADK resent the same request after a 429 up to twice without checking whether a streamed function call had already passed. This describes ApowerB code, not ADK behavior. His resulting rule was: “once a call has passed, forward the 429 and let a human decide.” The author of this page suggested that the forwarded error could identify calls already completed in that turn (Meziani, Izgorodin).
Meziani also names the boundary of his approach: “A replay is a new run that cites the original”. His system did not yet provide true mid-flight resume that reused completed tool results (source).
Stable identifiers also matter during retrieval. See Why does vector search return duplicate results?.
Where should what the agent learned live?
Learned information should survive beyond one execution. It should not depend on whether a particular run remains resumable.
LangGraph separates these responsibilities. “Stores persist application-defined data outside the graph state.” Its documentation recommends stores for “long-term, cross-thread memory, including user preferences, facts, and shared knowledge”, with a database-backed store for production (persistence, memory).
ADK likewise distinguishes sessions, state, and memory. Its in-memory memory service loses data at restart. State with user: or app: scope can span conversations, but ADK notes that values held by its in-memory service are lost at restart (memory, state).
An external memory layer is another option. Mnemoverse is one example for learned memory. Its REST POST /memory/write accepts an external_ref, described as a client-provided unique reference for idempotent writes. A write that reuses one is answered with 409 CONFLICT, and the reference can be looked up to recover an atom identifier after restart. The documented /memory/write-batch route accepts an Idempotency-Key; retrying with the same key after a dropped response returns the cached response instead of writing the batch twice. An external_ref derived from stable intent, such as a decision and its date rather than model-generated wording, applies the same rule used for effectful tools. See How should an agent memory write gate work?.
Concurrent writers introduce a separate consistency problem. See How should concurrent MCP memory writes stay coherent?. Transport session state is also distinct from durable memory, as explained in Does stateless MCP mean an agent has no memory?.
What changes when the code is upgraded between the crash and the restart?
A stored execution may outlive the code that created it. ADK gives a direct warning: “Do not modify a stopped agent workflow before resuming it.” (source)
Schema compatibility needs the same attention. Debashish Ghosal, confirming a reader's analysis of his own recovery guard, wrote: “So the guard is build-vs-manifest, and the restore path never reads alembic_version from the target DB.” He agreed that the rolling deployment window is the gap, because an old pod could restore into a database one revision ahead (comment).
A recovery check should compare checkpoint metadata with the database and schema into which it will restore, not only with the application build. During a rollout, old and new processes may write the same durable state. Compatibility rules must cover that overlap.
How do I test that agent state survives a restart?
Treat restart recovery as a fault-injection test, not as a database connectivity check.
- Kill the process during an effectful tool call. Restart it and verify that the external effect exists once. Confirm that the call is recorded as completed or unknown rather than silently repeated.
- Kill the process between plan steps. Verify that execution continues from the recorded step and plan. It should not infer a fresh trajectory solely from the transcript.
- Write a user preference, then start a new thread after restart. Verify that cross-session memory still contains the preference.
- Run a negative control with the documented in-memory option. It should lose state. If it does not, the test may be exercising an unintended persistent component.
Meziani proposes the same basic fault injection in his own walkthrough: “kill the container mid-run, restart it, and watch the session come back.” (source)
What this page does not claim
No performance figure is given for any framework or product. The frameworks in the table are examples, and only their own documentation is quoted, as read on 1 November 2026. This page tests none of them.
Practitioners' accounts describe their own systems and code. The four recovery tests are proposals, not a description of any team's test suite.
Common questions
How to store agent states across restarts?
Store four kinds of state separately: run state in a database-backed framework checkpointer or session service, the current plan explicitly inside that state, tool calls in flight with an outcome status and an idempotency key derived from stable intent, and learned memory outside the individual run.
My LLM agent keeps losing user preferences when restarting the server, how do I persist them?
Move preferences out of process memory. Use the framework's persistent cross-thread or cross-session facility, such as a LangGraph store or an ADK persistent SessionService, or place them in an external memory layer.
What options exist for giving AI agents long-term state across sessions?
The documented options include a framework store that spans threads, a persistent session service, a framework memory service, or an external memory layer. Keep this learned state separate from the state of one running task.
Is saving the conversation history enough to resume an agent after a crash?
No. Conversation history does not necessarily record the active plan, the exact completed step, or whether an external side effect committed before the crash. Those states must be recorded explicitly.
What should happen to a tool call whose outcome is unknown after a restart?
Mark it as outcome unknown, preserve it for reconciliation, and avoid both blind retry and permanent queue blockage. Recovery should inspect the external system or use an idempotency key at the effect boundary.
How do I make a retried agent step safe to run twice?
Give each effectful operation an idempotency key derived from stable intent, not model-generated arguments. The service that performs the effect must enforce the key, and completed nondeterministic results should be stored for replay.
Sources
Every page below was read on 1 November 2026. Each quotation on this page is contiguous text of the page it comes from.
Frameworks
- LangGraph: Persistence, Checkpointers, Fault tolerance, Memory
- Google ADK: Session, Memory, State, Resume stopped agents
- OpenAI Agents SDK: Sessions, Human in the loop
- Temporal: Activity definition, Workflow execution
Changes in October 2026
Practitioners
- Anis Meziani: article and linked comments
- Max Quimby: comment
- Adam Lewis: comment
- Debashish Ghosal: comment
- Hugging Face forum: How do you preserve agent state across restarts?
Mnemoverse
Sources read on 1 November 2026.
Related
- What survives when AI agents restart?
- What happens to chat history after access is revoked?
- How should an agent memory write gate work?
- Why does vector search return duplicate results?
- How should concurrent MCP memory writes stay coherent?
- Does stateless MCP mean an agent has no memory?
Edward Izgorodin · Mnemoverse · 2026-11-02
