03. Nodes and Edges
Nodes are plain Python functions (or callable objects—LangChain Runnable instances also work) that receive the current state dict and return a dict of updates. Edges are the routing rules that determine which node executes next. There are three types: normal edges (add_edge("a", "b") means "after 'a' always go to 'b'"), conditional edges (add_conditional_edges routes by calling a routing function), and the special START/END sentinels.
A node that errors should raise an exception for LangGraph to catch in its error-handling layer, or return a special state marker that a conditional edge inspects. Raising exceptions inside a node is the standard pattern—LangGraph does not swallow them silently.
def orchestrator(state: AgentState) -> AgentState:
query = state["messages"][-1]
if "research" in query.lower():
worker = "researcher"
elif "code" in query.lower():
worker = "coder"
else:
worker = "generalist"
return {"active_worker": worker}
def researcher(state: AgentState) -> AgentState:
return {
"messages": state["messages"] + ["[researcher] gathering sources"],
"artifact": "mock research data"
}
builder.add_node("orchestrator", orchestrator)
builder.add_node("researcher", researcher)
builder.add_edge("orchestrator", "researcher")
Edges can also point to END, which terminates execution. Multiple nodes can point to the same node—this is a fan-in pattern. Only one node can point to START.
The failure mode: if two nodes declare an edge to a third node and only one of them has a defined edge leaving that target node, LangGraph raises InvalidEdgeError at compile() time. Every non-END node must have at least one outgoing edge defined (either normal or conditional). There is no implicit fall-through.
Local verification checkpoint
Run the smallest example from this chapter in a local workspace and record the package version, runtime, data path, and observed output. If the result depends on model size, vector count, CPU/GPU backend, or available memory, note that constraint beside the exercise so the lesson remains reproducible.
Build a graph with three nodes: router, worker_a, and worker_b. Make router inspect the state and return {"active_worker": "worker_a"} or {"active_worker": "worker_b"}. Use a conditional edge to route to the correct worker. Print the final state to confirm routing works for both branches.