LangGraphLangGraph 1.2 · Python 3.10+
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
37 small wins to finish your pathNext lesson

Routing from inside a node

Sometimes the node doing the work already knows where the run should go next. Returning a Command lets it update the state and choose the next node together.

Look back at lesson 6. The ticket was read twice: once by pick_team to choose a route, and the node it chose never learned what the decision was. If one function already knows, it can record the answer and name the destination in one go.

A state that keeps the decision

python
from typing_extensions import TypedDict

class State(TypedDict):
    ticket: str
    category: str
    reply: str

A node that decides and routes

This is the whole idea of the lesson, in five lines.

python
from typing import Literal
from langgraph.types import Command

def read_ticket(state) -> Command[Literal["billing", "technical"]]:
    if "charge" in state["ticket"]:
        return Command(update={"category": "billing"}, goto="billing")
    return Command(update={"category": "technical"}, goto="technical")

update does what a normal return value does, and goto names the node to run next. The return type listing the two destinations is what lets LangGraph work out the shape of the graph, which is why there is no conditional edge anywhere below.

The two replies

python
def billing(state):
    return {"reply": "We will refund the double charge."}

def technical(state):
    return {"reply": "Try logging out and back in."}

Wiring, with one edge missing

Count the edges. There is only one, into the first node. Nothing says what happens after read_ticket, because read_ticket says it itself.

python
from langgraph.graph import StateGraph, START

builder = StateGraph(State)
builder.add_node("read_ticket", read_ticket)
builder.add_node("billing", billing)
builder.add_node("technical", technical)
builder.add_edge(START, "read_ticket")
Example
print(builder.compile().invoke({"ticket": "charged twice", "category": "", "reply": ""}))

The category is in the result as well as the reply, which is the thing lesson 6 could not do. The routing decision was worth keeping, and the node that made it wrote it down.

Which one should you use

SituationUse
The node doing the work also decides the routeCommand
The decision is separate, or several nodes share one routera conditional edge
The routing rule is long and you want it in one obvious placea conditional edge

Both are correct and you will meet both in real code. A conditional edge keeps the decision outside the work, which reads better when the rule is long. A Command keeps it beside the thing that knows, which reads better when the rule is short.

You will see Command again
Command comes back twice more. In lesson 23 you send one into a graph to answer a question it stopped to ask, and a tool can return one to change the state as well as reply.
Try it yourself
  • Add a third route for tickets containing password, and add it to the Literal.
  • Remove update= and check the category in the result.
  • Print the graph's edges with and without the return type hint, and compare.

Little by little, you're building something great.