The LangGraph Mental Model: Agents as State Graphs
LangGraph treats an agent as a state graph: named nodes that read and write a shared state object, connected by edges that decide what runs next.
Search across all documentation pages
LangGraph treats an agent as a state graph: named nodes that read and write a shared state object, connected by edges that decide what runs next.
That model is why the library focuses on durable execution, branching, interrupts, and checkpoints rather than hiding the loop inside a single black-box agent call.
END or pauses.LangChain (the broader stack) supplies models, tools, messages, and higher-level agent helpers.
LangGraph supplies the orchestration runtime: compile a graph, invoke or stream it, persist progress, and resume.
You can use LangGraph with LangChain chat models and tools, or with plain Python callables and non-LangChain SDKs.
Three objects define the mental model:
A -> B) or conditional edges that inspect state and return the name of the next node (or END).The special symbols START and END mark entry and termination.
Compiling the builder yields a runnable graph (under the hood, a Pregel-style runtime) that you call with invoke, stream, or event-streaming APIs.
Why "graph" instead of "loop"?
A loop is one control shape.
Production agents need many shapes: tool loops, parallel fan-out, approval branches, fallback paths, and early exit.
A graph encodes those shapes as data you can draw, log, and version.
Why "state" instead of "messages only"?
Messages are one channel.
Real agents also need budgets, plan steps, tool payloads, user IDs, and approval decisions.
Shared state is the single source of truth for every node.
Execution proceeds in supersteps.
In each superstep the runtime plans which nodes are ready, runs them (possibly in parallel when the graph fans out), then applies channel updates so the next superstep sees a consistent state.
Nodes do not see each other's mid-step partial writes until the step commits.
That bulk-synchronous model is why parallel branches and reducers matter.
By default, writing a key overwrites the previous value for that channel.
For lists such as chat history you usually attach a reducer with Annotated:
from typing import Annotated, TypedDict
from langgraph.graph.message import add_messages
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
route: stradd_messages merges new messages into the list instead of replacing the whole history.
Without the right reducer, two parallel nodes writing the same key can clobber each other.
A router function reads state and returns a node name (or a list of targets for multi-branch maps):
def route_after_agent(state: AgentState) -> str:
last = state["messages"][-1]
if getattr(last, "tool_calls", None):
return "tools"
return "end"You wire that with add_conditional_edges so the path is explicit in the graph definition, not buried inside one mega-node.
When you compile with a checkpointer, each step can persist a snapshot keyed by thread_id in config:
config = {"configurable": {"thread_id": "user-42-session-1"}}
graph.invoke(inputs, config=config)That is the hook for multi-turn chat, crash recovery, time travel, and human-in-the-loop.
Without a checkpointer, the graph is still a state machine for one in-memory run, but it cannot resume after process death or wait indefinitely for a human.
Calling interrupt(payload) inside a node pauses the graph, surfaces the payload to the caller, and waits until you resume with Command(resume=...).
Interrupts are dynamic breakpoints driven by application logic, not only static "pause before node X" debug hooks.
As the graph runs, you can stream full state (values), node updates (updates), LLM tokens (messages), custom progress events, checkpoints, or tasks.
LangGraph 1.1+ adds version="v2" stream parts with a uniform {type, ns, data} shape; later versions add richer event streaming.
Streaming is how UIs show "thinking" without waiting for the full graph to finish.
Not every agent needs a hand-drawn graph.
LangChain's higher-level agent APIs and harnesses (including deep-agent style stacks) often build on LangGraph under the hood when you need durability and HITL.
Reach for raw StateGraph when you own the control flow: custom routers, multi-agent handoffs, approval gates, or domain-specific stages.
Subgraphs compose specialization.
A parent graph can call a compiled child graph as a node, keeping each specialist's state schema local while still participating in parent checkpoints when configured correctly.
Stores complement checkpointers.
Checkpointers are thread-scoped short-term memory.
A store holds cross-thread facts (user preferences, long-term memory) that nodes read and write by key.
Production graphs mix both.
| Approach | Strength | Weakness | Best Fit |
|---|---|---|---|
| Single LLM call | Simple, cheap | No multi-step recovery | Classification, one-shot draft |
| Fixed chain / pipeline | Deterministic steps | Brittle branching | Known linear workflows |
| Free-form tool loop (no graph) | Fast to prototype | Hard to resume, gate, or audit | Throwaway demos |
| LangGraph state graph | Explicit control, persistence, HITL | More design surface | Production agents with real side effects |
| Multi-agent graphs / crews | Role specialization | Coordination cost | Large workflows with clear roles |
It turns agent control flow into an explicit, durable program: you can branch, pause, resume, and inspect every step instead of trusting an opaque multi-turn loop.
No. LangGraph nodes can call any Python code. LangChain models and tools are optional integrations that many teams use for convenience.
A function that defines how a new write merges into the existing value for a state key (overwrite, append, add, custom merge).
They make entry and termination first-class so the compiler and visual tools share the same topology you reason about.
LangGraph is optimized for LLM-centric steps, streaming, tool loops, and HITL inside an application process (or LangSmith deployment). Classic DAGs target batch data jobs with different latency and operator models.
Yes. When multiple edges lead to ready nodes in the same superstep, the runtime can execute them concurrently. Design reducers so concurrent writes to shared keys combine safely.
Tools are usually invoked inside nodes (or via prebuilt tool nodes). The graph decides when the tool node runs; the tool defines the side effect.
A string you pass in config that tells the checkpointer which conversation or job lineage to load and append. Reuse it to continue; mint a new one to start fresh.
No. Agent tool loops are intentional cycles (agent -> tools -> agent) with a conditional edge that eventually routes to END or a stop condition.
ReAct is a pattern (reason, act, observe). LangGraph is a runtime that can implement ReAct as a small cyclic graph, or implement other patterns (plan-execute, multi-agent) with different topologies.
Build a two-node graph with one conditional edge, then add a checkpointer and a stream consumer. Those three exercises lock the model in place.
If a single model call or a fixed three-step script meets the product need, a graph adds ceremony without benefit. Match complexity to task risk and branching.
No. The graph structures execution. You still need policy checks, tool sandboxing, and evaluation of task success across paths.
Compiled graphs can be rendered (for example via Mermaid export or LangSmith Studio). Visualization is a debugging aid, not a substitute for typed state and tests.
The core state-graph idea is stable. 1.x hardens production features (streaming versions, fault tolerance, persistence ergonomics). Always verify import paths and method names against the version you pin at build.
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026