A graph that always follows the same edge cannot send passing and failing results to different handlers. LangGraph conditional edges let state produced by one node select the next node at runtime.
A routing function runs after its source node and returns a label. The add_conditional_edges() mapping translates that label to a destination node, which keeps decision vocabulary separate from node names and makes each branch straightforward to test.
The program uses a TypedDict state, one evaluation node, and two terminal branches without an external model or API key. Invoking the compiled graph with scores above and below the threshold proves that both labels reach their intended nodes.
Related: Build a state graph in LangGraph
Related: Inspect route execution events
from typing import Literal from typing_extensions import NotRequired, TypedDict from langgraph.graph import END, START, StateGraph class RouteState(TypedDict): score: int result: NotRequired[str] message: NotRequired[str]
def evaluate_score(state: RouteState) -> dict[str, str]: result = "passed" if state["score"] >= 70 else "failed" return {"result": result} def accept_score(state: RouteState) -> dict[str, str]: return {"message": "accepted for review"} def reject_score(state: RouteState) -> dict[str, str]: return {"message": "returned for revision"}
def route_result(state: RouteState) -> Literal["passed", "failed"]: return "passed" if state["result"] == "passed" else "failed"
The return annotation documents every label the selector can emit. Each label must appear in the conditional mapping.
builder = StateGraph(RouteState)
builder.add_node("evaluate", evaluate_score) builder.add_node("accept", accept_score) builder.add_node("reject", reject_score)
builder.add_edge(START, "evaluate")
builder.add_conditional_edges( "evaluate", route_result, {"passed": "accept", "failed": "reject"}, )
A source node should have one routing mechanism because normal and conditional outgoing edges can schedule both paths.
builder.add_edge("accept", END) builder.add_edge("reject", END)
graph = builder.compile()
for score in (84, 42): final_state = graph.invoke({"score": score}) print( f"score={score} route={final_state['result']} " f"message={final_state['message']}" )
$ python conditional_route.py score=84 route=passed message=accepted for review score=42 route=failed message=returned for revision