LangGraph Complete Guide 2026: Build Stateful AI Agents
Build agents with cycles, memory, human-in-the-loop using LangGraph
LangGraph Complete Guide 2026: Build Stateful AI Agents
LangGraph models an agent as a state machine: nodes are functions (LLM calls, tools, plain code), edges decide what runs next, and a typed state object flows through the graph. That explicitness is the whole pitch — loops, branches, retries, and human approval become visible graph structure instead of prompt-buried hopes. It's the production-agent layer of the LangChain ecosystem and the part most worth learning even if you skip the rest.
Install
bash
pip install langgraph langchain-openai
The 30-second version: prebuilt ReAct agent
python
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool@tool
def get_weather(city: str) -> str:
'Get current weather for a city.'
return f'72°F and sunny in {city}'
agent = create_react_agent('openai:gpt-4o-mini', tools=[get_weather])
result = agent.invoke({'messages': [{'role': 'user', 'content': 'Weather in Paris?'}]})
print(result['messages'][-1].content)
create_react_agent gives you the standard tool-calling loop in three lines. Use it until you need custom control flow — then build the graph yourself:
The real thing: explicit graphs
python
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, START, END, add_messages
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAIclass State(TypedDict):
messages: Annotated[list, add_messages] # reducer: appends instead of overwrites
llm = ChatOpenAI(model='gpt-4o-mini').bind_tools([get_weather])
def agent_node(state: State):
return {'messages': [llm.invoke(state['messages'])]}
def route(state: State):
last = state['messages'][-1]
return 'tools' if last.tool_calls else END
builder = StateGraph(State)
builder.add_node('agent', agent_node)
builder.add_node('tools', ToolNode([get_weather]))
builder.add_edge(START, 'agent')
builder.add_conditional_edges('agent', route) # agent → tools, or finish
builder.add_edge('tools', 'agent') # tool results loop back
graph = builder.compile()
Three concepts carry the whole framework:
Annotated[list, add_messages] pattern declares *how* updates merge (append vs replace). Custom state fields (a plan, retry counts, retrieved docs) live alongside messages..invoke(), .stream(), async variants, all standard.What makes it production-grade: persistence
This is LangGraph's real differentiator. Pass a checkpointer and every step's state is saved under a thread ID:
python
from langgraph.checkpoint.memory import MemorySaver # Postgres/SQLite savers for prodgraph = builder.compile(checkpointer=MemorySaver())
cfg = {'configurable': {'thread_id': 'user-42'}}
graph.invoke({'messages': [('user', 'My name is Alice')]}, cfg)
graph.invoke({'messages': [('user', 'What is my name?')]}, cfg) # remembers — same thread
Persistence buys you, with no extra code: multi-turn memory (state survives between calls), crash recovery (resume from the last checkpoint mid-run), and time travel (inspect or fork any historical state for debugging).
Human-in-the-loop: interrupts
Pause the graph at consequential actions, wait for approval, resume:
python
from langgraph.types import interrupt, Commanddef execute_trade(state: State):
decision = interrupt({'proposed': state['trade']}) # graph pauses here
if decision == 'approve':
return {'result': do_trade(state['trade'])}
return {'result': 'rejected by human'}
later, after a human reviews:
graph.invoke(Command(resume='approve'), cfg) # resumes mid-node
Because state is checkpointed, the pause can last seconds or days — the resume request can even come from a different process. This is the approval-gate pattern from human-AI collaboration patterns implemented at the framework level.
Multi-agent shapes
The supervisor pattern is just a graph: a router node picks which specialist subgraph handles the next step; specialists return to the supervisor; the supervisor decides done-or-continue. Each specialist can itself be a compiled graph (subgraphs compose). When evaluating LangGraph against crew-style frameworks for this — CrewAI vs AutoGen — the trade is explicit control (LangGraph) vs faster scaffolding (CrewAI).
Observability and serving
graph.astream() in a FastAPI SSE endpoint (recipe) for stateless deployments; for managed persistence/queues/cron there's LangGraph Platform — the build-vs-buy analysis is in FastAPI vs LangServe.graph.stream(..., stream_mode='updates') yields per-node state deltas — stream "searching…", "found 12 results" as typed events, not just tokens.When LangGraph vs simpler tools
The honest cost: state typing, reducers, and edge functions are real concepts to learn, and simple flows feel over-engineered as graphs. The payoff arrives exactly when your agent needs to survive restarts, pause for humans, or be debugged from a trace.
FAQ
LangGraph vs LangChain agents? LangGraph *is* the successor — classic LangChain AgentExecutor is legacy; new agent work in the ecosystem happens on graphs (LangChain vs LangGraph).
TypeScript? LangGraph.js mirrors the Python API closely; for Next.js-native alternatives see Vercel AI SDK vs LangChain.js.
Which model? Tool-calling quality dominates agent reliability — frontier models are noticeably better at it; compare in the model library.
*Last updated: June 2026. APIs move — verify against the LangGraph docs.*
Also available in 中文.