# Mythical Agent Month

> Brooks's law generalised to agent fleets - adding agents to a late project adds coordination surface, not progress, because communication paths grow as n(n-1)/2 while only partitionable work actually divides. Reach for it when deciding how many agents to run at once, when a fleet looks busy but the story is not landing sooner, or on "how many agents should I run", "add more agents", "fleet sizing", "would a bigger fleet be faster", "why is parallel slower". Differentiator - it sizes the FLEET and prices its coordination surface, so a serial relay of specialists and a crowd of peers can be compared as numbers rather than vibes.

- Skill: `island-dev-crew/mythical-agent-month` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add island-dev-crew/mythical-agent-month`
- Raw SKILL.md: https://api.skillmd.com/api/skills/island-dev-crew/mythical-agent-month/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Island-Dev-Crew (https://skillmd.com/u/island-dev-crew)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/island-dev-crew/mythical-agent-month

---


# Mythical Agent Month: coordination surface is what a crowd costs

Bob's relay is five agents, not one, and he is explicit that staging costs something. The seats have to hand work to each other. Each new seat pays *"startup times are high… 10, 15 seconds to even start up… then it's got to figure out its whole context all over again"* (C10). The whole stack is still worth it only because the margin survives: *"factor of four, factor of five improvement… and very high quality"* (C5). This island is the sizing question underneath that. How many agents before the handoffs eat the margin?

The answer is fifty years old. The [seventies-canon brief](../../research/seventies-canon.md) records Brooks's law and the surgical team from *The Mythical Man-Month* (1975), and argues both generalise to agent fleets: adding agents to a late project adds coordination surface, not progress. The arithmetic is just the count of distinct pairs in a set of n, `n(n-1)/2`. It grows quadratically, while your throughput gain grows linearly at best. Bob's own fleet note points straight at the tension: *"you could have three coders running at the same time. And my little laptop can support a lot more than three"* (C10). The machine can host more agents than the work can absorb, and that gap is where fleets go wrong.

### A grounding note, because this island is about honest cost

The roster line for this island carries the phrase "communication overhead like crazy" as a C9 quote, and for a while it reached the roster without passing through [the concept ledger](../../docs/01-CONCEPT-LEDGER.md) — the only place an island may quote the conversation from ([CONTEXT.md](../../CONTEXT.md)); claims that go beyond the conversation cite a brief in `research/` instead. The gap is now closed at the source rather than by demoting the words: C9 carries the sentence verbatim with its locus (auto-captions ~00:17:52–00:18:01, SRT cues 903–907, RCM's turn), so every quote on this island is ledger-backed, and re-greppable in `source/` once the transcript is regenerated. Re-grep the ledger rather than trusting this sentence.

The re-grep has two halves, and a clone can only run one of them unaided. The ledger is tracked, so its half reproduces anywhere. `source/transcript.txt` is deliberately gitignored — it is the whole of someone else's recorded conversation, cited here and not redistributed — so a fresh clone has nothing to grep until it runs the two regeneration commands in [`source/README.md`](../../source/README.md). The third line below is written to say so rather than to fail:

```bash
bash -c 'grep -qF "communication overhead like crazy" ../../docs/01-CONCEPT-LEDGER.md'   # exit 0
bash -c 'grep -qF "Diet Coke" ../../docs/01-CONCEPT-LEDGER.md'                           # exit 1
bash -c '[ -f ../../source/transcript.txt ] || exit 0; grep -qF "communication overhead like crazy" ../../source/transcript.txt'   # exit 0
```

The second fails at the ledger grep, which is what a roster quote with no ledger entry looks like — so the first is not a grep that always says yes. That failure is the whole of what the control proves in a fresh clone. "Diet Coke" is also *in* the recording, which is what makes it the right control rather than a random string, but confirming that half needs the regenerated transcript like everything else below.

The third is the transcript half, and its guard is the honest part rather than a way around the check. With no transcript present it skips and reports `0` having graded nothing; with one present the `grep -qF` runs and a phrase the source does not carry returns `1`. So its `0` means "checked, or not there to check", and `ls ../../source/transcript.txt` is what tells you which of the two you got. The guard stays silent by choice, not by force. An announcement written with bash's *builtin* `echo` does take SIGPIPE when this pack's own closed-stream harness closes stderr — measured, 141, and 141 names no verdict — because the builtin makes the shell itself the writer. An external `/bin/echo` does not: the child dies and the guard's own `exit 0` stands, so a loud guard is reachable. Silence is preferred here because the skip is not news at the point it happens, and `ls ../../source/transcript.txt` distinguishes the two zeros afterwards.

## Where this island sits

- **The five-seat relay itself is [`seat-relay`](../seat-relay/SKILL.md)**: specifier, coder, cleaner, hardener, QA, the batons between them, the born-do-die lifecycle (C9, C10). That island runs the relay. This island owns FLEET SIZE and its coordination cost: how many agents, in what topology, before the handoffs stop paying.
- **The continuous agent-versus-human productivity ledger is [`margin-ledger`](../margin-ledger/SKILL.md)**: per-story gated wall clock against an honest human baseline, defending the 2–4x band and the 1x floor (C5). That island prices the gate stack as stories ship. This one prices the fleet before you spawn it. They meet at one number. An oversized fleet shows up in the margin ledger as a thinning margin, and this island is where you find out which agent caused it.
- **Per-step model picks are a Forge concern: [`model-routing`](../../COMPANION.md#model-routing).** Cheapening a seat's model changes what an agent costs per minute. It never changes how many communication paths a fleet has. Size first here, then route each seat there.
- **Same-machine isolation mechanics belong to [`worktree-fleet`](../../COMPANION.md#worktree-fleet).** Once this island says "three coders", giving each its own worktree is that island's job. So is its rule that worktree artifacts are inadmissible as gate evidence until re-derived from a fresh clone.

## Two shapes of work, and only one of them divides

| Shape | Example | What n does to it |
|---|---|---|
| Partitionable | five independent endpoints, five test files, five unrelated bug fixes | divides by n; this is the whole reason to run a fleet |
| Needs shared context | one domain model three seats must agree on, an interface being designed while it is being used | does not divide at all, and every agent holding it is one more that can disagree |

The second row is why "just add another agent" fails. Work needing shared context is not made shorter by spreading it, and spreading it manufactures the pairs that then have to reconcile. Bob's compartmentalisation argument is the same claim at module scale: *"If you load up a module with every bit of stuff under the of under the sun [sic], the poor agent is going to wonder, 'What the heck am I doing in here?'"* (C15). A fleet with no partition is one loaded module wearing five hats.

## Why a serial relay beats a crowd

Compare the two topologies at the same headcount, using nothing but edge counts:

- **A crowd of n peers** on shared-context work is a mesh: `n(n-1)/2` paths. Five peers is ten reconciliations, and every one of them is a chance to disagree.
- **A relay of n seats** is a chain: `n-1` handoffs. Five seats is four batons. Each baton is a *typed artifact* (Gherkin, code, CRAP report, mutation log, QA verdict), not a conversation, so the coordination cost per edge is bounded by what the artifact contains rather than by how long two agents argue (C9).

Five seats: 4 edges. Five peers: 10 edges. Same headcount, two and a half times the surface, and the relay's edges are the cheap kind. That is the whole case for staging specialists in series. It is also why the relay can afford five agents on work that would drown five peers.

The relay's costs are still real and still additive, and Bob says so about the very relay he runs: *"there's communication overhead like crazy in that. and yet it's still faster by a large token than a human"* (C9). Each seat pays the fixed startup and context-rebuild toll (C10), and the stack must keep the margin above the human floor or *"you've lost the game"* (C5). Serial staging buys a better edge count; it does not buy immunity.

## The sizing model

```
elapsed(n) = S * ((1 - p) + p/n)   +   h * n(n-1)/2
             \___ partition term ___/   \_ pair term _/
