Mod 3.1Implementing Conditional Edges in LangGraph
Level 3›Module 3.1
Level 3: Advanced Patterns & System DesignModule 3.1

Implementing Conditional Edges in LangGraph

Conditional Edges

Level 3 • Advanced Patterns & System Design
Est. ~21 mins
5 Key Topics
🎁 Free Learner Perk

Unlock Verified Certificate & Daily Streak Tracker

Ready to master Implementing Conditional Edges in LangGraph? Enable cloud sync to record your daily streak 🔥 and earn your Informational Completion Badge for your study milestones.

Day 1 Streak ActiveFree Completion BadgeSync Laptop & Phone

🎯 By the end of this module, you will:

Explain the 3 components of a conditional edge: source node, routing function, path map
Write a Literal-typed routing function that inspects tool_calls to decide the next step
Wire add_conditional_edges() with a path map dictionary into a LangGraph builder
Extend to N-way routing for multi-specialist triage workflows
Conditional Routing • Dynamic Edges

Implementing Conditional Edges in LangGraph

Standard pipelines flow in a straight line. Real agents make decisions. Conditional edges are the railway switches of LangGraph — they inspect current state and dynamically route execution to the right destination node.

1. Source Node: Where It Begins
# SOURCE NODE: The node whose output triggers the routing decision
# This runs the LLM and updates state["messages"]

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

model = ChatOpenAI(model="gpt-4o-mini").bind_tools([search_web, get_weather])

def agent_node(state: AgentState) -> dict:
    """Calls LLM with tool bindings — result drives routing decision."""
    response = model.invoke(state["messages"])
    # State update: routing function will inspect this later
    return {"messages": [response]}

# After agent_node runs:
#   - If LLM chose to call a tool → response.tool_calls is non-empty
#   - If LLM wrote a final answer → response.tool_calls is empty
# The routing function reads this to decide where to go next

🔬 Railway Switch Simulator

Conditional Edge Railway Switch Simulator

See how a routing function inspects state and flips the execution track in real time

Source Node: [agent_model]Conditional Edge: should_continue()
Source Node
agent_model
Updates state
state evaluation
Routing Logic
should_continue(state)
Returns string key
path map
🛠️ "call_tools"
🏁 END (Finished)
👤 "human_review"
Active Rule: State has tool_calls in last message. Router switches track to 'call_tools'.
1. Source Node

Where the edge starts: "agent_model"

2. Routing Function

Inspects state dict: def should_continue(state): ...

3. Path Map Dictionary

Maps returns to nodes: {"continue": "tools", "stop": END}

✍️ Instructor Note: "The routing function is the ONLY place where you decide WHERE to go. Never put routing logic inside a node. Nodes do work. Routers make decisions. Keep them completely separate — this is the core architectural rule."
📌 Golden Rule: Routing functions must be PURE — read-only, no side effects, <1ms. If your routing logic requires a DB lookup or LLM call, move that logic into a dedicated predecessor node and store the result in state for the router to read.

Conditional Edge Traps

TRAP #1: Incomplete Path Map

If your routing function returns "retry" but your path map only has keys for "call_tools" and "__end__", LangGraph will raise a KeyError at runtime. Always ensure every possible return value of your routing function has a corresponding key in the path map.

TRAP #2: No Loop Ceiling

A cyclic edge (tools → agent → tools → ...) with no escape condition creates an infinite loop that burns tokens until your budget limit hits. Always add a loop_count field to state and route to END when loop_count exceeds your maximum iteration threshold.

Key Takeaways

  • 1.3 Components, Not 1: add_conditional_edges() needs all three: source node, routing function, path map. The path map is what makes the routing function's string output meaningful — without it, the string has no target.
  • 2.Typing Prevents Runtime Errors: Use Literal['call_tools', '__end__'] as the return type of routing functions. This lets TypeScript/pyright catch missing path map keys at write-time, before any runtime error.
  • 3.Always Add a Loop Ceiling: Any cyclic conditional edge (agent ↔ tools loop) needs a termination condition. Add a recursion_limit parameter to builder.compile() or track iterations in state. A tool error without a ceiling = infinite loop.
Up Next • Module 3.2

Designing Custom Workflows with State Graphs

Master the 3 canonical graph topologies: Linear Pipelines, Cyclic Reflection Loops, and Branching Triage Networks.

Continue to Module 3.2