Three months with a team of Claudes: the bottleneck was me
In October my agents opened 371 pull requests. 98% of them came from Claude, and almost every one waited for my click. What I measured, what I tried, and what actually helped.
From August to November I built software with Claude Code doing most of the typing. Our team is two people, my teammate and me, plus a growing number of Claude sessions that write code, open pull requests, run overnight and report back in the morning.
By October the numbers looked great. About 3,000 commits in a month, 371 pull requests opened and 335 merged, compared with 2 pull requests in all of September. 98% of those PRs came from agent branches.
Then I measured where the time went. The agents were fast. Almost everything they finished had to go through me, and I was the bottleneck.
August and September: nothing to coordinate
It started with small tools. Each solved one annoyance, and Claude wrote nearly all the code:
- a local YouTube transcript tool that needs no API key;
- a full-resolution Instagram downloader;
- a Telegram bot that files links I tag into a curated catalog in git;
- a Telegram bot that sends a small group a monthly forecast parsed from YouTube videos.
Each had its own repo. There was no shared process and no pull requests. Everything was fast because there was nothing to coordinate.
October: coordinating the agents
On October 1 we decided to build a shared home for the tools: a thin layer over separate repositories, for a two-person team whose work is mostly done by agents. Two hours after the first commit, one person’s Claude sent the first task to the other’s.
Over the month we built:
- A team CLI that syncs every project, checks its health, injects secrets from a password manager, deploys, and creates new projects from templates.
- A task exchange between our two Claudes. Each task is a brief in git, written for an agent with no context, mirrored to GitHub Issues and announced with a Telegram ping.
- A project standard, a CLI that checks every repo against it, and shared CI. The standard went through 9 releases in 12 days.
- Project scenarios: a graph of steps, each marked “done” only when its shell commands exit 0. Steps that need a human are marked as such.
- A knowledge base documenting the system. A weekly agent run, “the architect”, checks the system against its sources and reports on weak spots, priorities and changes.
- An activity dashboard that pulls GitHub data and Claude Code session numbers into JSON in git.
- A research engine that runs study packages with cached pages and code-checked quotes.
- A personal assistant in Telegram for real people, with each person’s data in their own private repo. That project alone had over 800 commits in October.
I logged 222 active hours in Claude Code sessions in October, and 1,667 messages. It felt like the most productive month of my life.
Fast code, slow handoffs
The first crack appeared during an overnight research run. I set six sessions to investigate why building our Telegram bots still felt slow. They examined 947 past Claude Code sessions and found:
- 147 pauses where an agent had asked me something and stopped. The median pause was 2.8 hours; 35 lasted more than a day.
- 28 of those pauses ended with a one-word “yes”.
- 24 sessions stopped at a merge, a tag or a deploy that the agent wasn’t allowed to do.
- The Telegram API, deploys and secrets together took under 20% of the active time.
The report summed it up: “The human’s time goes not to bot code but to the gates and manual steps around it.”
Other data showed the same pattern:
- Merges waited for me. 314 of the merges ran under my account. When I was at the keyboard, the median wait was 23 minutes. The slowest 10% waited 22 hours or more, 12 waited over three days, and one waited 13 and a half days.
- A bot built in 90 minutes shipped a week later. Claude went from brief to a finished habit-tracking bot in an hour and a half. Shipping stalled at “no bot token”, because only I could create one. It stayed blocked for 7 days.
- Agents couldn’t prove the work was done. The deploy check accepted the first HTTP 200, which arrived before the bot even started listening. No agent could demonstrate that “the bot answers”. Only a human could.
- Unfinished work piled up. By early November there were 130 open “tails”: 108 branches and 70 worktrees across 20 projects. While a merge waits, the next session forks off and starts something new.
- Known problems stayed open. The architect’s count of open weak spots rose from 34 to 37 to 39 to 40 across four weekly reports. None were closed.
- My attention kept fragmenting. For one day, the dashboard showed 2.8 hours of attention, 31 context switches, about 30 PRs opened from my account, and 4 of them closed as duplicates.
Every one of those PRs was cheap to produce. Every one cost me a context switch.
What I changed
1. Put the rules in executable checks
A prose rule such as “remember to run the tests” is easy for an agent to skip. I moved as much as I could into executable checks:
- Agents may merge their own PRs, within limits. The project must opt in, the branch must be an agent branch, and the check must be green on the latest commit. The PR must not touch protected paths: CI config, the verify script, the agent instructions or package files.
- An audit flags violations: merges without a green check, commits that skip PRs, and agent merges that broke the rules.
- Tasks need “done when” criteria and boundaries before they can be sent. The task exchange also rejects hidden text, including zero-width characters and HTML comments, that the receiving agent would read but a human wouldn’t see.
- Sync only pulls commits that came through a merged PR or were signed by the machine’s owner.
- A scenario step is done only when its commands exit 0.
The checks caught real violations, including a PR merged two and a half minutes before its check went green, 23 audit errors in one run, and merges that skipped the check during an outage.
The agent-merge rule was meant to remove my merge bottleneck. Rolling it out across the projects took five PRs that waited almost two weeks for me to merge them. In three months, agents merged exactly 2 PRs on their own.
I’d install that rule first next time, before the PR volume makes it hard to get anything through.
2. Define “done when” before work starts
I thought I was over-specifying how agents should work. The data pointed to a different problem: 85% of my task statements had no “done when” criterion at all. In a small sample of ten sessions, those with a criterion needed no corrections 90% of the time, compared with 65% without.
Now every task starts with a definition of “done” expressed as a command that can pass or fail. The task exchange refuses to send a brief without one.
3. Batch the decisions
A session now gathers the loose ends and handles anything with one obvious answer. It brings the rest to me one question at a time, each with a recommendation and real alternatives. We settled the project’s direction for November through seven multiple-choice questions, recorded word for word as a decision.
The instruction that made this work was mine: “Where the decision is obvious, decide for me.”
I also learned to keep merges out of these lists. A report once ended with “From you: 1. Merge #10. 2. Tag.” I answered “1 yes 2 yes 3 yes 4 yes”, and the agent merged a critical PR itself. Minutes later I wrote: “#10 I merge myself. Tag after my merge.”
Since then, a merge never goes into a yes/no list. The agent writes “you merge” and stops at a green PR.
4. Run overnight, review in the morning
For some jobs, I leave an orchestrator session running overnight. It splits the work across several sessions and leaves a report with a fixed format: what to read carefully, what to skim, decisions it made for me with “cost if wrong”, what it parked, and what’s next.
The results varied:
- The bot research went well: six sessions, read-only, nothing parked, a measured answer by morning.
- A research-engine pilot failed. It scored 5.25 for usefulness against a target of 8.5, with 5.5 errors per fact sheet against a limit of 1. The full run was cancelled, and we added a pilot gate to catch the next failure at less cost.
- Several runs ended with the same line: “waiting for the owner”. Overnight work still stopped at anything only I could do.
5. Get a review from another model family
For major conclusions and final reviews, I use a GPT model through Codex to review Claude’s work and look for blind spots.
Its most useful feedback was about my own reports. The architect had concluded that the system was getting healthier based on commit and PR counts. GPT replied: “This doesn’t follow from commit and PR counts: they measure activity.” That sentence changed what I measure.
The reviews cost extra tokens, and subscription limits run out. I reserve them for conclusions and final reviews.
6. Skip rules I won’t follow
I considered capping the number of sessions I run at once. I rejected it because rules about my own behaviour are the ones I’m least likely to follow. I can automate a gate. I can’t automate discipline.
What still broke
- One billing problem stopped everything. From late October, every CI job in our GitHub organization failed without running a single step because of a payment issue. Agent merges require a green check, so they stopped. Meanwhile, 21 merges in critical projects went through with no check at all. The gate depended on the account paying for it.
- A local model wasn’t a cheap substitute. A 27B model running locally on a laptop scored 3.6 out of 10 on research extraction, compared with 9.0 for Opus and 8.8 for Sonnet. The local model took about five minutes per sheet.
- “Ask” permission rules didn’t ask in auto mode. Deny rules held; ask rules let commands through silently.
- Two agents acted on the same message. A scheduled agent thread and my desktop session both followed the same instruction and opened duplicate PRs. I settled on requiring an agent to check recent activity in a repo before opening a PR. That check isn’t enforced yet.
- Tasks arrived where my teammate didn’t look. My teammate barely used the task exchange for two weeks. It delivered tasks to a rarely opened folder as long Markdown documents that were awkward to read on a phone. One-tap buttons in Telegram (take it, later, no) fixed it.
- Agents graded other agents. Agents write, agents summarise, and an agent grades the summaries. GPT flagged this as the biggest risk in mid-October. I haven’t solved it.
What I’d do from day one
- Measure where the human’s time goes. Commit and PR counts measure activity. Count pauses, waits and context switches.
- Write “done when” before the agent starts, as a command that can pass or fail.
- Give agents a narrow, pre-approved class of merges with protected paths. Install it before the volume arrives.
- Batch decisions, one question at a time. Never let a “yes” in a list mean “merge”.
- Keep small tools small, and make them public. In November I rewrote a 7,000-line tool I depended on as a 345-line bash script I can read in one sitting. Small, readable code is the only kind a single human reviewer can keep up with.
Can it work without me?
In November I deliberately reduced the activity. The system had worked in October, but it still depended on me to deliver its value. The decision page from late October put it bluntly: “Today the carrier of this value is me, not the code.”
My next step is to reduce that dependence. That means narrower gates agents can pass on their own and checks that verify the result beyond an HTTP 200. A pilot with people outside our team will test whether any of it works without me in the loop.
If you’re running more than a couple of agents in parallel, I’d like to compare notes: where does your time actually go, and which of your gates can an agent pass without you?