Lesson 5 / 29

Conditional Edges and Routing

Pick the next node from the state.

A function chooses the path

add_conditional_edges(source, router, mapping) runs router(state) after source and uses its return value to pick the next node. The router can be ordinary Python (keyword checks, thresholds) or read a label that an earlier classifier node produced, often with a small LLM call. Keep routers pure and cheap, return only known labels, and always cover the default case. Routing keeps each node simple: the classifier decides, specialised nodes act, and the graph shows the structure at a glance.

Decide, repeat, hand off, split

Conditional edges, loops with limits, Command hand-offs and Send fan-out cover most agent flows.

Five tools: branch, loop, limit, command, send.
Figure 2.1 — Branch, loop, limit, command and send.

Routing by category, run

I ran this offline with langgraph 1.2.12 and langchain-core 1.6.6 in a Python virtual environment. No API key or model is needed because plain Python functions stand in for the model, so the output is repeatable. A classify node sets a route; the conditional edge sends refund and invoice questions to billing and everything else to other.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):
    question: str
    route: str
    answer: str

def classify(state):
    q = state["question"].lower()
    return {"route": "billing" if "refund" in q or "invoice" in q else "other"}

def billing(state): return {"answer": "Routed to the billing team."}
def other(state):   return {"answer": "Routed to general support."}

g = StateGraph(State)
g.add_node("classify", classify); g.add_node("billing", billing); g.add_node("other", other)
g.add_edge(START, "classify")
g.add_conditional_edges("classify", lambda s: s["route"], {"billing": "billing", "other": "other"})
g.add_edge("billing", END); g.add_edge("other", END)
app = g.compile()
for q in ("I want a refund", "Where is your office?"):
    print(q, "->", app.invoke({"question": q})["answer"])

Output:

I want a refund -> Routed to the billing team.
Where is your office? -> Routed to general support.

Keep routers pure

A router should only read state and return a label. Do the work in nodes so routing stays easy to test.

Quick check: What should a router always cover?

  • Only the first label
  • A default path for unexpected labels
  • Nothing
  • A GPU
Answer

A default path for unexpected labels — Unhandled labels cause errors or dead ends.