Перейти к содержимому
Цена founder — зафиксирована для ранних клиентовНачать →

AI Agent State Management: Checkpointing, Shared State, and Crash Recovery

AI agent state management is the practice of persisting an agent's execution context to durable external storage so that a crashed agent can resume from its last checkpoint rather than restart, and so multiple agents can read and write shared runtime context without passing full message history on every handoff. Without it, a 20-step pipeline that fails at step 14 discards 14 LLM calls and all their tool costs. It is the persistence layer beneath agentic workflow execution patterns.

AI agent state management is the practice of persisting an agent's execution state to durable storage so that a crashed or interrupted agent can resume from its last checkpoint rather than restart from scratch, and so that multiple agents in a pipeline can read and write shared runtime context without overwriting each other's data.

State Management vs. Agent Memory: What's the Difference?

Developers regularly conflate agent memory and agent state. They solve different problems and use different storage primitives.

Agent Memory: Private, Per-Agent, Episodic and Semantic

Agent memory (covered in depth in AI agent memory types and episodic storage) is private, per-agent, long-term storage about past interactions and accumulated knowledge: episodic memory (what happened in prior sessions), semantic memory (facts the agent has learned), and procedural memory (how to perform tasks). Memory is read-mostly, persists across separate runs, and belongs to one agent. No other agent reads your episodic log.

Agent State: Shared, Mutable, Runtime Execution Context

Agent state is shared, mutable, runtime context that multiple agents read and write within a single task execution. It answers: which steps have completed, what intermediate results are available, which work items have been claimed. State is read-write-concurrent, scoped to an active execution, and designed to be written by agents that have no prior relationship with each other. A research agent writes findings to a shared key; a summarization agent reads them when ready — no direct coupling required.

When You Need Both: Long-Horizon Multi-Agent Pipelines

Production pipelines need both. A multi-day research task needs agent memory to recall what was investigated yesterday, and agent state to coordinate which of today's 12 sub-tasks are claimed, completed, or failed. Memory answers "what do I know?"; state answers "what are we doing right now and who is doing it?"

The Three Core Problems State Management Solves

Problem 1: Crash Recovery and Resumability

Without checkpointing, any process crash forces a full restart from step zero. Every LLM call, every tool invocation, every API round-trip must be repeated. In a 20-step research pipeline that crashes at step 14, steps 1-13 are wasted: their LLM tokens, tool costs, and wall-clock time are all spent again.

With a checkpoint after each step, recovery is targeted: the agent loads the latest checkpoint for its thread_id, sees that steps 1-13 completed successfully, and resumes at step 14. LangGraph (langchain-ai/langgraph, 34,815 ⭐, MIT, June 2026) implements this exactly: every graph execution is identified by a thread_id, every step produces a checkpoint_id, and any backend that implements BaseCheckpointSaver can serve as the durability layer.

Problem 2: Cross-Agent Coordination Without Message Passing

In message-passing architectures, Agent A's handoff to Agent B must include enough context for B to understand the full task — often duplicating data B could read from shared storage. A Hacker News builder reported 60% context window reduction in January 2026 by switching from full-context message passing to a shared-state architecture where each agent reads only the specific keys it needs.

The economics compound: smaller context windows reduce per-call LLM costs, reduce latency, and reduce the probability of the model losing track of early context. Shared state is the coordination primitive for multi-agent orchestration architecture — orchestrators assign work by writing to state; workers claim it atomically.

Problem 3: Concurrent Writes and Race Conditions

When multiple agents write to shared state simultaneously without coordination, last-write-wins semantics corrupt data. Classic example: Agents A and B both read task_count = 5, both increment it independently, both write 6. The correct value is 7. Three strategies exist:

  • Reducer functions (LangGraph): define a merge function per state field — Annotated[list[str], operator.add] appends all concurrent writes to a list rather than overwriting. No coordination required; merge is automatic.
  • Compare-and-swap (CAS): write only if the current value matches an expected value. If another agent wrote first, the CAS fails and the writing agent retries with the updated value.
  • Pessimistic locking: acquire an exclusive lock before writing, serialising all writes to a field. Correct but serialises throughput.

Checkpointing Architecture: How LangGraph Does It

LangGraph is the reference implementation of agent checkpointing. At 34,815 stars and MIT-licensed, it is the most widely adopted framework with a formal checkpoint persistence API.

BaseCheckpointSaver: The Interface Every Backend Implements

All LangGraph checkpoint backends implement BaseCheckpointSaver. Three core methods:

get_tuple(config) → CheckpointTuple | None Loads the most recent checkpoint for a given thread_id. If config includes a checkpoint_id, loads that specific snapshot. Returns a CheckpointTuple containing the checkpoint data, metadata, and any pending writes that had not yet been flushed. Returns None if no checkpoint exists for the thread.

