Multi-agent · Free preview

Orchestrator and Workers

Fan out, gather back

An orchestrator splits a job into subtasks, dispatches each to a worker, and gathers the workers' results back in order into one combined answer.

Fan out, gather back

In the last lesson the router handed each task to one specialist. But some jobs aren't one task — they're a list. Imagine a security agent asked to "alert, scan, and report" on an incident. One agent grinding through all three in a single pass is slow, and if it stumbles on step two the whole answer is lost — and you can't even see which part failed, because the work happens in one opaque breath.

The orchestrator/workers pattern splits the job up. The orchestrator decomposes the goal into subtasks, fans out by handing each subtask to a fresh worker, then gathers the results back and combines them into one answer. The orchestrator never does the work itself — it delegates and assembles. Each worker is small and focused, so it's easy to reason about, easy to retry, and (in a real system) the fan-out can run in parallel.

The discipline is order. Say the subtasks are ["alert", "scan", "report"]. You dispatch them in that order; worker 1 returns ALERT (5), worker 2 returns SCAN (4), worker 3 returns REPORT (6). When you stitch the final line you must preserve that sequence — ALERT-5 | SCAN-4 | REPORT-6 — because the answer is meaningless if "report" shows up before "alert." In a parallel system the fastest worker finishes first, so you can't append results as they arrive; you slot each into the position it was dispatched from.

Fan-out is how multi-agent systems get both speed and traceability. The per-worker trace (worker 1: ...) is your audit log: when one step is wrong you see exactly which worker produced it, instead of debugging a single blob.

Below, the worker is written for you — give it one subtask, it returns one result. The starter cheats by doing everything inline in a single line. Replace that with a real dispatch: loop over the subtasks, call worker() for each, push results into an array in dispatch order, print worker <i>: <result> as you go (i starting at 1), then print the combined final: line.

Order is the contract. Fanning out is easy; the discipline is gathering the results back in the same order you sent them, so the combined answer lines up.

In the full academy, you write and run this — live, graded:

// The orchestrator gets a job: a list of subtasks to process.
const subtasks = ["alert", "scan", "report"];

// 🔧 A worker. Give it ONE subtask, it returns ONE computed result.
//    Here: upper-case the word and tag it with its length, e.g. "ALERT (5)".
function worker(task) {
  const up = task.toUpperCase();
  return `${up} (${task.length})`;
}

// ❌ Right now the orchestrator does everything inline in one breath —
//    no fan-out, no per-worker trace. Replace this with a real dispatch.
const combined = subtasks.map((t) => t.toUpperCase()).join("-");
console.log(`final: ${combined}`);

// TODO: dispatch EACH subtask to worker(), collect the results IN ORDER,
//       print "worker <i>: <result>" for each (i starting at 1),
//       then print "final: " + the results joined as "WORD-LEN | WORD-LEN | ...".

🔒 Live code execution, real agent runs, mastery tracking and verifiable credentials unlock with the full academy.

This is 1 of 50 lessons.

The full academy: write real code, watch real agents run, and earn verifiable credentials — across 8 tracks, in a 3D campus.

Unlock the full academy — $100 →

14-day refund · 🔒 Stripe-secured checkout · lifetime access

More free lessons: An LLM Is a Function  ·  The Agent Loop  ·  Define a Tool  ·  Give an Agent a Tool  ·  Durable State

← The Agent Marketplace