LangGraph — step by step

Updated 4 min read source
On this page12
  1. Step 1 — What it is, and when not to use it
  2. Step 2 — State and reducers
  3. Step 3 — Nodes, edges, routing
  4. Step 4 — The prebuilt agent
  5. Step 5 — Persistence
  6. Step 6 — Human in the loop
  7. Step 7 — Streaming
  8. Step 8 — Composition
  9. Step 9 — Production
  10. The 60-second answer
  11. Where this connects
  12. Official documentation

LangGraph — step by step

A reading path, not a reference. Work down it in order; each step names what you should be able to do before moving on. Tick the box when you can explain it out loud without notes.

The deep-dive notes live in LangGraph, in depth. Verified against LangGraph 1.3.x / LangChain 1.3.x, 2026-08.

Before anything else: the front door is create_agent from langchain.agents. create_react_agent is the pre-1.0 name — most tutorials and Stack Overflow answers still use it, and saying it out loud dates your knowledge to before October 2025.

Step 1 — What it is, and when not to use it

State machine runtime, not a chain library. A node never calls the next node — it returns an update and the runtime decides. That indirection is the whole design, and everything else is downstream of it.

Be able to say: why a chain cannot loop, branch, pause or resume, and the three conditions that justify adopting LangGraph at all — durability, human-in-the-loop, genuine branching.

Step 2 — State and reducers

python
from typing import Annotated
from operator import add

class State(TypedDict):
    question: str
    logs: Annotated[list[str], add]

The single concept people miss. Without a reducer an update replaces the key; with one it merges. That is also what makes a key safe for two parallel branches to write.

Be able to say: what add_messages does that add does not (replaces by message id, so a turn can be revised rather than duplicated).

Step 3 — Nodes, edges, routing

Normal edges, conditional edges, and Command for update-and-route in one return. Loops are just a backward edge — an agent is a graph with a cycle and a model in the router.

Be able to write from memory: the smallest complete graph, StateGraphadd_nodeadd_edge(START, ...)compile().

The gotcha: own your termination condition. The runtime’s recursion limit raises rather than finishing gracefully, so put a step counter in state.

Step 4 — The prebuilt agent

python
from langchain.agents import create_agent

agent = create_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search],
)

It returns a compiled graph, so everything from step 3 applies to it. Middleware is the 1.0 replacement for subclassing — summarisation, guardrails, approval and retry each become an independent unit.

Be able to say: where approval logic belongs (middleware, running on every tool call — not prompt text), and when you would drop to StateGraph.

Step 5 — Persistence

python
graph = builder.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "conv-42"}}

One mechanism, four payoffs: conversation memory, crash resumption, human-in-the-loop, time travel. PostgresSaver in production — AsyncPostgresSaver in an async app, or you block the event loop.

Be able to say: how you debug a bad run — read the state history, fork from the checkpoint before it went wrong with one value changed.

Step 6 — Human in the loop

python
from langgraph.types import interrupt, Command

decision = interrupt(
    {"action": "refund", "amount": 500}
)
# ... later, possibly another process:
graph.invoke(Command(resume=True), config)

The pause is durable — a row in Postgres, not a suspended coroutine — so approval can happen days later from another machine.

The two rules: resuming replays the node from its start, so side effects go after the interrupt; and never wrap interrupt() in a bare except, because it works by raising and a broad catch silently disables the gate.

Step 7 — Streaming

updates for step progress, messages for tokens — different questions, and a long run needs both.

Be able to say: streaming changes perceived latency, not actual, and the underrated half is that visible progress lets a user abort a run that has misunderstood them.

Step 8 — Composition

A compiled graph is callable as a node. Three legitimate reasons to split: context isolation, genuine parallelism, privilege separation — otherwise one agent with more tools.

Be able to say: five agents at 90% each is about 59% end to end, and a supervisor routing on a state field needs no model at all.

Step 9 — Production

Durability modes, determinism, the three testing layers, and the failure catalogue.

Be able to say: why a node must be safe to run twice, and why now() or random() inside one makes a resumed run diverge from the one you were debugging.

The 60-second answer

If you get one question about LangGraph and no follow-up:

“It’s a state machine runtime rather than a chain library. You declare state, nodes and edges, and the runtime owns execution — which is what makes checkpointing, resumption and human-in-the-loop possible, because it can pause between any two nodes. In practice I reach for create_agent first since it’s a compiled graph anyway, and drop to an explicit StateGraph when the flow has stages rather than a loop. The thing I’d emphasise is that most production agents are a graph with explicit edges and one routing decision — the free-running loop is the exception, not the default.”

Where this connects

Official documentation

These notes are written from the docs, not copied from them — go to the source when you need an exact signature.