RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /LangGraph for Local Agents
  6. /Ch. 9
LangGraph for Local Agents

09. Multi-Agent Teams

Chapter 9 of 18 · 20 min
KEY INSIGHT

Multi-agent teams use a shared typed state with per-agent write keys. The supervisor pattern is a polling dispatch model—each turn, the supervisor decides who goes next and workers report back into shared state.

A multi-agent team in LangGraph is a supervisor node that dispatches tasks to specialized worker nodes, each of which may itself be a compiled sub-graph. The pattern has three layers: a team state shared by all agents, a supervisor that routes work to idle workers, and worker nodes that perform domain-specific tasks and write results back to shared state.

class TeamState(TypedDict):
    task: str
    assignments: Annotated[list[str], add]
    results: dict[str, str]
    next_worker: Literal["researcher", "coder", "done"]

The supervisor node implements the routing logic. Rather than branching via conditional edges alone, the supervisor returns a next_worker string that a conditional edge uses:

def supervisor(state: TeamState) -> TeamState:
    task = state["task"]
    pending = [w for w in ["researcher", "coder"] if w not in state["assignments"]]
    if not pending:
        return {"next_worker": "done"}
    chosen = pending[0]
    return {"next_worker": chosen, "assignments": [chosen]}

The conditional edge maps next_worker to actual node names:

builder.add_conditional_edges(
    "supervisor",
    lambda s: s["next_worker"],
    {"researcher": "researcher", "coder": "coder", "done": END}
)

Workers write their outputs into the shared results dict keyed by their agent name. The supervisor reads this dict after each worker completes to synthesize or decide the next step. This pattern cleanly separates concerns: the supervisor handles orchestration logic; workers handle domain execution.

Local verification checkpoint

Run the smallest example from this chapter in a local workspace and record the package version, runtime, data path, and observed output. If the result depends on model size, vector count, CPU/GPU backend, or available memory, note that constraint beside the exercise so the lesson remains reproducible.

EXERCISE

Build a two-worker team (researcher and coder) with a supervisor. Add a summarizer node that the supervisor calls after both workers complete. Use conditional routing to confirm the summarizer only runs after both workers have reported.

← Chapter 8
Checkpointing
Chapter 10 →
Supervisor Agent