← All practical guides
Agent reliability15 min readUpdated Sep 12, 2026

Agent memory, checkpoints, and durable workflows: choosing what to persist

Choose what must survive a conversation, a worker crash, and an external action, with a worked refund scenario and concrete recovery checks.

The direct answer

Persist knowledge when a later interaction needs context, and persist execution progress when unfinished work must resume. Add durable scheduling when work must continue without the original request, and protect external actions with stable operation identities and outcome reconciliation: a saved checkpoint alone cannot prove that a refund happened only once.

01

Name the fact that must survive

Write down what the application must recover after each boundary: a new conversation, a dead worker, or an interrupted external request. “We have memory” does not answer all three.

ResponsibilityRecord to preserveRecovery question it answersAdditional requirement
Retrieval memorySelected facts, summaries, source referencesWhat context should a later interaction use?Retrieval scope, freshness and a persistent backend
Execution stateInputs, saved results, pending work, approval stateWhere can this operation safely continue?A stable thread/run identity and compatible resume logic
SchedulingQueued work, waits and their delivery stateWhat will wake the operation after its worker disappears?A surviving dispatcher and recovery policy
External-action outcomeBusiness operation ID, request parameters, provider receipt or uncertain statusDid this particular action happen, and may it be retried?Provider deduplication or an explicit reconciliation path

These are responsibilities, not four mandatory services. One database can hold several records; one runtime can provide execution state and scheduling. LangGraph itself combines thread checkpointers with cross-thread stores. Its “short-term” versus “long-term” memory distinction describes scope; neither label specifies whether the chosen backend survives a process restart. LangGraph persistence

Use the diagram to assign ownership before choosing a product. In particular, an execution log and an external provider can disagree temporarily: one may record an unfinished request after the other has already performed it.

Conceptual map: context, continuation and external outcomes

Loading diagram…
Conceptual diagram. Knowledge supplies later context. An execution record tracks pending work, and a queue or dispatcher wakes it. External actions have a separate outcome; the application must reconcile that outcome with its execution record. These responsibilities can share infrastructure.
02

Check what survives a worker restart

For a crash-recovery requirement, inspect both storage and the mechanism that schedules another attempt. A durable record with no surviving wake-up path can leave work stuck.

LangGraph: InMemorySaver keeps checkpoints in RAM; replacing the process loses them. Use a persistent checkpointer when that failure must be recoverable. Cross-thread memory also needs its own persistent store; attaching a database checkpointer does not turn an in-process store into durable storage. Persistence, Memory setup

Choose checkpoint timing explicitly. The Python 1.2.11 source defines these modes, and the current checkpointer guide explains their crash tradeoffs:

ModeWhen writes happenDesign consequence
syncBefore the next step startsUse when advancing past an uncommitted checkpoint is unacceptable.
asyncWhile the next step executesAccept that a crash may lose a checkpoint still being written.
exitWhen execution exits, including normal completion, a handled error exit or an interruptDo not rely on recovering intermediate progress from an abrupt process crash.

LangGraph 1.2.11 durability definition, Checkpointer durability modes

These settings control when the runtime writes; they do not strengthen the database's replication guarantees or commit an external API call atomically. For an embedded graph, also identify the application worker, queue or recovery routine that will invoke the saved thread again.

Workflow SDK: Local World writes workflow data to local JSON files, but its queue is in memory and does not persist across server restarts. A surviving .workflow-data/ directory therefore does not establish durable scheduling. Vercel World supplies managed storage and queuing for Vercel deployments. Validate the actual World your deployment uses rather than carrying a local development result over to production. Local World, Vercel World

The useful acceptance test is a replacement worker loading the same operation and receiving its pending work. Reusing the same live object only verifies in-process continuity.

03

Choose which work may run again

Mark every model call, time-dependent lookup and external write. Decide whether recovery should reuse its recorded result, retry unfinished work, or intentionally compute a fresh answer.

LangGraph's Graph API saves full checkpoints at super-step boundaries: a super-step is a group of nodes scheduled together. When one node fails, saved pending writes from successful peers can prevent those peers from running again during recovery. This does not preserve arbitrary local variables halfway through an unfinished node. Checkpointers

The Functional API restarts its entrypoint during resume and restores completed task results. Put non-deterministic operations and side effects in separate tasks when each result needs its own recovery boundary. A task that began but did not finish can execute again. Functional API: determinism and idempotency

Workflow 4.8.8 similarly reruns workflow control flow using recorded step results; steps perform runtime work. A step called from another step behaves as an ordinary function, so adding "use step" to a nested helper does not create an independent recovery boundary. Call independently recoverable steps from workflow orchestration. Workflow 4.8.8: workflows and steps

