Chapter 4 of 5
Orchestrator-Workers
The workflow that blurs into agency — a central LLM dynamically breaks down the task, delegates to workers, and synthesizes. Subtasks aren't predefined.
Orchestrator-Workers
In the orchestrator-workers workflow, a central LLM dynamically breaks down tasks, delegates them to worker LLMs, and synthesizes their results. (source)
┌→ [worker: file A] ─┐
[task] → [orchestrator] ┼→ [worker: file B] ─┼→ [synthesize] → output
└→ [worker: file C] ─┘
How it differs from parallelization
This is the key distinction, and it's easy to miss:
- Parallelization fans out to predefined subtasks. You wrote down the branches in advance.
- Orchestrator-workers fans out to subtasks the orchestrator decides on, based on the specific input.
Topographically they look similar — one input, many workers, one aggregated output. The difference is who decides the workers: you (parallelization) or the model (orchestrator-workers).
When to use it
This pattern fits complex tasks where you can't predict the subtasks.
In coding, for example: the number of files that need to change, and the nature of the change in each, depends on the task. A "refactor the auth module" task might touch 2 files or 12 — you can't know until someone looks. The orchestrator looks, decides which workers to spin up, and each worker handles one file.
# The orchestrator decides the plan
plan = orchestrator_llm(f"Break this task into file-level subtasks: {task}")
# plan = [{"file": "auth/login.ts", "change": "..."}, {"file": "auth/token.ts", "change": "..."}]
# Workers execute in parallel, each on one file
results = [worker_llm(subtask) for subtask in plan]
# Synthesize — the orchestrator (or you) merge and verify
final = merge_and_verify(results)
Other examples:
- Search tasks that gather and analyze information from multiple sources, where the relevant sources depend on the query.
- Any task where the work unit is "go figure out what needs doing, then do the pieces."
The bridge to full agents
Orchestrator-workers is the pattern where a workflow starts to feel like an agent — the model is making decisions about what to do. But it's still bounded: it decides the breakdown once, executes, and stops. A full agent (next course) loops this — decide, act, observe, decide again. If orchestrator-workers is a fan-out, an agent is a fan-out that keeps fanning until the goal is met.
When NOT to use it
If you can predict the subtasks, use plain parallelization. Orchestrator-workers adds an LLM call (the orchestrator's planning step) and a synthesis step. That's worth it when the planning genuinely varies; it's waste when the plan is always the same.
# If the plan is always the same, just write it:
results = [worker_a(task), worker_b(task), worker_c(task)] # parallelization
# Don't pay an orchestrator to rediscover a fixed plan.
What you've now seen
You now know four workflows — chaining, routing, parallelization, orchestrator-workers — plus the augmented LLM they all stand on. The fifth workflow, evaluator-optimizer, is the one that turns a workflow into a loop, and it's where the next course picks up.
The thread connecting all of them: the path is partly or fully written down, and complexity is added only when it demonstrably helps. That discipline is what separates a system that ships from one that spirals.
Next: Designing Tools for Agents (ACI) — the unsung skill that determines whether any of these patterns actually work.