Skip to content

Agent sandbox

A sandbox is a Pod that runs one agent for one task run; this page covers its lifecycle, its identity and what runs inside it.

Sandbox lifecycle

A sandbox is a Pod that runs one agent for one task run. With the warm pool on (Enable Agent-Sandbox Warm Pool (CRD), off by default), the deployment keeps a pool of pre-provisioned sandboxes (Agent-Sandbox Warm Pool Size, default 3) so that a task does not wait for a Pod to start. When the pool is empty, a task falls back to a sandbox created on demand.

stateDiagram-v2
[*] --> Pooled
Pooled: Pooled (no task, no identity)
Bound: Bound (task labels applied)
OnDemand: Created on demand (no pooled sandbox)
Live: Identity live (epoch active)
Ready: Runtime ready (harness running)
Running: Running (agent working)
Idle: Idle (waiting for a prompt)
Revoked: Identity revoked
Deleted: Deleted
Pooled --> Bound: claimed
Bound --> OnDemand: bind check fails
Bound --> Live: attested
OnDemand --> Live: attested
Live --> Ready: harness started
Ready --> Running: prompt delivered
Running --> Idle: turn complete
Idle --> Running: next prompt
Idle --> Revoked: run ends
Revoked --> Deleted: deleted
Deleted --> [*]
StateMeaningNext state
PooledNo task, no identityBound (claimed)
BoundTask labels appliedIdentity live (attested), or Created on demand (bind check fails)
Created on demandNo pooled sandboxIdentity live (attested)
Identity liveEpoch activeRuntime ready (harness started)
Runtime readyHarness runningRunning (prompt delivered)
RunningAgent workingIdle (turn complete)
IdleWaiting for a promptRunning (next prompt), or Identity revoked (run ends)
Identity revokedDeleted
  1. A pooled sandbox has no task and no identity; its agent runtime is already running. When a task needs one, it is claimed and labeled with the task, run and agent.
  2. A claim is accepted only if the sandbox can enforce the in-sandbox tool policy, was built from the current template and passes the identity bind (sidecar present; model hosts point at the live egress proxy). Otherwise the claim is discarded and a sandbox is created on demand.
  3. The task does not start until the sandbox’s identity is live (see Sandbox identity).
  4. At the end of the run, identity is revoked first; the claim and the sandbox are then deleted. A sandbox bound to a task is also deleted two days after it was bound, whatever its state. Pooled sandboxes that were never claimed are replaced when the sandbox template changes.
  5. The sandbox’s working files are on an ephemeral volume deleted with the Pod. Results persist only if the agent saves them to the drive.

The identity states and steps above apply with Sandbox Workload Identity on. With it off (the default), there is no identity to establish or revoke, and the sandbox runs with a Context API key scoped to its agent and run that expires after 24 hours.

Sandbox identity

Workload identity is controlled by the installer setting Sandbox Workload Identity, which is off by default. With it on, sandboxes hold no credentials for your data: each sandbox proves its identity to the application tier through a separate sidecar container, and afterwards its requests are recognized by its network address. With it off, there is no identity sidecar and no identity epoch; the sandbox authenticates with a scoped Context API key that expires after 24 hours and calls the model gateway with the gateway key (see Without Sandbox Workload Identity). The rest of this section describes a sandbox with it on.

sequenceDiagram
autonumber
participant W as Temporal worker
participant K as Kubernetes API
participant C as Sandbox controller
participant S as Identity sidecar (uid 1001)
participant R as Agent runtime (uid 1000)
participant B as Identity broker
participant D as Identity records (Amazon RDS)
participant E as Enforcement points
W->>D: create epoch and single-use bootstrap value
W->>K: create labeled Sandbox, then bootstrap ConfigMap
C->>K: create Pod; projected token (broker, 600 s)
S->>B: bootstrap value + projected token, over TLS
B->>D: bootstrap pending, unexpired, matching
B->>K: read Pod: IP, ServiceAccount, owner, network
B->>K: TokenReview; re-read Pod
B->>D: epoch live; bind Pod name, UID and IP
B->>S: capability token, 600 s lease
S->>R: readiness signal releases the runtime
W->>D: wait for the live epoch (up to 65 s)
W->>R: start the harness, deliver the prompt
R->>E: request identified by source Pod IP
E->>D: live epoch for this IP? (cached 2 s)
S->>B: renew about every 8 minutes
W->>D: teardown: revoke epochs
W->>K: delete claim and Sandbox

