Curriculum/Multi-Agent Systems
Reduce Is the Product
Map is easy. Never concatenate 200 traces into a supervisor prompt. Reduce down to a table: vote, merge ids, drop schema failures, list missing items.
Reduce is where swarms die. Map is easy: one function per item. Reduce is the product: a small table the parent is allowed to see. Never concatenate 200 raw traces into a supervisor prompt. That re-creates the context problem you split to avoid. The why-part’s context isolation applies to your own children.
Reduce strategies:
- Vote — majority label (only if labels are comparable)
- Merge lists — concat + dedupe with an id
- Cluster then summarize — for open-ended research, still a table of cluster ids, not 200 novels
- Verifier gate — drop workers that failed schema
A straggler on item 199 should not block forever: reduce with partials and mark missing ids. Timeouts are data. Pretending the child will arrive if you wait one more minute is how jobs never finish.
The parent assembler gets the reduce object: winner, counts, dropped, missing, maybe a page of top rows. It does not get child chain-of-thought. Thoughts stay on child traces for operators.
What reduce must do
| Job | Rule | Failure if skipped |
|---|---|---|
| Drop schema failures | ok false → dropped | Garbage labels win the vote |
| Dedupe by id | last-write or first-write, one slot per id | Duplicate children double-count a vote |
| List missing | expect_ids minus present | Silent holes; you think N=200 when N=180 |
| Vote only on comparable labels | fixed enum | “sev3” vs a paragraph cannot majority |
| Stable ties | sort key includes id or text | flaky pages, flaky evals |
| Size cap | table not a dump | parent context explodes |
Vote, merge ids, list holes. The parent never sees 200 novels.
Reduce is the productVote. Majority of remaining labels. Tie-break with a documented rule (lexicographic label, or “no winner → human”). Do not let a 70B “summarize the vibe” replace this when labels exist.
Duplicates. Retries enqueue the same item_id twice. Key by id. Duplicate a in the toy does not become two ids. Counts for voting use unique ids, not raw row count — decide that explicitly. The toy keeps last label per id; two a rows with the same label still count as one a.
Dropped. Child c has ok: False. It does not vote. It is listed. If dropped is huge, the swarm is sick (schema too strict, or model too small). Do not silently ignore.
Missing. Expected d never arrived. Listed. Parent may rerun only d, or proceed partial with a flag. Do not treat missing as label 0.
Walkthrough: four rows, three expected holes
Rows: a ok sev3, b ok sev1, c fail, a ok sev3 again, and expect ids a,b,c,d.
Reduce: by_id has a and b. dropped includes c. missing includes d (and c is dropped and not in by_id, so c may also appear in missing depending on whether you treat dropped as present — the toy lists missing as “not in by_id,” so c and d are missing; c is also dropped). Winner sev3. n=2 unique ok ids.
Read the print. Your production schema should document whether dropped ids are also missing. Pick one, test it. Ambiguity here becomes a dashboard lie.
Run to execute this in your browser. Nothing is sent to a server.
What printed: winner sev3, n: 2, missing includes c and d (c failed so it never entered by_id; d never arrived), dropped includes c. Duplicate a does not double-count as two ids. Failed c is dropped. Missing d is listed. Winner is sev3.
If both a and b had different labels 1–1, the sort (-count, label) would pick the lexicographically smaller label. Document that. Evals hate a random winner.
Never paste traces
The parent prompt that contains 200 JSON dumps will: cost a fortune, drown the supervisor, and re-expose child thoughts as instructions (injection sideways, now from your workers). Reduce down. If you need examples, include three rows, not two hundred.
Open-ended research swarms still reduce: cluster ids, one summary sentence per cluster, cite child ids. A 40-page concatenation is the research dump the why-part told you not to hand a coder.
Partials: after a deadline, reduce what you have. Stamp partial: True. The sequential parent can HITL or rerun missing. Infinite wait is not quality.
Open-ended research still needs a table. “Summarize the web” is not a reduce. Cluster ids, one sentence per cluster, citation list, dropped children. If the parent needs a narrative, a single writer role writes it from the table — sequential, one allow-list — not 200 children arguing in the prompt. That writer is not a swarm member. It is the next node after reduce.
When labels are not comparable (one child returns sev3, another returns a paragraph), do not vote. Drop the paragraph as schema failure. If too many drop, the child schema is wrong or the model is too small. Shrink the schema. Do not ask a 70B parent to “reconcile the vibe.” That is concatenating traces with extra steps.
How agents use this
Log parent_id, child_id, item_id on every span. Cost attribution without those keys is a mystery novel.
Unit-test reduce with duplicates, drops, missing, empty input (winner None, n 0). No tokens. This function is more important than the child prompt.
The parent apply step (next lesson) reads this table, not the children. If winner is None or missing is non-empty on a money job, do not apply. Human. Write barrier plus a complete reduce is how you sleep.
Dashboards: dropped rate, missing rate, n vs expected, cost vs pre-launch estimate. A swarm that maps beautifully and reduces into a novel is a failed swarm. Treat reduce like billing code: reviewed, tested, owned. If only the child prompt has an owner, the parent will drown.
Check your understanding