put(config, checkpoint, metadata, new_versions) → RunnableConfig Atomically writes a new checkpoint with version tracking. new_versions is a dict mapping state channel names to their new version numbers — used to detect concurrent writes and resolve conflicts. Returns the updated RunnableConfig with the new checkpoint_id embedded.

alist(config, *, filter, before, limit) → AsyncIterator[CheckpointTuple] Streams checkpoint history for a thread_id in reverse chronological order. filter accepts metadata key-value predicates; before accepts a checkpoint_id to paginate backwards; limit caps the result count. Used for audit trails, rollback UI, and debugging execution history.

All three methods have synchronous variants (get_tuple, put, list) and asynchronous variants (aget_tuple, aput, alist).

Built-in Backends: SQLite, Postgres, Redis, MongoDB

LangGraph ships five backends out of the box:

BackendUse caseCrash safe?Multi-process?
MemorySaverDevelopment / testing❌ No❌ No
SqliteSaverSingle-process demos✅ Yes⚠️ Limited
PostgresSaverProduction✅ Yes✅ Yes
RedisSaverHigh-throughput pipelines⚠️ Optional✅ Yes
MongoDBSaverComplex metadata✅ Yes✅ Yes

PostgresSaver / AsyncPostgresSaver is the recommended production backend. It handles concurrent writes from multiple processes safely, survives crashes, and supports connection pooling. MemorySaver is development-only: a process crash wipes it completely.

thread_id, checkpoint_id, and checkpoint_ns: The Addressing Model

Three identifiers locate a checkpoint:

  • thread_id: identifies a task or conversation execution — analogous to a session ID. All checkpoints for a run share the same thread_id. To resume a crashed run, pass the same thread_id; LangGraph loads the latest checkpoint_id automatically.
  • checkpoint_id: a UUID identifying one specific point-in-time snapshot within a thread. LangGraph assigns these automatically. Pass a specific checkpoint_id to roll back to an earlier state or branch the execution graph from a prior step.
  • checkpoint_ns: namespaces checkpoints within sub-graphs. Critical for nested agent architectures where an orchestrator spawns sub-agents, each running their own execution graph. The orchestrator's checkpoint_ns is the empty string; each sub-agent gets a namespaced prefix that prevents sub-graph state from colliding with the parent graph state.

State Schema: TypedDict and Reducers

LangGraph state is declared as a TypedDict. Each field can carry a reducer annotation controlling how concurrent writes merge:

from typing import Annotated
import operator
from typing_extensions import TypedDict

class ResearchState(TypedDict):
    query: str                                      # last-write-wins (default)
    findings: Annotated[list[str], operator.add]   # concurrent writes appended
    step_count: Annotated[int, operator.add]        # concurrent writes summed

In a fan-out pattern where three parallel research sub-agents all write to findings, each write appends to the list rather than overwriting it. The orchestrator receives a merged list of all three agents' findings when they converge. Without the reducer annotation, two of the three writes would be silently discarded.

The Blackboard Pattern: Shared State Without Message Passing

The blackboard is the canonical distributed systems pattern for multi-agent coordination. It predates LLM agents by decades: the HEARSAY-II speech understanding system (1970s) used a shared blackboard to coordinate independent knowledge sources that each posted and consumed partial solutions. The pattern maps directly to modern multi-agent AI pipelines.

What the Blackboard Pattern Is

A blackboard is a shared, persistent, named key-value space that all agents in a system can read and write. Agents communicate through shared state rather than direct messages: one agent writes its findings to a named key; another agent watches that key and acts when it changes, with no knowledge of which agent wrote the data or when.

This decouples agents completely. Adding a new agent that reads research/findings requires no changes to any existing agent. The blackboard pattern is one of the standard coordination approaches covered in multi-agent system design.

Namespace Isolation: Preventing Cross-Agent Data Collisions

Without namespace discipline, two agents writing to the same key overwrite each other. The convention is hierarchical prefixes: {domain}/{agent_id}/{topic} or {domain}/{task_id}/{step}.

Examples:

  • research/agent-1/findings and research/agent-2/findings — parallel research agents, isolated namespaces
  • tasks/pending/item-42 — a pending task any worker can claim
  • tasks/claimed/item-42 — the claimed record, written by the claiming agent
  • output/summarizer/report-v1 — a finished artifact