Deterministic replay preserves decisions from recorded inputs and results. It does not make a fresh model request deterministic. For example, in a hypothetical refund flow, persist the proposed amount and policy evidence before asking for approval. Reusing that proposal preserves what was approved. Calling the model again could produce a different proposal; treat that as new work requiring validation.

Keep historical replay separate from failure recovery. In LangGraph, invoking an earlier checkpoint re-executes the nodes after it, including model calls and API requests. It can therefore create new outputs and repeat external actions. Checkpointers: replay

For debugging, route action calls to a test substitute or enforce the original business operation identity. A graph checkpoint is not a snapshot of the outside world, and restoring one cannot undo a previously completed refund.

04

Work through one refund with explicit state boundaries

Hypothetical design, not an executed example. A support agent handles case case-184 for order order-72. It proposes a USD 30 refund, waits for approval, calls a provider, then sends a confirmation. Assume the provider supports deduplication by a client operation key with a documented retention window.

Give the approved refund its own business identity, refund-request-9. Associate it with the authenticated tenant, case and order. Keep that identity across worker retries and replacement workflow runs. A second legitimate partial refund would receive a new identity.

BoundaryDurable record before advancingWhat recovery does with it
Proposal readyproposal-3; amountMinor=3000; currency=USD; order/policy versions; relevant evidence; model outputReuse the proposal that will be shown for approval.
Awaiting approvalPending approval ID bound to proposal-3; thread/run ID; allowed decision and expiryReconstruct the pending request and resume the correct operation.
Approved, ready to dispatchDecision bound to the exact proposal; approver identity; refund-request-9; immutable provider request; status=readyValidate the decision, claim dispatch atomically, and preserve the same request/key on retry.
Dispatch begun, no confirmed outcomestatus=dispatching or outcome_unknown; operation key and request still availableReconcile or resend under the provider's deduplication contract. Absence of a local receipt is not evidence of failure.
Provider outcome confirmedProvider refund ID and status; status=succeeded only once success is confirmedPersist the receipt before marking the refund complete; recover notification separately.

Here, ready, dispatching, outcome_unknown and succeeded are application states we chose, not framework API names. If the provider initially returns a pending refund, record that status and wait or poll for the final outcome.

Keep three records logically distinct. Retrieval memory may say that the customer prefers email. Execution state says that this case is waiting for approval or a provider result. The business record says exactly which refund was authorized and which outcome the provider reported.

An atomic uniqueness constraint on the tenant and refund-request ID prevents two workers from creating two business intents. A conditional dispatch claim coordinates workers; if a claim becomes stale, recovery must reconcile the existing operation rather than create a new one. These controls are design recommendations, not automatic properties of the cited runtimes. Close the intent-to-queue gap too: commit an outbox record with the intent in one application-database transaction, or give a recovery worker a reliable scan of ready and uncertain operations. A crash after saving the intent but before enqueueing must leave discoverable work.

This can be a LangGraph application with persistent checkpoints and a reliable worker, or a Workflow application whose steps perform the proposal, approval handling and refund work. If one calls the other, nominate one owner for refund dispatch and define which saved result crosses the boundary. Avoid having both layers independently retry the same business action without sharing its operation identity.

05

Close the gap between an action and its receipt

In the hypothetical refund, the provider accepts refund-request-9 and performs the refund. The worker dies before recording the reply. Its execution record still looks unfinished. Retrying with a new key can issue another refund, even though both the runtime and its database are behaving as designed.

Workflow's 4.8.8 documentation recommends the stable stepId as an external idempotency key for retries of that step. That scope matters: it identifies a step invocation, not every future run that happens to process the same customer request. Use a persisted business operation ID when duplicate starts, historical replays or replacement runs must converge on the same action. Workflow 4.8.8: idempotency

Apply this recovery sequence:

  1. Persist the intent before dispatch. Store the operation ID and exact action parameters together. Deduplicate repeated inbound requests against that identity, including requests arriving after completion.
  2. Check the provider's contract. Verify key scope, retention, parameter matching, concurrent-request behavior and how to retrieve an existing outcome. An arbitrary header has no deduplication effect unless the provider implements it.
  3. Keep retries identical. Reuse the key and parameters; do not add an attempt number or regenerate the key. A changed amount is a changed intent, not a retry.
  4. Reconcile uncertainty. Retrieve the provider result or resend the same request while its deduplication contract still applies. Treat conflicts according to the provider's documented semantics; a conflict alone does not prove success.
  5. Persist the result, then advance. If the provider offers neither deduplication nor a reliable outcome lookup, stop automatic resends after an ambiguous result and assign reconciliation to a named operational path.

LangGraph also documents that unfinished tasks may run again, and Workflow documents duplicate step execution when an invocation crashes before reporting its result. Wrapping the API call in a task or step reduces repeated completed work; it does not remove the action-to-receipt gap. LangGraph task idempotency, Workflow duplicate steps