```

| Symbol | Meaning | Where the number comes from |
|---|---|---|
| `S` | serial minutes: the work if one agent did all of it | historical actuals, or the same honest-baseline discipline `margin-ledger` demands |
| `p` | partitionable share, 0 to 1 | your read of the story; the estimate most likely to be wrong, and the one to write down before you are attached to an answer |
| `h` | handoff minutes per communication path | measure it once: how long two agents' work actually took to reconcile |
| `n` | fleet size | the thing being decided |

The partition term divides only the partitionable share. Shared-context work does not divide at all. The pair term is Brooks's. `elapsed` is convex in n: the first term falls at a decreasing rate, the second rises at an increasing one. So the first fleet size whose successor costs at least as much is the global optimum, and no search past it is needed. That "at least as much" is the script's own rule (`crossover()` triggers on `>=`): an exact tie counts as not paying, the same way the exit table does.

## One command

[`scripts/fleet-cost.py`](scripts/fleet-cost.py) reads a four-key plan file and answers one question: does the *last* agent in the proposed fleet still reduce elapsed time?

```bash
python3 scripts/fleet-cost.py <plan-file>
python3 scripts/fleet-cost.py --help      # -h is accepted as the same flag
```

| Exit | Meaning |
|---|---|
| `0` | the proposed fleet pays — the last agent reduces elapsed time. Also `--help` (or its accepted synonym `-h`) on a working stdout. |
| `1` | Brooks — the last agent does not reduce elapsed time. A tie counts as not paying: it bought nothing and added a path. |
| `2` | not a verdict — usage error, a path that is not a regular file (directory, FIFO, `/dev/zero` and other character devices), a plan over 64 KiB, unreadable file, non-UTF-8, malformed line, unknown key, duplicate key, missing key, out-of-range value, dead output stream, internal failure. |

Three codes. The script emits no others, and every input reaches one of them. The path is `stat`ed and refused unless it is a regular file, and the read is capped at 64 KiB, so no input class runs forever instead of returning a code (`/dev/zero` on an uncapped read is a hung CI job, not a refusal). All arithmetic runs in exact rationals (`fractions.Fraction`), so no verdict is ever decided by a float. Every printed minute figure is rounded for display, and when rounding would hide a non-zero difference the exact ratio is printed beside it.

### Red and green, both run

```bash
python3 scripts/fleet-cost.py scripts/fixtures/oversized-fleet.txt     # exit 1
python3 scripts/fleet-cost.py scripts/fixtures/right-sized-fleet.txt   # exit 0
```

The two fixtures carry identical values for `serial_minutes`, `partitionable` and `handoff_minutes`, and differ only in `fleet`: 5 versus 2. Their comment lines differ in wording and are not parsed. So the red run fails for the reason claimed, the fifth agent's marginal cost, and not for malformed input. The red run prints `crossover fleet 2 is the last size that still pays` and `elapsed fleet 4: 414.00m -> fleet 5: 499.60m (delta +85.60m)`.

The pack's own acceptance ritual agrees ([`known-dirty-fixture`](../known-dirty-fixture/SKILL.md)):

```bash
bash ../known-dirty-fixture/scripts/prove-gate.sh scripts/fixtures/oversized-fleet.txt \
  scripts/fixtures/right-sized-fleet.txt -- python3 scripts/fleet-cost.py   # exit 0, ACCEPTED
