> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boat.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Run many agents in parallel

> Fork one prepared sandbox into N copies and give each copy its own agent task, from the CLI or Python. Stay under the start limits.

Prepare one sandbox, fork it N times, and prompt each fork. Each agent gets its own disk, processes and IP address. They do not interfere.

To run a few tasks on one sandbox instead, use [parallel conversations](/integrated-agents/conversations#parallel-conversations). They share one disk and one desktop.

## Watch the start limits

Each fork counts as one start. Above a limit, Boat refuses the fork with `429 rate_limited`. The answer names the `window` that you hit.

| Plan | Starts per minute / hour / day | Sandboxes at once |
| - | - | - |
| \$20 | 12 / 60 / 200 | 100 |
| \$100 | 30 / 210 / 840 | 300 |
| \$500 | 65 / 420 / 1,680 | 1,000 |
| \$2000 | 90 / 600 / 2,400 | 2,000 |
| [Free trial](/free-trial) | 5 / 25 / 75 | 2 |

* An organization gets these limits times its number of seats.
* Pace your forks below the per-minute limit. The examples below wait 6 seconds between forks, which fits the \$20 plan.

Read [Limits and errors](/limits) for every limit and how to raise it.

## 1. Prepare the source sandbox

```bash theme={null}
boat new
boat exec bx_f7k2q9hd --cwd web-app --timeout 600 "npm ci"
boat stop bx_f7k2q9hd
```

A fork copies the newest snapshot of its source. Stop the source first, so that its snapshot has your last change. A fork of a running sandbox can miss the writes of the last minute.

The source needs your AI keys. Read [Run a coding agent on your repo](/recipes/agent-on-repo) for the environment settings.

## 2. Fork N copies and prompt each one

<CodeGroup>
  ```bash CLI theme={null}
  source=bx_f7k2q9hd
  tasks=("Fix issue 101" "Fix issue 102" "Fix issue 103" "Fix issue 104")

  for task in "${tasks[@]}"; do
    id=$(boat fork "$source" --ttl 7200 --json | jq -r .id)
    echo "$id" >> forks.txt
    boat prompt "$id" "$task" > "$id.log" 2>&1 &   # runs in the background
    sleep 6                                         # stay under the start limit
  done
  wait                                              # every agent is done
  ```

  ```python Python theme={null}
  import os, time, uuid
  from boat_sdk import ApiClient, Configuration, wait_until_ready, wait_for_prompt
  from boat_sdk.api.boat_api import BoatApi
  from boat_sdk.exceptions import ApiException
  from boat_sdk.models.fork_request import ForkRequest
  from boat_sdk.models.prompt_request import PromptRequest

  config = Configuration(host="https://boat.dev/api/v1", access_token=os.environ["BOAT_API_KEY"])
  source = "bx_f7k2q9hd"
  tasks = ["Fix issue 101", "Fix issue 102", "Fix issue 103", "Fix issue 104"]

  with ApiClient(config) as client:
      sandbox = BoatApi(client)
      runs = []
      for task in tasks:
          key = str(uuid.uuid4())   # the same key on a retry never makes a second fork
          while True:
              try:
                  forked = sandbox.fork(
                      sandbox_id=source,
                      fork_request=ForkRequest(ttl_seconds=7200),
                      idempotency_key=key,
                  )
                  break
              except ApiException as exc:
                  if exc.status != 429:
                      raise
                  time.sleep(10)    # start limit hit: wait, then retry with the same key
          wait_until_ready(sandbox, forked.id)
          queued = sandbox.prompt(forked.id, PromptRequest(prompt=task))
          runs.append((forked.id, queued.prompt_id))
          time.sleep(6)             # stay under the start limit

      for sandbox_id, prompt_id in runs:
          run = wait_for_prompt(sandbox, sandbox_id, prompt_id)
          print(sandbox_id, run.status)
  ```
</CodeGroup>

* `--ttl 7200` gives each fork a 2-hour auto-stop. A fork never copies the auto-stop setting of its source. A running prompt moves the deadline by itself.
* `Idempotency-Key` makes a retry safe. Without it, a retry after a lost answer can make a second fork that you pay for.
* Prompts queue while a fork starts. You do not have to wait for `ready` before a prompt. The Python example waits only to fail early on a bad fork.

## 3. Collect the results and clean up

Each `<id>.log` file holds the work of one agent. Then read the result in each fork and stop or delete it:

```bash theme={null}
while read -r id; do
  boat exec "$id" --cwd web-app "git log --oneline -1"
done < forks.txt

boat stop bx_k3v9x2mq           # keep the disk of a fork; boat resume brings it back
boat delete bx_p8w4z7nc --yes   # erase a fork that you do not need
```

A fork that you do not stop stops by itself at its auto-stop deadline.

## Related

* [Resume and fork](/snapshots/resume-and-fork)
* [Use a named snapshot as a template](/platform-guide/templates-and-sizing)
* [Stream events](/integrated-agents/conversations#stream-events)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.