Zenaique

How conditional edges encode the routing decision in a LangGraph supervisor

Flashcard·Medium·4.0 · 0·~30s·Asked atAdaFractal AnalyticsLinkedin
Attempt it
TL;DR

A routing function reads the state and returns a node name (or END); LangGraph dispatches the edge to the named node. The LLM writes the decision into state; plain Python dispatches it.

Memory aid
Sign in to see the mnemonic that makes this stick.
Easy to grasp

Imagine a hotel concierge with a clipboard. A guest walks up, the concierge writes the next thing the guest should do (room, restaurant, gym) on the clipboard, and then a separate doorman reads the clipboard and points the guest the right way. The concierge can be moody and inconsistent (that is the language model), but the doorman is robotic and predictable: he reads exactly what is on the paper and never invents a destination. Splitting the decision (concierge) from the dispatch (doorman) means you can audit and unit-test the doorman even though the concierge is a black box. That split is what LangGraph's conditional edges encode.

Concept explanation~2 min read

Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.

LangGraph's conditional edges are the mechanism that turns a graph of LLM nodes into something an executor can actually run, trace, and resume. They encode a clean separation between the decision (an LLM call inside the supervisor node) and the dispatch (a deterministic Python function that reads state and returns a node name).

This separation is not a stylistic preference. It is the engineering choice that makes the rest of LangGraph work: testable routing, observable transitions, and resumable runs after a crash. Frameworks that collapse decision and dispatch into a single LLM emission (handoff tool calls, GroupChat selector LLMs) give up the same properties.

Mental model: the supervisor decides; the router dispatches. The split is the whole feature.

The routing function in detail

Signature and contract

A routing function has the shape:

python
def route(state: State) -> str:
    return state["next_agent"]

The input is the current state, the output is a string. The string must match one of the keys in the mapping you pass to add_conditional_edges, or it must be the END sentinel.

For parallel fan-out, the return type widens to list[str]: returning ["worker_a", "worker_b"] sends the same state to both nodes in parallel; the reducer at the join (per typed-channel rules) merges their state updates.

What the function must not do

The router is a pure function over state. It must not:

  • Call the LLM.
  • Make tool calls or side-effectful operations.
  • Mutate the state in place.
  • Depend on global state or random sources.

Violating any of these breaks resumability: a crash-resumed run reloads the state and re-runs the router, and if the router is non-deterministic, the resumed path can diverge from the original.

How the mapping ties it together

You register the edge with:

python
graph.add_conditional_edges(
    "supervisor",
    route,
    {"worker_a": "worker_a", "worker_b": "worker_b", "finish": END},
)

The first arg is the source node, the second is the router, the third is the mapping from return values to downstream nodes. If the router returns a value not in the mapping, LangGraph raises a ValueError. This is the safety mechanism that catches bugs early.

How the supervisor and router collaborate
Sentinels, parallel branches, and common patterns
Why this design wins over alternatives
Sign in to unlock the full deep dive.

Situations where this technique stops working.

Sign in to see when this approach fails.

2–4 min · Everything important, quickly.

Sign in to see the quick scan of the deep dive.

Real products, models, and research that use this idea.

  • LangGraph's create_supervisor prebuilt encodes exactly this pattern: a supervisor LLM call plus a conditional edge router.
  • Anthropic's published agent traces from 2025 show the same split (decide in the model, dispatch in Python) as a recommended pattern.
Sign in to see more production examples.

What an interviewer would ask next. Try answering before peeking at the approach.

QHow do you handle the case where the supervisor LLM returns an invalid node name (a typo or a hallucinated worker)?
A

Validate the LLM output in the supervisor node before writing to state (cast against a Literal type or a Pydantic enum). On invalid output, write a fallback value the router maps to a 'replanning' node that re-prompts the supervisor with a stricter instruction or escalates to a human. Never let invalid output reach the router; the router should assume valid state.

1 more follow-up an interviewer would ask next. Sign in to reveal them.

Red flags & common mistakes

The phrases that signal junior thinking. Click to expand.

Most common mistake

Letting the LLM directly determine control flow inside the routing function. The routing function should be pure Python over state; the LLM call belongs in the supervisor node that writes its decision into the state for the router to read.

Sign in to see all red flags and common mistakes.

60 second bullets to scan on the way to the call.

  • The signature of a routing function (state -> str or list[str])

  • How add_conditional_edges binds the function to the source node

Sign in to unlock the revision sheet.

Primary sources. Browse if you want the original framing.

Similar questions

Same topic, related formats. Practice these next.

4 curated
Next question
Why AutoGen 0.4 makes TerminationCondition a first class primitive instead of leaving it to convention
Flashcard·Medium