LangGraph Module 3: Conditional Edges, Routing, and Loops
Introduction
Straight-line graphs are only the start. Real workflows branch, loop, and retry based on what has happened so far. LangGraph supports this through conditional edges, where a function looks at the state and chooses the next node, and through Command, where a node chooses its own successor.
Prerequisites
- Modules 1 and 2 completed
Step-by-Step Guide
Step 1: Write a routing function
A routing function receives the state and returns the name of the next node. It makes no state changes; its only job is to choose.
from typing_extensions import TypedDict
class State(TypedDict):
question: str
category: str
answer: str
def route(state: State) -> str:
return state["category"] # "math" or "chat"Step 2: Add conditional edges
A node first records its decision in state, then add_conditional_edges takes the source node, the routing function, and optionally a mapping from the function's return values to node names. Each target node then connects onward as usual.
from langgraph.graph import StateGraph, START, END
def classify(state: State) -> dict:
has_digit = any(character.isdigit() for character in state["question"])
return {"category": "math" if has_digit else "chat"}
def math_node(state: State) -> dict:
return {"answer": "That looks like a math question."}
def chat_node(state: State) -> dict:
return {"answer": "That looks like a general question."}
builder = StateGraph(State)
builder.add_node("classify", classify)
builder.add_node("math", math_node)
builder.add_node("chat", chat_node)
builder.add_edge(START, "classify")
builder.add_conditional_edges(
"classify", route, {"math": "math", "chat": "chat"}
)
builder.add_edge("math", END)
builder.add_edge("chat", END)
graph = builder.compile()
print(graph.invoke({"question": "What is 12 * 7?", "category": "", "answer": ""}))Step 3: Create a loop with a retry limit
A loop is just a conditional edge that points back to an earlier node. Always include a counter or another stopping condition, so the graph cannot run forever.
class RetryState(TypedDict):
attempts: int
ok: bool
def try_task(state: RetryState) -> dict:
attempts = state["attempts"] + 1
return {"attempts": attempts, "ok": attempts >= 3} # pretend it succeeds on try 3
def should_retry(state: RetryState) -> str:
if state["ok"] or state["attempts"] >= 5:
return "done"
return "again"
builder = StateGraph(RetryState)
builder.add_node("try_task", try_task)
builder.add_edge(START, "try_task")
builder.add_conditional_edges(
"try_task", should_retry, {"done": END, "again": "try_task"}
)
graph = builder.compile()
print(graph.invoke({"attempts": 0, "ok": False}))Step 4: Let a node choose with Command
A node can return a Command that both updates state and says where to go next, which keeps the decision next to the logic that makes it. Annotate the return type with the possible destinations so the graph can be drawn and validated. Don't also add a normal edge from the same node, because both paths could run.
from typing import Literal
from langgraph.types import Command
def triage(state: State) -> Command[Literal["math", "chat"]]:
goto = "math" if any(c.isdigit() for c in state["question"]) else "chat"
return Command(update={"answer": "triaged"}, goto=goto)Step 5: Visualize the graph
Drawing the graph is a quick way to check your wiring. In a notebook, the compiled graph can render a diagram, and there are text-based options too, so check the visualization section of the documentation for your setup.
# In a Jupyter notebook:
from IPython.display import Image, display
display(Image(graph.get_graph().draw_mermaid_png()))FAQs
- Conditional edge or Command: which should I use?
- Use conditional edges when routing is separate from the node's work, which keeps nodes reusable. Use Command when the node already has the information and you want the update and the routing together.
- How do I stop an infinite loop?
- Add an explicit counter or condition in state and check it in the routing function. LangGraph also enforces a recursion limit as a safety net, but you should not rely on it as your stopping rule.
Summary
Conditional edges route on state, loops are edges that point backward with a stop condition, and Command lets a node update state and choose the next step together.
Comments
Log in or create a free account to join the discussion.