Route to search, confirm, and smalltalk

The router wrote intent and maybe some slots into state. Now we need to turn that into a routing decision: which node runs next? LangGraph supports conditional edges, where a plain Python function reads the state and returns the name of the next node.

booking_graph.py
python
def route_from_intent(state: BookingState) -> str:
    intent = state.get("_intent")
    stage = state.get("stage") or "routing"
    choice = state.get("_choice_index")

    # Already proposed options
    if stage == "proposing":
        if choice or intent == "confirm":
            return "confirm_booking"
        return "propose_options"
    if intent == "confirm":
        return "confirm_booking"
    if intent == "smalltalk":
        return "smalltalk"

    # Booking flow: fill slots in order
    if not state.get("origin"):
        return "collect_origin"
    if not state.get("destination"):
        return "collect_destination"
    if not state.get("depart_date"):
        return "collect_dates"
    return "search_flights"

The router is stateless: it reads the current state and returns a string. Stage is checked first because it carries conversational context that the slots alone cannot express.

booking_graph.py
python
graph.add_node("intent_router", intent_router)
graph.add_node("collect_origin", collect_origin)
graph.add_node("collect_destination", collect_destination)
graph.add_node("collect_dates", collect_dates)
graph.add_node("search_flights", search_flights_node)
graph.add_node("propose_options", propose_options)
graph.add_node("confirm_booking", confirm_booking)
graph.add_node("smalltalk", smalltalk)

graph.set_entry_point("intent_router")

graph.add_conditional_edges(
    "intent_router",
    route_from_intent,
    {
        "collect_origin": "collect_origin",
        "collect_destination": "collect_destination",
        "collect_dates": "collect_dates",
        "search_flights": "search_flights",
        "propose_options": "propose_options",
        "confirm_booking": "confirm_booking",
        "smalltalk": "smalltalk",
    },
)

Every node is registered by name, the entry point is always the router, and the conditional-edges mapping turns the routing function output into a concrete next node.

Ordering exercise: Order the checks inside route_from_intent

Loading practice…

Quiz: Quiz

Loading practice…

Checkpoint: Router and edges checkpoint

Loading practice…