For transient failures, Workflow 4.8.8 defaults to three retries after the initial attempt; maxRetries, FatalError and RetryableError provide controls. Set a retry budget and delay that fit the dependency. Stopping retries does not establish whether an earlier request took effect. Workflow 4.8.8: errors and retrying

The same gap applies to the confirmation email. Give notification its own operation identity and delivery policy. A failed email must not cause the refund to be repeated.

Conceptual recovery: refund succeeded, receipt was lost

Loading diagram…
Conceptual failure sequence for the hypothetical refund. The provider has already acted when the worker loses the reply. Recovery uses the original key and parameters to resolve the outcome under the provider's contract. Without that support, it preserves uncertainty and routes reconciliation instead of issuing a fresh refund.
06

Preserve what approval and resume mean

Treat an approval as a decision about a specific proposal. In the refund design, store the approver, proposal version, action parameters and expiry. Accept a resume request only after checking its authorization and its match to the pending decision. A thread ID locates state; it is not an authorization policy.

A LangGraph interrupt resumes using the same thread_id and Command(resume=...). The interrupted node starts again from its beginning, so code before interrupt() runs again. Place proposal generation in a preceding saved node/task and keep the approval node narrow. Moving a side effect after the interrupt avoids repetition caused by that pause, but does not eliminate later crash retries. LangGraph interrupts

For the hypothetical refund, revalidate mutable eligibility after a long wait and before the first dispatch. If the amount or policy basis changes, create a revised proposal and obtain a decision on it. Once dispatch may have happened, resolve the original intent before replacing it; revalidation cannot erase an uncertain external outcome.

Version compatibility is also part of recovery. On Vercel, existing Workflow runs stay with their originating deployment, while new runs use newer deployments. A rerun on the latest deployment starts fresh with the inputs; treat it as a replacement run and retain the refund's business identity. Other Worlds require their own deployment strategy. Workflow versioning, Vercel World

For any runtime, record a state-schema version and decide whether old work will finish on retained code, pass through an explicit migration, or be replaced under the same business identity. Verify an old pending approval against the new deployment before retiring the old one. Keeping a record readable is only part of preserving its meaning.

07

Retain knowledge without turning it into proof

Use retrieval memory for information that helps later interactions, and keep operational decisions in structured records. A summary such as “customer was refunded” may help find a case; the provider receipt and business operation ID should determine whether that refund can be repeated.

LangGraph stores support data across threads and can support semantic search when configured. A store is not necessarily a vector database, and a vector search result is not an execution cursor. Begin with exact lookup if you already know the customer or case ID; add semantic retrieval when the problem is finding relevant prior information. LangGraph stores

Claude-Mem's published Claude Code architecture is an illustrative retrieval pipeline: hooks capture session information, a worker processes it, and stored observations or summaries can supply later context. This supports a knowledge-reuse example; it does not establish recovery of the observed application's pending actions. Scope that example to the documented integration: the source README at the 13.24.23 package revision also describes a Grok Bot path and Grok Mem branding. Check the selected host and release before adopting its setup. Claude Code architecture, 13.24.23 source README

For your own memory records, retain a source reference, subject/tenant scope, observation time and a way to correct or invalidate the fact. Read current order status from its authoritative system when it controls an action. Treat retrieved text as input to validate, rather than permission to operate.

Set retention separately for conversation history, reusable knowledge and operation receipts. LangGraph documents trimming, deletion and summarization as ways to manage conversation state. Those operations do not by themselves define a deletion policy for every historical checkpoint, store entry or external log. Memory management

For the refund design, keep operation records for the period in which your system accepts duplicate requests or replacements, subject to your data-retention requirements. If the provider's deduplication window expires sooner, make reconciliation the path for older ambiguous requests. Keeping fewer chat messages should not silently remove the evidence needed to resolve an unfinished action.

08

Choose the smallest design that meets the failure contract

Follow this sequence and stop adding infrastructure when the next requirement does not apply.

  1. Only a later interaction needs facts? Start with a persistent, scoped knowledge store and a retrieval policy. If restarting unfinished work is acceptable and repeats have no harmful effects, a durable execution runtime may be unnecessary.
  2. The same conversation or graph must continue? Use execution state with a stable thread identity. For a graph application, LangGraph's checkpointer and store can cover conversation continuity and cross-thread knowledge within one framework. Persistence
  3. Work must continue after the original request or worker disappears? Add or verify durable scheduling, saved execution results and a resume path. Choose LangGraph when its graph state and recovery model fit the application; consider Workflow when TypeScript workflow/step orchestration and the chosen World fit the deployment. These capabilities overlap. Functional API, Workflow 4.8.8 steps
  4. Any action can change an external system? Define business operation identities, duplicate-start handling, retry rules and uncertain-outcome reconciliation regardless of which runtime you choose.
  5. Both knowledge and execution must persist? Keep their ownership and retention explicit. Add a second runtime only for a requirement the first design does not meet, such as a distinct orchestration boundary; share business identities across the handoff.

