Sandbox providers
A worker always runs in a sandbox: a throwaway workspace cloned from the project repo. Where that sandbox lives is the provider.
| Provider | Where the worker runs | When to use |
|---|---|---|
local (default) | A host process on the agent VM, in the worker sandbox directory | One dedicated VM per project; the common case |
e2b | Inside an E2B-compatible remote sandbox | Offload heavy or untrusted runs, or keep the agent VM small |
One client serves E2B Cloud and self-hosted CubeSandbox; only the endpoint and API key change. The worker lifecycle is the same either way: the agent holds a worker lease, admission bounds how many run at once, and checkpoints capture the work.
Configure a provider
Section titled “Configure a provider”Set the keys on the Config surface (or PATCH /api/config):
| Key | Values | Default |
|---|---|---|
sandbox_provider | local, e2b | local |
sandbox_endpoint | E2B-compatible control-plane URL, e.g. https://api.e2b.app | empty — required for e2b |
sandbox_template | Template/image id, e.g. tpl-… | empty — required for e2b |
sandbox_work_dir | Working directory inside the sandbox | /workspace |
sandbox_idle_timeout_secs | Sandbox idle TTL | 0 (provider default) |
sandbox_cpu | vCPUs (v1: informational; bake CPU into the template) | 0 (provider default) |
sandbox_memory_mb | Memory MiB (v1: informational) | 0 (provider default) |
sandbox_max_concurrency | Provider sandbox cap; 0 means only max_workers bounds the pool | 0 |
sandbox_reap_minutes | Orphan sandbox sweep cadence; 0 disables | 15 |
Remote workers fail closed: with sandbox_provider=e2b and a missing endpoint or template, spawns do not fall back to the host.
The API key is not a config key. Store it as the sandbox credential (kind token) in Credentials; it is sent as X-API-KEY on provider requests and never logged.
Template contract
Section titled “Template contract”For e2b, the template must carry everything a worker needs — the provider only supplies the command and environment:
- the Pi coding CLI (
pi) onPATH, matchingcoding_runtime(legacy runtime names resolve to Pi); bash,tee, and coreutils — the provider wraps the worker so its output is captured inside the sandbox (<work_dir>/.steelframe/worker.outand.exit), which survives an agent restart;git(the workspace is a clone; checkpoints shell out togit);nodefor the Node-based Pi CLI andghfor PR creation;envdlistening on port49983(E2B templates and CubeSandbox base images already include it);- a writable
sandbox_work_dir.
Example for CubeSandbox:
ARG CUBE_BASE_IMAGE=ghcr.io/tencentcloud/cubesandbox-base:2026.16FROM ${CUBE_BASE_IMAGE}RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates curl git gnupg jq ripgrep \ && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ && apt-get install -y --no-install-recommends nodejs \ && curl -fsSL https://pi.dev/install.sh | sh \ && rm -rf /var/lib/apt/lists/*WORKDIR /workspaceEXPOSE 49983What to expect
Section titled “What to expect”- Egress allowlist. Remote sandboxes are created with host-keyed network rules: GitHub, crates.io, and npm, plus the Pi model API host — the catalog provider’s host for a
<provider>/<id>model, orcoding_runtime_base_urlfor asteelframe/*model. The local llama-server (http://127.0.0.1:8080/v1) is unreachable from a remote sandbox — pointcoding_runtime_base_urlat a host the sandbox can reach, or the first model call fails. - Re-adoption. A remote worker’s pid and captured output let the agent re-attach after an agent restart; local workers are killed on restart and resume their durable Pi Coding session on the task’s respawn.
- Reap. The watchdog deletes managed sandboxes no lease holds on
sandbox_reap_minutes. - Snapshots. Final remote checkpoints request a provider snapshot and record its id on the checkpoint; the git inspection stays the authoritative record.
- Kills. Remote kills signal the wrapper pid; the idle TTL and reap sweep are the backstop.
Known limitations
Section titled “Known limitations”sandbox_cpu and sandbox_memory_mb are logged but the compatible create API takes them from the template. The real cloud path is not exercised in CI — smoke it on a staging deployment before trusting it, and keep sandbox_work_dir absolute there. Remote worker stderr is merged into the captured stdout.