Running 4 Agents at Once
Queue-based self-scheduling across machines. Database branching for isolation. Trunk-based development with rebase. Conflict resolution patterns.
~8 minute read
Why Parallelism Matters
A solo founder with 150+ units cannot build them sequentially. At 4-5 hours per spec, sequential execution means 600-750 hours of agent time for the first version. With 4 parallel instances, that compresses to 150-190 hours of wall clock time.
But parallel execution introduces coordination problems: merge conflicts, database schema collisions, resource contention, and scheduling dependencies. This section covers how to solve each one.
Queue-Based Self-Scheduling
A shared JSON file (agents/queue.json) tracks all specs across three arrays: ready (waiting for execution), in_progress (being worked on), and completed (pushed to main). When a command runs without arguments, it reads the queue and recommends the next spec.
The Scheduling Algorithm
- Filter by dependencies. Only specs whose dependencies are all in "completed" are eligible.
- Exclude conflicts. Skip specs whose
files_modifieddestructively overlap with any in-progress spec. Additive overlap (both add new files) is fine. Destructive overlap (both modify the same existing file) requires sequential execution. - Apply priority. Dependency unblocking (specs that unblock others first) > critical path > conflict avoidance > FIFO.
- Recommend. Present the top candidate with rationale. Human confirms.
Status progression: ready > testing > tests-written > implementing > implemented > verifying > complete
Database Branching for Isolation
Each spec creates three separate database branches (one per command), each from the current dev branch. Branches are created in ~1 second using copy-on-write (no physical data copy) and cost fractions of a cent per hour.
Why Three Branches Instead of One
- Commands can be separated by hours. A branch that lives across commands risks expiry or stale schema.
- Each branch created from latest dev captures schema changes from other specs that merged between commands.
- Each command is fully self-contained. No cross-command state in the database.
The Migration Strategy
During execution, schema changes use push (applies the schema diff directly to the branch, no migration files). This avoids migration file conflicts when multiple specs execute in parallel.
Canonical migration files are generated only by ex-verify, as the final step before pushing to main. If two specs merged between creation and push, the migration number may conflict. Resolution: delete local migration files, regenerate from the current schema state, retest.
Git on Main: Trunk-Based Development
No feature branches. No pull requests. All work on main. Rebase before start and before push.
This extreme trunk-based approach works because:
- Each spec touches a well-defined set of files (specified in the queue entry).
- The scheduling algorithm avoids destructive file overlap.
- Additive conflicts (both sides add different files) auto-resolve during rebase.
- Only ex-verify pushes. It rebases immediately before pushing.
Conflict Resolution Table
| Conflict Type | Resolution | Automated? |
|---|---|---|
| Both add new files in same directory | No conflict. Both coexist. | Yes |
| Both modify root router (add registration) | Additive. Rebase auto-resolves. | Yes |
| Lock file (pnpm-lock.yaml) | Accept theirs, re-run install, re-add. | Yes |
| Same migration number | Delete local, regenerate, retest. | Yes |
| Same file, same lines | STOP. Report to human. | No |
.git/index.lock during rebases, blocking the operation. Always run turbo daemon stop before any rebase. This is built into every command's rebase step.
Resource Management
Machine Configuration
Each machine has a .machine file (gitignored) that the scheduling algorithm reads. It contains: machine name, type, RAM, concurrent instance count, and Playwright worker limits.
A setup script auto-detects hardware and calculates optimal Playwright worker counts based on available memory after accounting for the AI agent's memory usage (~6GB per instance).
E2E Test Framework Memory
Context Window Management
All commands run a proactive compaction at 60% context capacity. Do not wait for auto-compact at 95%. When compacting, preserve: current task, which tests pass/fail, files modified, decisions made, spec ID.
The spec header includes a context budget estimate. If the budget was underestimated and context reaches 60% during execution, the command compacts proactively rather than risking quality degradation.