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

# Sandbox pools

> Share sandbox execution capacity across jobs with fenced leases and explicit cleanup.

**Agent environments** define interaction and deployment. **Sandbox pools** govern
shared execution capacity. **Tasksets** define the work. These resources have
different lifecycles and separate pages.

A pool has a Docker or E2B backend, total concurrent trial slots, a per-job limit,
a lease timeout, and an allowed-user list. One lease reserves one **trial slot**;
it is not a measurement of physical containers, CPUs or provider billing. A trial
may involve additional verifier services, so provision backend capacity accordingly.

## Provision and register

Provision the provider account or Docker runtime first, then create a pool in
**Assets → Sandbox pools** as an administrator. Use a single pool for capacity
shared by the same jobs; duplicate pools pointing at the same provider do not
share a budget. The allowed-user field accepts comma-separated usernames, or `*`
for all platform users. Creating a pool does not deploy machines, grant Docker
access, store provider credentials or create warm sandboxes.

Operators see authorized pools and their own leases. Administrators manage limits,
see all leases, drain pools and confirm cleanup. The page shows available,
occupied and cleanup-required slots, with unreleased leases first and pagination.

## Use from Agent evaluations

Select a matching active pool in **Agent evaluations**. The prepared configuration
records its ID. Run it through the `harbor-eval` experiment in `tuneplane-examples`.
The worker obtains one lease before each trial, waits when capacity is full,
renews while running, and releases after explicit provider cleanup succeeds.
The configured per-job concurrency must not exceed the pool's per-job limit.

The pool applies to jobs using its lease API. A job without a selected pool keeps
only its local concurrency limit. Existing OpenEnv runner registration does not
automatically acquire pool leases. Other training harnesses must integrate the
same acquire/renew/release contract in their user project or environment plugin.
The control plane does not execute agents or call provider SDKs.

## Drain, revoke and recover

* **Drain** stops new allocation. Existing leases can renew and finish normally.
* **Revoke lease** marks its slot as requiring cleanup. A cooperating worker stops
  when its next renewal is refused, then attempts provider cleanup.
* **Lease timeout** marks a lost worker's slot as requiring cleanup. It does not
  prove that the remote sandbox was deleted, so it does not restore capacity.
* **Confirm provider cleanup and release** is an administrator action. First
  delete or verify absence of the provider resources, then record evidence in the
  page. This action releases accounting capacity; it does not call the provider.

A worker that fails cleanup reports it immediately. A killed worker requires
provider TTLs or operator reconciliation. Cleanup uncertainty keeps capacity
occupied deliberately. Reducing capacity below occupied slots is refused, and
old attempts still count toward a run's limit until their resources are cleaned.

## Worker API

Use an attempt-bound job ingest token, not a user's console token:

| Operation      | Endpoint                                               | Body                                         |
| -------------- | ------------------------------------------------------ | -------------------------------------------- |
| Acquire        | `POST /api/ingest/sandbox-pools/{pool}/leases`         | `request_key`, `provider`                    |
| Renew          | `POST /api/ingest/sandbox-pools/{pool}/leases/{lease}` | `action: renew`                              |
| Release        | Same lease endpoint                                    | `action: release`, `cleanup_confirmed: true` |
| Cleanup failed | Same lease endpoint                                    | `action: abandon`                            |

An acquisition key identifies one trial within one job attempt and is idempotent
while its lease is active. Never reuse it after completion or expiration. Capacity
exhaustion returns 429; retry with backoff. Draining, expiration or a superseded
attempt returns 409. Retry/resume tokens cannot renew earlier attempts. An old
attempt can confirm cleanup of its own lease while its job record still exists.

The example adapter explicitly awaits `agent_environment.stop(delete=True)`;
only successful completion releases the lease. Its runtime therefore needs that
Harbor API and idempotent provider cleanup. Local tests exercise the lifecycle
through a fake runtime, not a real Docker or E2B deployment. Provider credentials,
native cleanup and large-scale throughput require deployment-level validation.
