The sandbox model
A sandbox is a fresh, single-session virtual machine. The harness and its tools run as a non-root workspace user (user, home /home/user); repositories mount under paths you declare (conventionally under /workspace). When the session ends, the sandbox goes away — durable state lives in git, in the provider surfaces the agent writes to, and in the session transcript.
The sandbox is the isolation boundary. That is why unattended operation works: by default every harness action is auto-approved inside the sandbox (see approvals below), and the blast radius of any command is the sandbox itself plus whatever credentials you deliberately handed the session. GitHub API credentials never sit in the sandbox at all — they are minted per-call by the platform’s brokered GitHub proxy (see GitHub MCP).
Every sandbox image also carries the agent toolchain baked in at build time: pinned versions of Claude Code and Codex, plus git and curl. You never install a harness in your own steps.
Layers of an environment
An environment recipe has three layers, distinguished by when they run and how they are cached:Base image: preset or direct reference
Use a named preset when one matches the repository:node24 and the legacy default alias resolve to node:24-bookworm-slim; explicit node22 and its legacy linux-node22 alias resolve to node:22-bookworm-slim. A direct base reference is also supported:
Build steps
steps are Dockerfile commands appended after the platform’s harness bootstrap. Use them for system packages and pinned command-line binaries — anything every session should find already installed:
Per-session setup
setup commands run when the sandbox is prepared, inside the agent’s working directory (the first git mount), as the workspace user, with a 10-minute timeout per step. This is where repository-dependent work belongs — installing workspace dependencies, fetching browsers:
- Declared cache paths. Each step can name directories under
/home/userto persist across sessions. Before the commands run, cached contents are restored; after they succeed, the paths are persisted back. The invalidation key is the step’scache.key(defaulting to the step name) combined with a hash of the listedfiles— changepackage-lock.jsonand the npm cache misses cleanly. - Snapshot reuse. When an environment declares setup, the platform bakes a post-setup snapshot and reuses it for subsequent sessions until the
setupCache.ttlwindow (default seven days) expires or the recipe changes.
npm ci into a warm start for every session after the first.
Resources
Environments can request CPU and memory for their sandboxes:cpuCount must be at least 1 and memoryMB at least 128; declare at least one of them if the block is present. Size for the heaviest thing the agent actually does — Docker-Compose-backed integration stacks want more headroom than a chat agent.
Environment variables and secrets
Agents and environments both accept anenv map. Values are plain strings or references into the project’s encrypted secret store:
optional: true means a missing secret omits the variable instead of failing the launch — useful for capabilities that should degrade gracefully until an org secret exists. Variable names that the platform’s own bootstrap reserves are rejected before launch, so agent env can never shadow the runtime’s wiring.
Secrets configured for injection never enter the sandbox at all: the sandbox sees a placeholder, and the provider’s network edge injects the real value into request headers for exactly the hosts the secret names (exact host match — no wildcards, and a parent domain does not cover its subdomains). Prefer injection for API keys whose only job is authenticating HTTP calls.
Approvals
approvals sets the harness’s permission posture inside the sandbox: bypass (the default when absent) auto-approves every harness action, so unattended sessions never stall on a permission prompt; prompt opts the environment back into the harness’s own approval escalation for operator-attended use. Today only the codex harness consults it — claude-code always runs with permissions bypassed, relying on the sandbox boundary.
Reuse: inline environments and fragments
An agent must resolve to exactly one environment after its imports merge. There are two ways to supply it. Inline — declare the environment object directly on the agent. The compiler splits it out into a generatedenvironment resource; the agent keeps only the name:
.auto/agents/digest.yaml
harness) in a fragment under .auto/fragments/environments/ and import it from every agent that runs there:
.auto/fragments/environments/agent-runtime-base.yaml
.auto/agents/staff-engineer.yaml
Where the code appears
Environments describe the machine; mounts describe the code on it. Each git mount clones a repository to itsmountPath, and the agent’s working directory defaults to the first mount’s path (a relative workingDirectory resolves inside it and may not escape it). Setup commands run in that working directory — an environment with setup but no mounts has nowhere to run it, so setup is skipped.
Environment reference
Every field: image, steps, setup, cache, resources, approvals.
Mounts reference
Git mounts, auth capabilities, refs, and clone depth.
Secrets reference
The project secret store, $secret references, and injection.
Sandbox runtime
What is running inside the sandbox once a session starts.