LangGraph hit 0.4 in early 2026 with stable state checkpointing, durable execution, and a cleaner API. It's now the framework of choice when you need an agent that's more than a prompt-with-tools — when you need branches, retries, parallel work, and persistent state across runs. This walkthrough builds a research agent that takes a question, searches, reads, and produces a cited summary.
What changed in 2026
- Durable execution shipped stable. Agents survive process restarts; long-running research tasks work.
- Streaming through the graph — token-by-token output during multi-node runs.
- First-class human-in-the-loop —
interrupt() makes pausing for human review trivial.
Step 1: define state
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from operator import add
class ResearchState(TypedDict):
question: str
searches: Annotated[list[str], add] # accumulated
docs: Annotated[list[dict], add]
answer: str
iterations: int
State is a typed dict — every field your nodes read or write goes here. Use Annotated[..., add] for fields that accumulate across runs (search history). Bare types overwrite. The iterations counter is the kill switch that stops infinite loops.
Step 2: define nodes
Each node is a function that takes state and returns a partial state update. The planner decides what to search next; the searcher hits the web; the reader extracts facts; the writer composes the final answer. Keep nodes pure — no global state, no side effects beyond the explicit return.
def planner(state: ResearchState) -> dict:
plan = llm.invoke(PLANNER_PROMPT.format(question=state["question"], history=state["searches"]))
return {"searches": [plan["next_query"]], "iterations": state.get("iterations", 0) + 1}
def searcher(state: ResearchState) -> dict:
query = state["searches"][-1]
results = tavily.search(query, max_results=5)
return {"docs": results}
def writer(state: ResearchState) -> dict:
answer = llm.invoke(WRITER_PROMPT.format(question=state["question"], docs=state["docs"]))
return {"answer": answer}
Step 3: wire conditional edges
The interesting part. After each search, we ask: do we have enough to answer, or do we need more research? A conditional edge routes to either writer (done) or back to planner (more research). The kill switch lives here too — past 6 iterations, force-route to writer regardless.
def should_continue(state: ResearchState) -> str:
if state["iterations"] >= 6:
return "write"
if needs_more_research(state["docs"], state["question"]):
return "plan"
return "write"
graph = StateGraph(ResearchState)
graph.add_node("plan", planner)
graph.add_node("search", searcher)
graph.add_node("write", writer)
graph.set_entry_point("plan")
graph.add_edge("plan", "search")
graph.add_conditional_edges("search", should_continue, {"plan": "plan", "write": "write"})
graph.add_edge("write", END)
agent = graph.compile()
Comparison: LangGraph vs alternatives in 2026
| Framework |
Best for |
Skip if |
| LangGraph 0.4 |
Stateful agents, human-in-loop |
Simple chains |
| LlamaIndex |
RAG-heavy workflows |
You're not retrieving |
| OpenAI Swarm |
Multi-agent handoff |
You need durable state |
| Anthropic SDK + custom |
Full control, lean |
Building a team |
| CrewAI |
Agent role-play patterns |
You need rigor |
Common mistakes to avoid
No iteration cap. The number-one source of "my agent is burning credits and not stopping". Always include a hard cap.
Putting prompts in code. Externalize prompts to files or templates. You'll iterate them 100x more than the graph.
Skipping checkpointing in production. Without checkpoints, a process restart loses all in-flight work. Use SQLite checkpointer for dev, Postgres for prod.
Mixing concerns in nodes. A node that searches AND filters AND writes is a node that's hard to debug. One responsibility per node.
FAQ
LangGraph vs LangChain?
LangGraph is the runtime; LangChain is the tool/integration library. They compose. New code should use LangGraph as the orchestrator and LangChain only for integrations.
Can I use Claude or Gemini, not OpenAI?
Yes — ChatAnthropic and ChatGoogleGenerativeAI work seamlessly. Pick by quality on your task.
How do I observe what the agent did?
LangSmith is the obvious answer, free tier is generous. Or wire OpenTelemetry directly.
When NOT to use LangGraph?
If your task is "one prompt, one tool, done" — skip the framework. Use the model SDK directly.
Where to go next
For related guides see AI coding agent workflows in 2026, AI agents for business in 2026, and MCP servers in Claude Desktop in 2026.