Multi-agent and Orchestration|INEMA.CLUB-PRO

Lesson 3 · 20 min

Orchestrator-workers and fan-out

Fan-out is an orchestrator releasing N workers on independent items and gathering only what matters. It works when each item fits in a clear request, has a cap, and returns a line you can check. In this lesson you run a shell fan-out with a fake agent, watch the time drop, and redo only the rejected item.

Start the lesson
A thick cable that splits into five thin cables connected to five identical modules with a green LED.

In this lesson you will

  1. 1The forms of fan-out in Claude Code and in the shell
  2. 2The delegation request: goal, format, sources, and boundaries
  3. 3Cap per worker and return in a file
  4. 4Consolidate by the last line and redo only the rejected one

Goal: run a fan-out with N workers, a cap per item, and a short consolidation, redoing only the rejected item.

01A fan-out with control

The orchestrator plans and merges; the workers only do their part. Click each step.

Click each block in the diagram to see what it does.

A fan-out of 500 mechanical files needs no model at all: it's a script. An agent comes in when each item requires judgment.

02The forms of fan-out today

Per the Claude Code docs (Run agents in parallel, read on Oct 19, 2026) and Codex CLI 0.163.0.

1. Subagents

Ask for several subagents in the same message. The results come back to the conversation that created them.

For a large, repeatable batch, the docs point to dynamic workflows (a script that runs many subagents and compares their results) and /batch, which splits a large change across 5 to 30 subagents, each in its own worktree.

03Fan-out in shell, with a rehearsal

The AGENTE is any command that reads the request on stdin. For the rehearsal, use a script that sleeps 2 s and answers.

fanout.sh · save it in ~/treino-multi/
#!/usr/bin/env bash
# fanout.sh — one worker per line of the list, N at a time, short return in a file.
# Usage: fanout.sh <lista.txt> <pasta-saida> [N]
#   AGENTE = command that reads the request on stdin (default: claude -p). For a rehearsal: a fake script.
#   TETO   = seconds per worker (default 600)
set -u
LISTA="${1:?uso: fanout.sh <lista.txt> <pasta-saida> [N]}"; OUT="${2:?pasta de saída}"; N="${3:-3}"
export OUT AGENTE="${AGENTE:-claude -p}" TETO="${TETO:-600}"
mkdir -p "$OUT"

trabalho() {
  item="$1"; nome=$(printf '%s' "$item" | tr -cs 'a-zA-Z0-9' '-' | cut -c1-40)
  if [ -s "$OUT/$nome.md" ] && [ "$(tail -1 "$OUT/$nome.md")" = OK ]; then
    echo "pula $nome (aprovado)"; return 0     # only the rejected one comes back
  fi
  printf 'Task: %s\nAnswer in at most 5 lines. Last line: OK, or FALHA: <reason>.\n' "$item" \
    | timeout "$TETO" $AGENTE > "$OUT/$nome.tmp" 2>&1
  rc=$?
  if [ $rc -eq 0 ]; then mv "$OUT/$nome.tmp" "$OUT/$nome.md"; echo "feito $nome"
  else mv "$OUT/$nome.tmp" "$OUT/$nome.erro"; echo "erro $nome (rc=$rc)"; fi
}
export -f trabalho

grep -v '^[[:space:]]*$' "$LISTA" | xargs -d '\n' -P "$N" -I{} bash -c 'trabalho "$1"' _ {}

