Nineteen Agents, One Working Directory, and a Codebase That Finally Got Cleaner
The screenshot is almost comically small: 19 subagents, Standard mode, 1 background job.
But that little status bar captures the most important change in how I work with coding agents. This was not one model answering one prompt. It was a small engineering team operating on one difficult task, with planning, implementation, review, and coordination happening at the same time.
The goal was familiar: make a large Ruby codebase easier to read without changing what it does.
The interesting part was not that nineteen agents could be started. Starting agents is easy. The interesting part was making them behave like a system rather than nineteen parallel conversations.
This is the actual session view that prompted the story. It is not a benchmark chart or a claim about model quality. It is a snapshot of the coordination surface: a visible fleet attached to one task.
The screenshot is an architecture diagram
At one point, the interface showed nineteen subagents working on the same task. A few were working on planning. Others were implementing the accepted plan. The remaining agents were reviewing the plans and the implementation, checking whether the work was safe, complete, and consistent with the repository's rules.
“The same task” did not mean nineteen agents editing the same file. That would be a race condition with a user interface.
It meant one shared objective, one repository, one working directory, and a controlled division of ownership.
Each agent had a bounded responsibility. The orchestrator had the global view. The working directory held the state that the agents needed to share. The result was less like asking a crowd to edit a document and more like running a build system whose workers happen to be language models.
That distinction matters. Parallelism creates throughput. Boundaries create safety.
The working directory became the message bus
The orchestrator could not keep the whole task in its own context. It also could not rely on every agent remembering what an earlier agent had discovered.
So the durable conversation moved into files.
The repository carried an ordered queue, a standing brief, per-file reports, owner flags, liveness logs, and a referee script. A simplified version looked like this:
.review-state/
queue.tsv # every unit of work and its closed-set status
brief_combined.md # the current standard and incident-derived rails
reports/ # one audit record per worker assignment
FLAGS.md # decisions reserved for the human owner
verify_and_commit.sh # independent gate before a change enters history
/tmp/tamoz-agents/
combined-<rank>.log # liveness, not a substitute for evidence
Planning agents wrote down the shape of the work. Implementation agents read that plan and changed only their assigned target. Review agents read the plan, the diff, and the repository rules, then recorded what they accepted, rejected, or escalated.
The orchestrator moved data back and forth through those artifacts. It did not have to retell the whole story in a prompt every time another worker woke up.
That was the breakthrough: the working directory was not merely where the code lived. It was the coordination surface.
Three kinds of work, one controlled loop
The fleet was easiest to reason about when I separated the work into three roles.
Planning: make the work legible before it is large
The planning lane turned a vague request—“clean up the codebase”—into bounded units.
It identified production files, ordered them by size, recorded the current status, and attached the rails that made each file dangerous or safe to change. It also made the acceptance criteria explicit: behavior-preserving only, no suppressed lint, no unproven public-API rename, and no pretending that a clean audit was a proof of correctness.
The plan was not disposable setup. It became part of the system's memory.
Implementation: make the smallest defensible change
The implementation lane owned exactly one target at a time. Its brief required an audit before editing, a written candidate list, and a rejection reason for every idea that did not survive scrutiny.
The changes were deliberately unglamorous:
# before
return unless tag && !tag.start_with?('tag:yaml.org,2002:')
# after
return if tag.nil? || tag.start_with?('tag:yaml.org,2002:')
Other passes replaced positional arguments with keywords after a repository-wide call-site search, removed a boolean parameter after proving its sole call site, or named receipt columns at the point where they were fetched.
The unit of progress was not “the agent made a clever change.” It was “this exact target has a recorded verdict, a bounded diff, and evidence that its behavior stayed inside the contract.”
Review: turn claims into facts
An implementation agent could say that syntax, lint, and focused tests passed. That was a claim, not a fact.
The review lane checked the plan, the diff, the ownership boundary, and the reported commands. Then an independent referee re-ran the important gates before the change was committed. Agents did not commit directly.
This separation was essential. A reviewer that shares the implementer's assumptions is useful. A referee that can still say “no” is safer.
The orchestrator was a traffic controller, not a super-agent
The orchestrator had a very specific job:
- Take the next bounded wave from the queue.
- Launch workers with exact bindings and disjoint write ownership.
- Wait for reports instead of busy-polling every conversation.
- Inspect the diff and report for each completed unit.
- Run the independent referee.
- Serialize the commit and update the queue.
- Periodically run whole-repository gates.
The most important step was the last one. Per-file tests can pass while the composition of several changes breaks an architectural rule. The fleet therefore had cohort gates over the whole tree, with single-unit reverts available when a cohort failed.
The shared directory made coordination possible. The single commit chokepoint made it auditable.
What the loop found at repository scale
The underlying field report comes from Tamoz, a monorepo of seventeen Ruby gems. At the evidence snapshot:
- 515 production files entered the queue.
- 260 files were fully processed: 216 committed, 37 audited clean, 4 exempt as declarative data, and 3 skipped as out of scope.
- 214 atomic commits landed after the loop began.
- 257 per-file verdict reports were written.
- 69 decisions were flagged for the human owner instead of being guessed by an agent.
- The first 200-file closing sweep reduced uncached RuboCop offenses from roughly 1,023 to 976, with no suppressions and no file allowed to get worse.
Those numbers describe the repository loop, not a claim that every one of the nineteen visible agents edited code simultaneously. The screenshot shows the coordination surface; the source evidence shows what entered history.
That distinction is important. A screenshot proves that a fleet was active. It does not prove that the fleet was safe. The ledger, reports, gates, and commits are the evidence for that.
The loop caught itself twice
The most convincing part of the run was not the number of refactors. It was the way the system found its own mistakes.
The first regression was a composition failure. Two individually green changes, when stacked, broke a static reachability check in the SQLite boundary. A cohort gate caught the problem. Single-file reverts isolated the pairing, commit fc3878a reverted it, and the lesson became a standing rail in later briefs.
The second regression was smaller and more embarrassing. An agent renamed a local variable at two remembered sites and missed a third occurrence. The focused tests for that file passed. Forty files later, another agent hit the failing path while running a sibling test lane as due diligence. It proved the failure predated its own edit, traced it to the earlier commit, and repaired it in af81312 while preserving the refusal message byte-for-byte.
The new rule was simple: before renaming anything, search the entire file for every occurrence. Memory is not evidence.
Neither catch required a human to notice the defect first. Both required verification to have a real job, a real artifact, and permission to stop the line.
The model was only half the story
There was also a model story behind the run.
I was using ox/alpha, a mysterious model label in the environment. Later, in my setup, it turned out to resolve to GLM 5.3 Flash. Through a DeepSeek harness, the usage counter reached roughly two billion tokens in a single week, free of charge to me.
That is an extraordinary opportunity for an independent engineer. The model was able to keep working for hours on a difficult task and eventually crack it. I am genuinely grateful to the GLM team for making that kind of heavy experimentation possible.
But the model did not carry the whole operation in its head. The harness kept the process running. The working directory preserved state. The queue made progress countable. The review lanes challenged assumptions. The referee separated “the model says it passed” from “the repository accepted the change.”
The free tokens made the experiment possible. The coordination system made the tokens useful.
What breaks without the artifacts
Nineteen agents without a protocol would have produced a familiar mess:
- overlapping edits and merge conflicts;
- plans that existed only in forgotten chat messages;
- reviewers checking code without knowing the acceptance criteria;
- “done” meaning whatever the last agent claimed;
- no durable record of rejected changes;
- no way to distinguish a real failure from a stale status update.
The remedy was not a more elaborate prompt. It was a small control plane:
- one queue with closed-set statuses;
- one writable target per worker;
- one file-based report contract;
- first-class no-op and escalation outcomes;
- one independent commit path;
- periodic whole-system gates;
- incident lessons amended into the standing brief.
This is why I now think of prompts as worker configuration, not as infrastructure. The infrastructure is the set of files and gates that survives when the prompt, the model, or the orchestrator session disappears.
The real lesson for engineers
The seductive headline is that nineteen agents cleaned a codebase.
The more accurate headline is that a written standard, an ordered queue, a shared working directory, and independent verification turned a fleet of agents into a maintainable engineering process.
The agents supplied parallel attention. The artifacts supplied memory. The review lanes supplied friction. The referee supplied authority. The human stayed responsible for the decisions that were semantic, cross-cutting, or too product-sensitive to delegate.
That is the shape of AI-assisted engineering I trust:
Scale the workers horizontally; keep control vertical.
Clean code is still a reading order. At repository scale, maintaining that reading order becomes a coordination problem. Solve the coordination problem, and the model can work for hours without the task dissolving into twenty disconnected chats.
The screenshot shows nineteen agents.
The files show whether they were a team.