The handshake for a sandbox created on demand:

StepFromToWhat happens
1Temporal workerIdentity recordsCreate epoch and single-use bootstrap value
2Temporal workerKubernetes APICreate labeled Sandbox, then bootstrap ConfigMap
3Sandbox controllerKubernetes APICreate Pod; projected token (audience: the broker, 600 s)
4Identity sidecarIdentity brokerBootstrap value + projected token, over TLS
5Identity brokerIdentity recordsCheck the bootstrap is pending, unexpired and matching
6Identity brokerKubernetes APIRead Pod: IP, ServiceAccount, owner, network
7Identity brokerKubernetes APITokenReview; re-read Pod
8Identity brokerIdentity recordsEpoch live; bind Pod name, UID and IP
9Identity brokerIdentity sidecarCapability token, 600 s lease
10Identity sidecarAgent runtimeReadiness signal releases the runtime
11Temporal workerIdentity recordsWait for the live epoch (up to 65 s)
12Temporal workerAgent runtimeStart the harness, deliver the prompt
13Agent runtimeEnforcement pointsRequest identified by source Pod IP
14Enforcement pointsIdentity recordsLive epoch for this IP? (cached 2 s)
15Identity sidecarIdentity brokerRenew about every 8 minutes
16Temporal workerIdentity recordsTeardown: revoke epochs
17Temporal workerKubernetes APIDelete claim and Sandbox

For a pooled sandbox, the Pod (step 3) already exists and its agent runtime is running. Just before the claim, the worker creates the identity epoch (step 1), adds the task labels to the Pod, and the broker delivers the bootstrap value to the sidecar over TLS instead of a ConfigMap (step 2). Steps 4 to 9 follow; step 10 does not apply, and in step 12 the harness is already running.

  1. The identity sidecar runs as a separate operating-system user with its own volumes. It is the only container that holds the projected ServiceAccount token and the capability token; the agent runtime container has no Kubernetes token.
  2. The broker attests a sandbox by its source IP, ServiceAccount, owner reference and a Kubernetes TokenReview before marking its identity live. Only one live identity can exist for an IP address.
  3. Enforcement points recognize a sandbox by its source Pod IP bound to a live identity. The capability token is used only to renew the identity and is never presented to enforcement points.
  4. Identity is revoked before a sandbox is deleted. A revoked identity can still be honored for up to 2 seconds by default (10 seconds at most) because of a short-lived cache (S-08).
  5. Recognition by IP address relies on the cluster network preventing address spoofing. Network policy enforcement in your cluster is your responsibility (S-14).

Inside the sandbox

ProcessUserNotes
Harnessuid 1000Runs the agent loop; port 4096; applies the in-sandbox tool policy ◇
Identity sidecaruid 1001Holds the projected token and the capability token
Toolsuid 1000bash, read, write, edit, MCP tool, drive search
CLI toolsuid 1000context-cli, rclone, context-web-search
Agent-generated codeuid 1000Same user as the harness

The harness’s tools are bash, read, write and edit, terminal sessions, the MCP connector tool, drive search and agent-browser; context-cli, rclone and context-web-search run through bash. Which harness runs is set by the installer (see Glossary). The drive search tool is provided by the OpenCode harness; on the default harness it is not yet available.

Pod settings:

  • Non-root; no privilege escalation.
  • Capabilities dropped; no host network.
  • No hardened runtime class (S-09).
  • No Kubernetes token or IAM role.

For every network path out of the sandbox, see Sandbox network paths.