Hierarchical prefixes let any agent list all keys under a namespace (tasks/pending/*) without knowing specific key names, and let the platform enforce per-agent ACL policies at the prefix boundary.

Compare-and-Swap: Preventing Race Conditions on the Blackboard

Compare-and-swap (CAS) atomically reads the current value, compares it to an expected value, and writes a new value only if the comparison succeeds — otherwise returning a failure. Two agents that simultaneously attempt to claim the same pending task by writing claimed_by: agent-1 and claimed_by: agent-2 to the same key cannot both succeed: one CAS wins, the other detects the conflict and retries on a different key.

OpenLegion's claim_task() implements CAS on the blackboard as the canonical pattern for distributed task assignment without a central coordinator. No lock manager, no queue service, no coordinator agent required.

Watch Notifications vs. Polling

Polling for state changes is wasteful: each agent must call read_blackboard() on a timer, burning API calls even when nothing changed. At 100 agents polling every second, that's 100 read operations per second of pure overhead.

Watch notifications push a message to the watching agent when a matching key changes — no polling required. OpenLegion's watch_blackboard(pattern) delivers change notifications in under 100ms. Glob pattern matching (tasks/pending/*) notifies any watching agent of a new pending task regardless of its specific key name. For AI agent observability and state tracing, watch notifications are also the mechanism for forwarding state change events to tracing backends without polling overhead.

OpenLegion's Take: External State Is the Only Reliable Architecture

State stored inside an agent process is unreliable by design. A process crash, OOM kill, or network partition doesn't just interrupt the agent — it destroys the state it held. This is the same problem that led distributed systems engineers to prefer external state stores (Redis, Postgres) over in-process state for any workload that requires durability or multi-node coordination. The same principle applies to agents.

OpenLegion's blackboard is external to every agent process. A crash in Agent A doesn't corrupt Agent B's view of shared state. State versions survive crashes because they live outside any individual container. Every write is versioned; rollback to any prior state version is O(1) via the version index.

The OpenAI Agents SDK (openai/openai-agents-python, 27,169 ⭐, MIT, June 2026) ships no built-in persistent checkpointing: state lives in the Runner.run() return value. A process crash loses the entire execution context. Developers must implement their own persistence layer, which in practice means wrapping every Runner.run() call with a SQLite write — exactly the code that a purpose-built state layer should eliminate.

DimensionOpenLegionLangGraphOpenAI Agents SDKAutoGenCrewAI
State persistence across crashes✅ External blackboard, versioned✅ BaseCheckpointSaver backends❌ No built-in⚠️ ChatHistoryStore (SQLite)❌ No built-in
Cross-agent shared state✅ Blackboard — all agents read/write⚠️ Via checkpoint, not true blackboard❌ DIY❌ DIY❌ In-process dict only
Concurrent write safety✅ CAS via claim_task()✅ Reducer functions❌ DIY❌ DIY❌ DIY
Change notifications (no polling)✅ watch_blackboard() <100ms❌ Poll-based❌ None❌ None❌ None
Namespace isolation✅ Hierarchical key prefixes + ACLs✅ checkpoint_ns❌ DIY❌ DIY❌ DIY
Built-in checkpoint backends✅ External persistent store✅ SQLite, Postgres, Redis, MongoDB❌ None⚠️ SQLite only❌ None

The state management capabilities covered here are a key criterion in AI agent platform selection.

State Security: What Shared State Exposes

Shared state is an attack surface. Three risks are specific to the state layer.

Stored Injection: Poisoned State Persists Across Sessions

Prompt injection via stored state is the highest-severity state security risk: malicious instructions written to a shared key persist across agent sessions and affect every future agent that reads that key. A research agent that reads a poisoned findings key carries the injection into its next LLM call. Unlike direct injection (which is scoped to one session), stored injection fires repeatedly until the poisoned key is overwritten or sanitised.

Mitigations: output validation before any content is written to shared state (assert the schema and check for instruction-like content), and input sanitisation at every state read boundary before content enters the LLM context.

Credential Leakage: Redact Secrets Before Checkpointing

Observability tools that capture state snapshots — checkpoint debugging, state replay, tracing backends — may log whatever is present in the state at checkpoint time. If an agent includes a raw API key or token in its state schema, that value propagates to every downstream consumer of checkpoints: log aggregators, tracing databases, backup stores. State snapshots are the primary data source for AI agent observability and state tracing — ensure secrets are redacted before checkpoints reach your tracing backend.

Use opaque credential handles (e.g. $CRED{name}) in state schemas rather than raw credential values. The handle resolves at call time; the plaintext secret never enters the checkpoint.

Namespace Access Control: Per-Agent Read/Write Permissions

In a multi-agent system, an agent with write access to one namespace should not be able to read another agent's private namespace. Without ACL enforcement at the platform layer, a compromised agent can read output/summarizer/*, tasks/claimed/*, or any other key it learns about — potentially exfiltrating intermediate results or poisoning other agents' task queues.

Enforce per-agent ACL gates on state keys at the platform layer, outside agent code. An injected agent cannot self-modify its read permissions if those permissions are enforced by the mesh host rather than by the agent's own code.

Frequently Asked Questions

What is AI agent state management?

AI agent state management is the practice of persisting an agent's execution context — completed steps, intermediate results, claimed tasks, and coordination data — to durable storage outside the agent process. This enables crash recovery (a failed agent resumes from its last checkpoint rather than restarting) and cross-agent coordination (multiple agents read and write shared mutable state without passing full context in every message). Without state management, long-horizon multi-agent tasks are fragile: any process failure requires a full restart from step zero.

What is the difference between agent state and agent memory?

Agent memory (episodic, semantic, procedural) is private, per-agent, long-term storage about past interactions and accumulated facts — what happened in previous runs and what the agent knows. Agent state is shared, mutable, runtime execution context that multiple agents read and write within a single task execution — which steps have completed, what intermediate results are available, which work items have been claimed. Memory is read-mostly and persists across runs; state is read-write-concurrent and scoped to an active execution.

How does LangGraph checkpointing work?

LangGraph persists execution state through the BaseCheckpointSaver interface, which every backend (SQLite, Postgres, Redis, MongoDB) implements. Each execution is identified by a thread_id; within a thread, each step produces a checkpoint with a unique checkpoint_id. The get_tuple(config) method loads the latest checkpoint for a thread_id so a resumed execution picks up where it left off. State schema is defined as a TypedDict with optional reducer functions (via Annotated type hints) that control how concurrent writes from parallel sub-agents are merged.

What is the blackboard pattern for AI agents?

The blackboard is a shared, persistent, named key-value space that all agents in a system can read and write. Agents communicate through shared state rather than direct messages: one agent writes research findings to a named key; another agent watches that key and acts when it changes, with no knowledge of who wrote it. This decouples agents from each other — adding a new consumer of shared state requires no changes to the producers. The blackboard pattern originated in 1970s AI research and maps naturally to modern distributed agent coordination.

How do you prevent race conditions in shared agent state?

Three approaches work: reducers (LangGraph — define a merge function per state field so concurrent writes are combined rather than overwritten; Annotated[list, operator.add] appends all concurrent writes to a list), compare-and-swap (write only if the current value matches an expected value; fails if another agent wrote first, triggering a retry), and pessimistic locking (acquire an exclusive lock before writing, serialising all writes). Reducers work best for accumulation patterns; CAS works best for task claiming and counters; locking works best for complex multi-field updates.

Which LangGraph checkpoint backend should I use in production?

PostgresSaver (or AsyncPostgresSaver) is the recommended production backend: it supports concurrent multi-process writes, survives crashes, and scales horizontally. MemorySaver is for development only — no crash recovery. SqliteSaver works for single-process deployments but does not handle concurrent writes safely. RedisSaver is fast but ephemeral by default, appropriate for high-throughput pipelines where losing a checkpoint on Redis restart is acceptable. MongoDBSaver suits pipelines where checkpoint metadata is complex and document-oriented queries are useful.

How does shared state reduce context window usage in multi-agent systems?

In message-passing architectures, every inter-agent handoff must include enough context for the receiving agent to understand the full task — often duplicating data a prior agent already computed. With a shared state layer, an agent writes its findings to a named key and the next agent reads only what it needs from that key, without the sender anticipating what to include. A Hacker News builder reported 60% context window reduction in January 2026 by switching from full-context message passing to a shared-state architecture. Smaller context windows reduce per-call LLM costs and latency.

What are the security risks of shared agent state?

Three risks are specific to the state layer: stored prompt injection (malicious instructions written to shared state persist across sessions and affect every future agent that reads that key — unlike direct injection, stored injection fires repeatedly until sanitised), credential leakage (observability tools that capture state snapshots may log secrets present in state — use opaque handles, not raw credential values in state schemas), and unauthorised state access (enforce per-agent ACL gates on state key namespaces at the platform layer, not in agent code, so a compromised agent cannot read outside its permitted namespace).

Pick the Right State Architecture Before You Need Crash Recovery

The failure mode is predictable: teams build multi-agent pipelines without external state, a pipeline crashes at step 14 of 20 after two hours of LLM calls, and the first thought is "we need checkpointing." Adding it after the fact requires refactoring every agent that touches mutable data.

External state should be a day-one decision: define your state schema, choose a durable backend (PostgresSaver if you're on LangGraph; OpenLegion's blackboard if you want CAS writes, watch notifications, and namespace ACLs without separate infrastructure), and treat every agent write as a durability event.

Build resumable multi-agent pipelines with OpenLegion's built-in state layer →