```

A gate that only ever saw the input its author imagined is not hardened. So the same violation was re-run through the encodings a real editor or CI produces: a UTF-8 BOM plus CRLF line endings on the *dirty* plan. It still lands on the same verdict:

```bash
python3 scripts/fleet-cost.py scripts/fixtures/dirty-bom-crlf.txt   # exit 1
```

### A closed hole, kept as a fixture

`str.splitlines()` breaks on eight separators beyond LF/CRLF/CR: `\x0b`, `\x0c`, `\x1c`, `\x1d`, `\x1e`, U+0085 (NEL), U+2028 and U+2029. While the parser used it, a line whose first character was `#` was *not* ignored. Everything after an embedded separator on that line was read as live configuration. The worst shape for this island is `handoff_minutes 0` smuggled inside a comment. It zeroes the Brooks pair term, the one number the island exists to charge, so every fleet size then reports `PAYS`. U+2028 is what macOS TextEdit and Notes emit for a soft break, and what survives a paste out of a PDF; `\x0c` is a routine Emacs page break.

The parser now splits on `\r\n|\r|\n` only, and tokenises on spaces and tabs only. A comment line is therefore ignored whole, and every other whitespace character stays inside its token, where it is refused as an unknown key or a malformed value. The fixture is a three-key plan whose comment carries a U+2028 ahead of `handoff_minutes 0`:

```bash
python3 scripts/fleet-cost.py scripts/fixtures/comment-smuggle-u2028.txt   # exit 2, missing required key(s): handoff_minutes
```

The byte-identical control, with an ordinary space in place of the U+2028, returns that same code. That is the point: the separator now changes nothing.

