Some days five to seven agent sessions ran at once across our repositories. You might expect that to mean lots of subagents. It didn't.
Peer sessions vs subagents
The counts for one month:
| Workspace | Subagents launched | Messages between sessions |
|---|---|---|
| Design workspace | 0 | 20 |
| Consumer app | 1 | 47 |
| Web portal | 8 | 89 |
A peer session is a full Claude Code session with its own repository, its own terminal pane and its own memory. It messages other sessions directly. Ours ran in tmux panes run by a desktop session manager, with status hooks so the developer could see at a glance which session was busy.
A subagent is short-lived and runs inside one session.
Our rule of thumb became:
- A long-lived role with its own repository and context gets a peer session.
- Well-specified, read-mostly execution gets a subagent, often on a cheaper model.
Step one: a lead and a worker
Need Help Implementing This?
Our team can help you put these ideas into action. Get in touch for a free consultation.
The first real collaboration was in design. A lead session asked a peer to audit the existing designs. It wrote a generator script, validated it, and sent updated versions to the peer by message. Together they ported about 25 missing features into about 40 screens.
The next morning the lead checked which backend endpoints were ready and briefed two portal sessions. Each brief covered:
- the files that worker owns
- the routes to build
- the worktree and branch to use
- "don't commit; run the check; report back"
Before pushing anything, the lead ran the test baseline and scanned every diff for leaked credentials. The result was three pull requests.
Step two: a coordinator and four peers
The biggest run took one change request from design to merged UI in under four hours. The backend wasn't ready, so the developer's instruction was "deliver the UI first".
- Questions and a brief. The coordinator read the design, asked four scoped questions, and wrote a brief. It covered decisions not to reopen, sources, vocabulary, four work packages that each owned specific design frames, and the report format.
- A foundation branch. It stubbed the seams between packages and added a sample backend behind a feature flag.
- Phase 0. Each peer wrote a read-only "needs" report before building anything.
- Phase 1. Each peer built its package in its own worktree, branched from the foundation branch.
- Merge. Everything landed as a single pull request of about 200 files.
What stalled: two of the peers came from another repository. Each stopped on a first-time "read outside the working directory" permission prompt and sat there, one for more than 20 minutes, until the coordinator reassigned its package piece by piece. Now we pre-approve the paths, or keep each peer inside its own repository.
Step three: apps talking to each other
By the final week, portal and app sessions were trading findings directly:
- "Set up the sandbox using the test account. Pass the details to the app session to verify."
- Peers report back with commit hashes, so nobody has to guess which version was tested.
- Ownership is explicit. When a session offered to pull the app repository, the developer said: "No, leave the app repo to the other session."
Messages from agents aren't approvals
At one point a peer told a worker that the developer had approved breaking a design rule. The worker asked the developer directly before acting. The developer had approved it, but the worker was right to check.
A message from another agent is information. It is not permission.
QA by cheaper subagents, behind a write guard
The prompt was simple: "Generate test cases for the feature across both portals and the app. Then delegate to subagents using Sonnet to execute."
- The testers. Five testers on a cheaper model ran well over a hundred cases on two web portals and a real Android phone. Their instructions were read-only ("you fix nothing"), and each wrote a results file.
- The write guard. Their Playwright helper fakes a
400error for any API write that isn't on an allow-list, and caps how many permanent records a run can create. - The results. They found real defects: a wrong default sort, a create path missing a conflict check, an off-by-one error in a "days left" counter, and a tab link that rewrote the URL.
We also used cheaper models for implementation, but only after the tests were written. Then the main session checked the subagent's work itself.
Shared resources need protocols
- A design canvas. Figma pages have no locking. Two sessions wrote to the same page, and a section measured 476 pixels taller than expected. The rules now: re-read the canvas right before writing, split it into fixed coordinate columns, and warn before overlapping.
- Phones. Each session gets its own bundler port, pins the device by serial number, and says so before taking the device (Part 7).
- Dev servers. Fixed ports mean only one checkout can run servers. Before killing a process, check that it belongs to your own worktree.
The cost to the human
Parallel agents are cheap. The developer's attention is not.
"Is this PR created yet? I lost track in the middle." With many sessions running, the developer's own context was the bottleneck.
What helped:
- a table in the session notes listing each piece of work and its status
- an "Active" section at the top of the memory index
- asking for the bottom line first: "So, conclusion: do we still have a blocker?" now gets "the front end can start" or "this needs the backend" before any detail
What to copy
- Give long-lived roles their own peer sessions, and use subagents for well-specified execution.
- Brief workers like contractors: owned files, worktree and branch, "don't commit", the check to run, and the report format.
- Start with a read-only phase and a foundation branch.
- Pre-approve the paths peers will need, or they'll stall on permission prompts.
- Treat messages between agents as information, not approval.
- Guard QA agents against writes, and use cheaper models for them.
- Track parallel work somewhere the human can see at a glance.