Parallel agent fleets
Prepare one environment, fork it into many exact copies, and give each copy its own task. Keep the winner, delete the rest.
For Teams clearing a backlog, running research sweeps or trying several approaches at once
Why it pays
- Setup once, not N times Install, build and warm caches once. Forks copy the prepared machine, running processes included.
- Truly independent workers Each fork has its own disk, processes, IP and identity, so agents can't collide.
- Compare and keep the winner Tag forks with a label, watch them finish on one event stream, and see the cost of each branch.
Step by step
Prepare a base machine
Clone the repo, install dependencies and start the dev server and test watcher once.
CLI
harebox new --name base --label experiment=auth harebox exec current -- ./setup-and-warm-caches.shPython
base = hb.create(name="base", labels={"experiment": "auth"}) base.run("./setup-and-warm-caches.sh")TypeScript
const base = await hb.create({ name: "base", labels: { experiment: "auth" } }); await base.run("./setup-and-warm-caches.sh");Fork it into several exact copies
Each copy starts from the same moment, with the server already running.
CLI
harebox fork current --count 4 --label experiment=authPython
forks = base.fork(count=4, labels={"experiment": "auth"})TypeScript
const forks = await base.fork({ count: 4, labels: { experiment: "auth" } });Give every fork its own task
Send each fork a different issue, or the same task with a different harness, and let them run.
CLI
issue=101 for id in $(harebox list --label experiment=auth --json | jq -r '.sandboxes[].id'); do harebox prompt "$id" "Fix issue $issue, run the tests, open a PR" --harness claude --budget 2 --detach issue=$((issue + 1)) donePython
issues = [101, 102, 103, 104] for box, issue in zip(forks, issues): hb.create_prompt(box.id, body={"prompt": f"Fix issue {issue}, run the tests, open a PR", "harness": "claude", "budget_usd": 2})TypeScript
const issues = [101, 102, 103, 104]; await Promise.all(forks.map((box, i) => hb.createPrompt(box.id, { body: { prompt: `Fix issue ${issues[i]}, run the tests, open a PR`, harness: "claude", budget_usd: 2 }, })));Watch them finish on one stream
No polling: follow the account's events and react as each turn ends.
CLI
harebox events --type "prompt.finished" --followPython
for ev in hb.stream_org_events(query={"type": "prompt.finished"}): print(ev["sandbox"], ev["data"])TypeScript
for await (const ev of await hb.streamOrgEvents({ query: { type: "prompt.finished" } })) { console.log(ev.sandbox, ev.data); }Compare cost, keep the winner
See what each branch cost, keep the best result, and delete the rest.
CLI
harebox usage --all --group-by label harebox delete LOSING_IDPython
for box in forks: print(box.id, hb.get_sandbox_usage(box.id)["total_usd"])TypeScript
for (const box of forks) console.log(box.id, (await hb.getSandboxUsage(box.id)).total_usd);
Tips
- A fork copies memory, so it copies session tokens too. Rotate tokens in a post-fork step if an app holds one.
- Put a budget on the experiment's label before you start, so the whole fleet has one ceiling.
- Use
--countrather than a loop: one call is one start-rate check and one idempotent request. - Forks of a stopped sandbox start from its disk; forks of a running one copy memory too.
Related use cases
A coding agent on your repository, with a spending cap
Hand an issue to Claude Code, Codex or OpenCode in a clean VM, follow it live, cap what it can spend, and get a pull request back.
See the stepsBrowser automation and scraping at scale
Run real Chrome with persistent profiles on a real desktop, record sessions for audit, and fork a logged-in browser into many.
See the stepsCI runners with a whole VM
Run tests that need Docker, systemd or KVM on a fresh VM per job, from GitHub Actions or any CI, billed by the second.
See the steps