Hostile inputs were swept separately. Every one returned `2`, never a verdict code: `nan`, `inf`, `4.8e2`, `-25`, `3/5`, `4_80`, a 4400-digit value, a duplicate key, a missing key, `Serial_Minutes` (case variant, refused rather than silently re-routed), a trailing `# comment` after a value, a `#` line carrying any of the eight exotic separators above ahead of a live key, an NBSP used as the key/value separator, `/dev/zero`, a FIFO with no writer, a 64 KiB+1 plan, `fleet 0`, `fleet 99999`, `fleet 5.0`, `partitionable 2`, an empty file, a UTF-16 file, a missing file, a directory, no arguments, two arguments. Recompute them rather than trusting this sentence.

A dead output stream is swept the same way, in both of its shapes: a closed-reader pipe, and an fd closed before the process starts. In the second, CPython sets the stream to `None` and `print()` becomes a silent no-op, so an unguarded script would report a verdict into an empty log:

```bash
python3 scripts/fleet-cost.py scripts/fixtures/right-sized-fleet.txt >&-   # exit 2, not 0
python3 scripts/fleet-cost.py scripts/fixtures/oversized-fleet.txt   >&-   # exit 2, not 1
python3 scripts/fleet-cost.py --help                                 >&-   # exit 2, not 0
python3 scripts/fleet-cost.py scripts/fixtures/right-sized-fleet.txt 2>&-  # exit 2
```

## Known limit, disclosed rather than hidden

The model charges an all-pairs mesh. A hub-and-spoke fleet (one lead agent, k workers who never talk to each other) really has k paths, not k(k+1)/2, so this script over-charges it. The failure direction is over-strict: it refuses a plan the real topology would still pay for, never a false green. It has a captured run:

```bash
python3 scripts/fleet-cost.py scripts/fixtures/hub-topology-blindspot.txt   # exit 1
```

At `S=480, p=0.9, h=8, fleet=6` the mesh model charges 15 paths and returns `1`. Under hub-and-spoke the same fleet has 5 paths and would still be improving. Until a topology field exists, read a `1` on a genuinely hub-shaped fleet as "check the topology", not "cut an agent".

## Enforced vs advisory

- **`enforced`** — the arithmetic and the refusals. `fleet-cost.py` exits `1` on a fleet size whose last agent does not reduce exact-rational elapsed time, and `2` on every input it cannot parse into exactly the four named keys. Its own red/green acceptance is enforced by `prove-gate.sh` (run above, exit 0). This island's shape is enforced by [`validate-island.py`](../../scripts/validate-island.py).
- **`advisory`** — every input number. `S`, `p`, and `h` are estimates, and the script cannot check any of them. A wrong `p` produces a confident wrong verdict. Write the three numbers down with their source before running it, exactly as `margin-ledger` demands of a human baseline, or the output is a guess wearing an exit code.
- **`enforced`** — the ledger half of the provenance re-grep. `docs/01-CONCEPT-LEDGER.md` ships in the repository, so the first two greps above reproduce in any clone, and the control still fails there for the reason claimed.
- **`advisory`** — the transcript half, in a clone that has not regenerated `source/transcript.txt`. The guard turns the absent file into a skip, so its `0` certifies nothing about the source. Run the two commands in [`source/README.md`](../../source/README.md) and that same line becomes enforced. Provenance breadth stays advisory in both worlds: no checker sweeps every quote in the pack for the same double-sourcing.
- **`advisory`** — the topology judgement (mesh versus chain versus hub), the choice to stage serially rather than fan out, and everything about *which* agent to cut. No checker sees your fleet's shape.

## Done when

- [ ] The story's partitionable share is written down as a number with its reasoning, before the fleet size is chosen.
- [ ] `python3 scripts/fleet-cost.py <plan>` exits `0` for the fleet you intend to spawn, and the plan file is kept beside the run.
- [ ] Shared-context work is named explicitly and assigned to *one* agent or one relay chain, never split across peers.
- [ ] The crossover size is recorded, so the next person adding an agent knows what they are spending.
- [ ] If the fleet is hub-shaped, the limit above is acknowledged in the run notes rather than silently ignored.

**No authority without evidence. Paths grow as n(n-1)/2 and progress does not — count the edges before you spawn the crowd.**