Write the result as a short contract: what is stored; its identity and owner; where it survives; what wakes it; what can repeat; how an uncertain outcome is resolved. If any answer is missing, buying more storage has not yet completed the design.

Evidence scope: documentation checked on 13 September 2026 (Asia/Kolkata). Release anchors are LangGraph Python 1.2.11 and Workflow 4.8.8; hosted documentation can change independently. Workflow's World documentation explicitly distinguishes 4.x and 5.x behavior, so check the release and backend you deploy. The scenario and selection rules are design analysis, not measured reliability results. LangGraph release metadata, Workflow release metadata, World version scope

09

Verify the failures you promise to handle

Run these checks against the chosen package versions and deployment backend. Use a test provider or controlled substitute for external actions. These are proposed acceptance checks; they were not executed for this guide.

Inject this conditionEvidence the design should produce
Start a new conversation for the same user, then a different tenantIntended shared facts are retrievable in the first case; the second cannot access them. Thread state remains scoped correctly.
Replace the worker after a saved resultThe new process loads the same operation and its saved result; pending work is delivered or explicitly recovered.
Kill the worker while a checkpoint is being writtenRecovered progress matches the selected durability mode. Any lost result can be recomputed or reconciled safely.
Complete one parallel graph node and fail its peerRecovery uses the successful node's saved pending writes when present; unfinished work follows the intended retry policy.
Complete a model step, pause, then resumeThe saved proposal remains the one associated with approval. A deliberately fresh computation is identifiable as new work.
Approve after a restart, or submit a stale/duplicate approvalThe correct pending operation accepts one applicable decision; stale proposals do not dispatch.
Have the provider act, then drop its reply or kill the workerThe operation enters an uncertain state, reuses its key/parameters, and converges on one provider outcome or a reconciliation path.
Submit the same business request concurrently and again after completionRequests converge on one business operation and its result, including across separate run IDs.
Fail the notification after the refund succeedsOnly the notification is retried under its delivery policy; the refund receipt remains authoritative.
Exhaust retries, or exceed the provider's deduplication windowThe operation stays visible with its outcome certainty and a named recovery owner; no fresh action is inferred from a timeout.
Resume old state after a deployment, then exercise the retention policyCompatible code/schema can read the state, or an explicit migration/replacement handles it. Necessary pending-action evidence remains available.

Capture the thread/run ID, business operation ID, checkpoint or event boundary, attempt records and provider receipt for each applicable check. A normal successful response alone does not prove crash recovery or duplicate-action protection.

The checkpoint, pending-write and task-retry checks follow the documented LangGraph boundaries; the duplicate-step and retry checks follow Workflow's documented behavior. The expected business outcomes are requirements you must implement and validate. LangGraph checkpointers, LangGraph task recovery, Workflow duplicate steps, Workflow 4.8.8 retry policy

Sources & further reading

Documentation informs the product behavior described here. The worked scenarios and conceptual diagrams explain how those behaviors fit together.

  1. Persistence ↗LangChain · Accessed 2026-09-13
  2. Memory ↗LangChain · Accessed 2026-09-13
  3. Checkpointers ↗LangChain · Accessed 2026-09-13
  4. Functional API overview ↗LangChain · Accessed 2026-09-13
  5. Interrupts ↗LangChain · Accessed 2026-09-13
  6. Stores ↗LangChain · Accessed 2026-09-13
  7. LangGraph 1.2.11 types.py ↗LangChain · Accessed 2026-09-13
  8. Workflows and Steps at Workflow 4.8.8 ↗Vercel · Accessed 2026-09-13
  9. Idempotency at Workflow 4.8.8 ↗Vercel · Accessed 2026-09-13
  10. Errors & Retrying at Workflow 4.8.8 ↗Vercel · Accessed 2026-09-13
  11. Local World ↗Vercel · Accessed 2026-09-13
  12. Vercel World ↗Vercel · Accessed 2026-09-13
  13. Step executed multiple times ↗Vercel · Accessed 2026-09-13
  14. Versioning ↗Vercel · Accessed 2026-09-13
  15. Architecture Overview: Claude Code integration ↗Claude-Mem · Accessed 2026-09-13
  16. README at claude-mem 13.24.23 source revision ↗thedotmack/claude-mem · Accessed 2026-09-13
  17. LangGraph 1.2.11 package metadata ↗PyPI / LangChain · Accessed 2026-09-13
  18. Workflow 4.8.8 package metadata ↗npm / Vercel · Accessed 2026-09-13

Explore the individual tools

Suggest a correction · More practical guides

Agent memory, checkpoints, and durable workflows: choosing what to persist — Runeval