Chapter 3 · Conditional routing and bounded loops
Use deterministic quality checks to choose revision or completion instead of delegating all control flow to a model. This bounded loop is the foundation of later tool-calling loops.
Mechanics and design choices
add_conditional_edges maps a routing function result to a target node. Increment attempts each round and stop according to business state. recursion_limit is a runtime guard, not the business objective. Cover every routing result and avoid mixing unconditional exit and conditional loop edges on the same node.
Example
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
attempts: int
score: int
def revise(state: State):
return {"attempts": state["attempts"] + 1, "score": state["score"] + 40}
def route(state: State):
return "done" if state["score"] >= 80 or state["attempts"] >= 3 else "again"
builder = StateGraph(State)
builder.add_node("revise", revise)
builder.add_edge(START, "revise")
builder.add_conditional_edges("revise", route, {"done": END, "again": "revise"})
graph = builder.compile()
result = graph.invoke({"attempts": 0, "score": 0}, {"recursion_limit": 10})
assert result == {"attempts": 2, "score": 80}
print(result)Run and verify
No model is needed. Expect exactly two revisions. Start at score -100 and verify that the attempt limit still stops execution at three.
Pitfalls
Raising recursion_limit does not fix an infinite loop. Record decisions and distinguish lack of model progress, repeated tool failures, and missing termination conditions.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. What defines business termination?
2. What is recursion_limit?
3. What do routing labels need?
4. How should an infinite loop be fixed?
Hands-on exercises
- Add a reason field distinguishing success from exhausted attempts.
- Test score=80, score=0, and score=-100 parametrically.
- Use a checker that always fails and verify bounded execution.
Official references
Verified on: 2026-09-17.