Agent patternsPatternValidated

Orchestrator-workers

Also called: coordinator pattern, manager-worker

Orchestrator-workers has a central model decide how to break a task down at run time, dispatch the pieces to workers, and combine what comes back. It is parallelization for tasks whose shape you cannot know in advance.

James Phoenix
Understanding Data Updated July 26, 2026

Parallelization assumes you know the split when you write the code: six criteria, six calls. Plenty of real tasks are not like that. "Update every call site affected by this API change" has a shape that depends on the codebase, and you cannot enumerate the subtasks in advance.

Orchestrator-workers moves the decomposition to run time. A central model looks at the task, decides what the subtasks are, dispatches them, and synthesises the results.

Text
                 ┌─────────────┐
    task ──────► │ orchestrator│ ── decides the split at run time
                 └──────┬──────┘
              ┌─────────┼─────────┐
           worker    worker    worker      ── each gets one scoped subtask
              └─────────┼─────────┘
                 ┌──────▼──────┐
                 │ synthesise  │
                 └─────────────┘

In code, the shape is three calls with a fan-out in the middle:

TypeScript
// 1. the orchestrator decides the split, returning structure rather than prose
const { object: plan } = await generateObject({
  model,
  schema: z.object({
    subtasks: z.array(z.object({ file: z.string(), instruction: z.string() })),
  }),
  prompt: `Break this into independent subtasks: ${task}`,
})

// 2. workers run concurrently, each with a clean context holding only its piece
const results = await Promise.all(
  plan.subtasks.map((s) => runWorker(s.instruction, s.file))
)

// 3. synthesis, which sees results and not the workers' intermediate noise
return synthesise(task, results)

Note what the orchestrator never sees: how each worker got there. It receives outcomes, which is what keeps its own context small enough to reason about the whole job.

What it buys

  • The split adapts. Three files or thirty, the same code handles it.
  • Workers get clean context. Each sees one subtask, not the whole job, which is usually why quality improves rather than just latency.
  • The orchestrator keeps the overview without holding every worker's intermediate noise. It sees results, not transcripts.

Where it goes wrong

  • Bad decomposition is invisible. If the orchestrator splits badly, every worker does good work on the wrong pieces, and the output looks thorough. This is the failure mode to watch, and it argues for logging the plan the orchestrator produced.
  • Synthesis is the hard part. Combining conflicting worker output is genuinely difficult, and it is where the pattern is usually underbuilt.
  • Cost multiplies. One task becomes N+2 calls. For a task with a knowable split, plain parallelization is cheaper and more predictable.

When to reach for it

Only when the decomposition genuinely cannot be written in advance. If you find yourself able to describe the subtasks while writing the prompt, you want parallelization or prompt chaining, both of which are easier to debug.

Note
Workers writing to the same files at the same time is a collision problem, not a prompting problem. Give each an isolated working copy, or scope them to disjoint areas and enforce it in code.

Related terms

Engineering context for real systems?

Getting the right information into the window at the right time is most of the job. If you want that thinking applied to your product, that is what I do.

See how I can help