One node, many items
Lesson 9 ran two different nodes side by side. This is how you run the same node once per item, when you do not know until the run starts how many items there are.
Twenty tickets arrive. Each one needs an answer, and you cannot draw twenty nodes because tomorrow there will be five.
Two states, one big and one small
The outer state holds all the tickets. The inner one holds a single ticket, and that is all a worker ever sees.
import operator
from typing import Annotated
from typing_extensions import TypedDict
class State(TypedDict):
tickets: list
replies: Annotated[list, operator.add]
class One(TypedDict):
ticket: strreplies gets the reducer from lesson 10. Every copy of the worker finishes in the same step and all of them write to that key, which is exactly the situation that needed one.
The worker, and the thing that hands out work
def answer(state: One):
return {"replies": [f"re: {state['ticket']}"]}It takes a different state class. This node never sees the ticket list, only the one ticket it was handed, which is what makes it easy to write and easy to reuse.
from langgraph.types import Send
def fan_out(state):
return [Send("answer", {"ticket": t}) for t in state["tickets"]]Send means run this node with this state, not the whole state, only what you hand it. Returning a list of three means three runs of the same node, side by side, in one step.
fan_out goes in a conditional edge, exactly like pick_team in lesson 6. The difference is that instead of one node name it returns a list of Send objects, each carrying its own small state.
Wire it and run it
from langgraph.graph import StateGraph, START
builder = StateGraph(State)
builder.add_node("answer", answer)
builder.add_conditional_edges(START, fan_out, ["answer"])tickets = ["late", "wrong size", "charged twice"]
print(builder.compile().invoke({"tickets": tickets, "replies": []})["replies"])Three tickets in, three replies out, and the number came from the data rather than from how many edges you drew. This is the pattern people call map and reduce: split the work, do the pieces side by side, and let a reducer put the answers back together.
- Add a fourth ticket and confirm nothing else changes.
- Take
operator.addoffrepliesand read the error. - Send an index with each ticket and print it in the reply.
Slow is fine. Stopping is the only problem.