Skip to content

Sandbox providers

A worker always runs in a sandbox: a throwaway workspace cloned from the project repo. Where that sandbox lives is the provider.

ProviderWhere the worker runsWhen to use
local (default)A host process on the agent VM, in the worker sandbox directoryOne dedicated VM per project; the common case
e2bInside an E2B-compatible remote sandboxOffload 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.

Set the keys on the Config surface (or PATCH /api/config):

KeyValuesDefault
sandbox_providerlocal, e2blocal
sandbox_endpointE2B-compatible control-plane URL, e.g. https://api.e2b.appempty — required for e2b
sandbox_templateTemplate/image id, e.g. tpl-…empty — required for e2b
sandbox_work_dirWorking directory inside the sandbox/workspace
sandbox_idle_timeout_secsSandbox idle TTL0 (provider default)
sandbox_cpuvCPUs (v1: informational; bake CPU into the template)0 (provider default)
sandbox_memory_mbMemory MiB (v1: informational)0 (provider default)
sandbox_max_concurrencyProvider sandbox cap; 0 means only max_workers bounds the pool0
sandbox_reap_minutesOrphan sandbox sweep cadence; 0 disables15

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.

For e2b, the template must carry everything a worker needs — the provider only supplies the command and environment:

  • the Pi coding CLI (pi) on PATH, matching coding_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.out and .exit), which survives an agent restart;
  • git (the workspace is a clone; checkpoints shell out to git);
  • node for the Node-based Pi CLI and gh for PR creation;
  • envd listening on port 49983 (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.16
FROM ${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 /workspace
EXPOSE 49983
  • 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, or coding_runtime_base_url for a steelframe/* model. The local llama-server (http://127.0.0.1:8080/v1) is unreachable from a remote sandbox — point coding_runtime_base_url at 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.

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.