The foundational mental model — why "the graph" is a Pregel program, and how shared state differs from message passing.
LangGraph is shared-state, not message-passing, and both models descend from Google's Pregel/BSP: work advances in supersteps that end at a synchronization barrier. Get this mental model first and the whole API stops being magic.
The one idea that makes everything else in LangGraph click: nodes don't pass messages, they update a shared state — and reducers decide how.
State is a typed dict of channels; each channel has an optional reducer. No reducer overwrites; a reducer (like add_messages or operator.add) combines. This is the single idea the rest of LangGraph is built on.
A LangGraph node is just a function — it reads the whole state and returns only the channels it changed.
A node is just a function: it receives the whole current state and returns only the channels it changed. Understand the partial-update contract and the immutable-snapshot guarantee that makes supersteps safe.
How the four smallest pieces of the LangGraph API turn a bag of nodes into a program you can run.
Edges, START, END, compile() and invoke() are the four smallest pieces that turn a bag of nodes into a runnable program. Here is the full lifecycle of a tiny two-node graph.
How one router function plus a `path_map` dict lowers to exactly one edge firing per step.
A conditional edge is a router function plus a path map: the router reads state and returns a key, the path map turns that key into the next node. This is how branching (and, next post, loops) are expressed.
The single most important pattern in LangGraph — a branch plus a back-edge, and the `recursion_limit` that keeps it from running forever.
Branching plus a back-edge is a cycle, and that cycle IS the agent loop: model proposes tool calls, tools run, control returns to the model, repeat until done. Plus recursion_limit, the guardrail that stops a runaway loop.
How a single `Command` object folds a state update and a routing decision together — and the tiny lowering that makes `goto` just another guarded edge.
Command lets a node return a state update and a goto in one object, moving the routing decision inside the node. It is the cleanest way to express supervisor handoffs and dynamic control flow.
Watching a LangGraph run happen — the three things `.stream()` can show you, and why they fall out of the superstep model for free.
stream() exposes a run in three modes: values (full state after each node), updates (what each node changed), and debug (the raw event stream). Streaming falls out naturally from the superstep model.
How a checkpointer turns a graph run into something you can stop, reload, and replay from any point in its history.
A checkpointer saves state at every superstep boundary, so a run can pause, resume on a thread_id, and even fork from an earlier checkpoint (time-travel). This is the foundation human-in-the-loop is built on.
The higher-level building blocks LangGraph stacks on top of the graph engine — pausing for a human, running an agent loop, calling tools, and fanning out dynamically.
The building blocks on top of the core graph: interrupt() to pause for human input, create_react_agent and ToolNode for tool-using agents, and the Send API for dynamic parallel fan-out with a reducer fan-in.
The reference capstone — each term in the series, defined in plain English and grouped by what it does.
The capstone of the series: every LangGraph concept defined in one place — the graph model, state and reducers, persistence, human-in-the-loop, agents and tools, parallelism, streaming, and the surrounding ecosystem.
This series is part of a larger body of work by Pratik Dhanave, an Agentic AI Architect writing about production AI systems, distributed systems, and cloud-native engineering. Explore all course series, browse every post, or find topics via the tag index.