scalable/ai/langgraph agent teams/lesson 06 cph / /
lesson 06 / 08 · 13 min · updated ·

subgraphs and fan-out

a team as a subgraph, a swarm of workers via Send. map-reduce over agents, parallelism, and keeping team state private.

tl;dr. two scaling moves. subgraphs: a compiled graph is a node, so a whole team mounts inside a bigger graph as one box — team state stays private, shared keys flow through. fan-out: Send spawns n copies of a worker node at runtime — map-reduce over agents, with reducers doing the reduce. between them you get org charts and worker pools without new concepts.

teams as black boxes

a compiled team is just a node
// a team is a graph. a company of teams is a graph of graphs.
// compile the lesson-four team once — mount it as one node.

const engineering = buildSupervisorTeam(engWorkers).compile();
const content     = buildSupervisorTeam(contentWorkers).compile();

const org = new StateGraph(OrgState)
  .addNode("triage", triage)
  .addNode("engineering", engineering)   // an entire team, one node
  .addNode("content", content)
  .addEdge(START, "triage")
  .addConditionalEdges("triage", routeToTeam, ["engineering", "content"])
  .addEdge("engineering", END)
  .addEdge("content", END)
  .compile();

// shared state keys (messages) flow in and out automatically.
// the team's internal keys — draft, revisionCount, whose turn —
// stay private to the subgraph. teams hide their process
// and expose their results. organizations should be so lucky.

this is the composition rule that makes everything before it scale. the supervisor team from lesson four, the swarm from lesson five — once compiled, each is indistinguishable from a plain node. the parent graph routes between teams; each team routes within itself; neither layer can see the other's internals.

the state boundary is the useful part. parent and subgraph communicate through the keys they share (usually messages, or a typed result field); everything else in the team's annotation — the working draft, the revision counter, whose turn it is — is invisible outside. that's team topologies applied to software you can compile: teams hide their process and expose their interface, and cross-team coupling has to be declared in the shared keys, where you can see it in review.

fan-out with Send

review every changed file, in parallel, then join
import { Send } from "@langchain/langgraph";

// fan-out: one worker definition, n dynamic instances.
// Send() creates a task per item — the graph doesn't know n
// until runtime.

function fanOut(state: typeof ReviewState.State) {
  return state.files.map(
    (file) => new Send("reviewFile", { file, pr: state.pr }),
  );
}

async function reviewFile(input: { file: string; pr: string }) {
  const verdict = await reviewer.invoke(fileContext(input));
  return { findings: verdict.findings };   // reducer concatenates
}

const review = new StateGraph(ReviewState)
  .addNode("plan", plan)
  .addNode("reviewFile", reviewFile)
  .addNode("summarize", summarize)
  .addEdge(START, "plan")
  .addConditionalEdges("plan", fanOut, ["reviewFile"])
  .addEdge("reviewFile", "summarize")   // implicit barrier: summarize
  .addEdge("summarize", END)            // waits for ALL branches
  .compile();
this is the other "swarm." lesson five's swarm is one conversation moving between peers. this is many workers hammering a work-list simultaneously — the shape people mean by "agent swarms" when they talk about scale. the sdlc capstone uses fan-out for its review gates: qa, security, and legal are a Send per gate, not a queue.

parallelism has a bill

fan-out multiplies everything by n: tokens, cost, and rate-limit pressure. three habits keep it honest. size the worker's context to the item — the file reviewer gets the file and the pr description, not the whole conversation; Send's private input exists precisely so parallel workers don't each drag the full state through the api. match the model to the task — two hundred small reviews on the fast model with one strong-model synthesis at the barrier beats two hundred strong-model calls on both cost and, usually, quality. and cap n — a pr with 400 changed files should fan out over the 30 that matter and say so, not silently review everything. silent truncation is worse than a visible cap.

when it breaks

next: human gates — the pause button. interrupts, checkpoints, and approval as a node in the graph instead of a hope in the process.

scalable labs·cvr 30091604·github·linkedin·hello@scalable.dk