# the orchestrator merges only the last lines: that is what goes back into its context
for f in "$OUT"/*.md; do [ -e "$f" ] && printf '%s: %s\n' "$(basename "$f" .md)" "$(tail -1 "$f")"; done > "$OUT/../consolidado.txt"
echo "itens: $(grep -cv '^[[:space:]]*$' "$LISTA") · feitos: $(ls "$OUT"/*.md 2>/dev/null | wc -l) · com erro: $(ls "$OUT"/*.erro 2>/dev/null | wc -l) · OK: $(grep -c ': OK$' "$OUT/../consolidado.txt") · FALHA: $(grep -c ': FALHA' "$OUT/../consolidado.txt")"
Terminal · no-quota rehearsal (fake agent)
cd ~/treino-multi && chmod +x fanout.sh
E=${TMPDIR:-/tmp}/ensaio-multi/fanout; rm -rf $E && mkdir -p $E
cat > $E/agente-falso.sh <<'SH'
#!/usr/bin/env bash
pedido=$(cat); sleep 2
case "$pedido" in
  *quebrado*) printf 'não consegui ler o arquivo\nFALHA: arquivo quebrado\n' ;;
  *) printf 'resumo de uma linha\nOK\n' ;;
esac
SH
chmod +x $E/agente-falso.sh
printf 'resumir docs/a.md\nresumir docs/b.md\nresumir docs/quebrado.md\nresumir docs/c.md\nresumir docs/d.md\n' > $E/lista.txt

time AGENTE=$E/agente-falso.sh ./fanout.sh $E/lista.txt $E/saida 1   # one at a time
rm -rf $E/saida
time AGENTE=$E/agente-falso.sh ./fanout.sh $E/lista.txt $E/saida 3   # three at a time
AGENTE=$E/agente-falso.sh ./fanout.sh $E/lista.txt $E/saida 3        # again: nothing is redone
cat $E/consolidado.txt
Terminal · real, with 2 or 3 items from your project
cd ~/treino-multi
printf 'Resuma runtime/POLITICA.md em 3 linhas\nResuma runtime/ROTEAMENTO.md em 3 linhas\n' > lista-real.txt
./fanout.sh lista-real.txt real/saida 2 < /dev/null
cat real/consolidado.txt
Example from the repository
feito resumir-docs-a-md
feito resumir-docs-b-md
feito resumir-docs-quebrado-md
feito resumir-docs-c-md
feito resumir-docs-d-md
itens: 5 · feitos: 5 · com erro: 0 · OK: 4 · FALHA: 1

real	0m10.094s
(…)
feito resumir-docs-a-md
feito resumir-docs-b-md
feito resumir-docs-quebrado-md
feito resumir-docs-d-md
feito resumir-docs-c-md
itens: 5 · feitos: 5 · com erro: 0 · OK: 4 · FALHA: 1

real	0m4.054s
(…)
pula resumir-docs-b-md (aprovado)
pula resumir-docs-a-md (aprovado)
pula resumir-docs-c-md (aprovado)
pula resumir-docs-d-md (aprovado)
feito resumir-docs-quebrado-md
itens: 5 · feitos: 5 · com erro: 0 · OK: 4 · FALHA: 1
resumir-docs-a-md: OK
resumir-docs-b-md: OK
resumir-docs-c-md: OK
resumir-docs-d-md: OK
resumir-docs-quebrado-md: FALHA: arquivo quebrado

Cuts: the user/sys lines from time. The time dropped from 10 s to 4 s because the fake agent only sleeps: it shows the shape of the gain, not the measurement of a real agent. In the third round, only the rejected item ran again.

04The delegation request

When the fan-out happens inside the session, you are the orchestrator, making the request. The four fields come from Anthropic's post.

Prompt · fan-out with subagents in one session
Split this into subagents, one per item in the list below, all in the same message.
For each subagent, write:
- Goal: <what this item needs to answer>
- Output format: at most 5 lines; last line OK or FALHA: <reason>; write to saida/<item>.md
- Sources and tools: <files or folders it may read>; do not edit anything outside saida/
- Boundary: do not handle the other items; if it depends on another item, stop and say which one
Then read only the last line of each file and give me the item → OK/FALHA table.
Items:
<item 1>
<item 2>
<item 3>

05Practice

Rehearsal first; then two real items.

E5 · Fan-out with a fake agent

10 min

Save fanout.sh and run the whole rehearsal.

Done when: the N=1 round takes about 10 s and the N=3 round about 4 s; both print OK: 4 · FALHA: 1; the third prints four pula … (aprovado) lines and one feito resumir-docs-quebrado-md.

E6 · Two real items

10 min

Run the real block (it uses claude -p, through your subscription). If an item comes out FALHA, read only its file and run fanout.sh again.

Done when: cat real/consolidado.txt shows 2 lines, each ending in OK or FALHA: …, and ls real/saida/*.erro finds nothing.

06Lesson quiz

Question 1 of 4

Why does the orchestrator read only the last line of each result?skill

07In three sentences

Frozen itemsOnly what doesn't depend on another item goes into the fan-out; the rest goes before or after.
Cap and fileEach worker with a timeout, a saved result, and a last line of OK or FALHA.
Only the failed one comes backThe orchestrator reads the last lines and reruns only what failed.

Going further

Previous lessonNext lesson