Skip to main content

Sandbox backends

Sandbox support is intentionally incremental. A backend is not presented as production-ready merely because it can execute a command: its isolation model, lifecycle guarantees, operational dependencies, and known limits must also be clear.

Local and Docker execution do not add another HTTP service. Remote adapters call an independently deployed sandbox service through the same in-process Go boundary:

Temporal Activity -> SessionManager -> sandbox.Provider -> sandbox.Sandbox

SessionManager gives each session one logical sandbox. PostgreSQL persists the provider name and opaque external ID; a restarted worker calls Attach instead of creating an empty replacement. Sandbox exposes command execution, confined file access, a workspace root, and teardown. The execution worker selects one compiled adapter through an internal registry. MANAGED_AGENT_SANDBOX accepts local (the default), docker, e2b, cube, opensandbox, or daytona; an unknown name fails startup instead of falling back to host execution. Provider selection does not add fields to the Managed Agents Environment or Session APIs.

Support levels

  • Available: implemented, documented, and exercised by repository tests.
  • Preview: implemented with offline and opt-in live conformance, but still awaiting promotion based on repeatable service-level validation.
  • Planned: selected for a dedicated adapter, but not implemented.
  • Evaluating: useful integration shape, without a committed adapter.

These labels describe project support, not a security certification.

Backend matrix

BackendStatusIsolation modelSession stateIntended use
Local processAvailable; defaultHost process plus confined workspace; not an isolation boundaryReattaches by durable workspace path on the same hostOffline tests and trusted local development only
DockerAvailable; opt-inContainer filesystem, namespaces/cgroups, configurable limits, network disabled by defaultReattaches by container ID on the same Docker daemonControlled single-host self-hosting
E2BPreviewManaged microVM serviceE2B ID plus auto-pause filesystem persistenceManaged production
Tencent CubeSandboxPreviewE2B-compatible microVM serviceProvider-owned durable sandbox IDSelf-hosted production on Linux/KVM
OpenSandboxPreview; Docker runtime manually live-verifiedDocker or Kubernetes-backed sandbox serviceProvider-owned durable sandbox IDSelf-hosted production
DaytonaPreviewManaged or self-hosted sandbox serviceDeterministic name, durable ID, and auto-pauseManaged production
ModalPlannedManaged sandbox serviceProvider-owned durable sandbox IDManaged production
RunloopPlannedManaged devbox serviceSuspend, resume, and snapshot lifecycleManaged production
Kubernetes SIG Agent SandboxPlannedKubernetes CRD, controller, and routing layerStateful sandbox resourceKubernetes deployments
Anthropic Sandbox Runtime, Vercel Sandbox, and Cloudflare SandboxEvaluatingBackend-specificBackend-specificLater adapters

The Docker provider has not been audited for hostile multi-tenant workloads. The local provider is not a security boundary. No backend currently carries a production security claim.

Compatibility contract

A backend implements the core lifecycle contract when it can:

  1. expose a stable provider name;
  2. idempotently create one resource for a session key;
  3. attach to a persisted opaque reference after restart;
  4. execute a command with cancellation and bounded output;
  5. read and write paths relative to the workspace;
  6. destroy the resource idempotently.

These requirements are executable in internal/sandbox/sandboxtest. Local, Docker, and every remote provider's opt-in live test run the same suite, including cross-client Create/Attach, workspace preservation, ownership rejection, cancellation, and post-delete missing-reference behavior. Offline adapter tests cover the same contract without credentials. Provider-specific tests cover protocol translation, isolation, and resource controls separately.

The built-in toolset currently assumes a POSIX-like environment with /bin/sh, find, and grep. A backend that does not provide those commands is not compatible with all executing built-ins yet.

Lifecycle today

  • The first tool-using run idempotently creates the provider resource and persists {provider, external_id, spec_hash} in PostgreSQL.
  • Remote services receive a fixed-length hash of the session key as their ownership label; credentials and raw session identifiers are not persisted in the provider reference.
  • Later turns reuse the cached client; a restarted worker attaches through the persisted reference.
  • Different sessions never share a logical sandbox.
  • Becoming idle retains it.
  • Deleting the session fences admission, stops its Session Workflow, durably retries provider teardown on the worker, removes the binding, and only then deletes the session row.
  • A persisted reference that no longer exists fails explicitly; Mango does not silently replace lost workspace state with an empty sandbox.

Required production lifecycle

Remote adapters must use the same lifecycle tests. Production deployments still need orphan reconciliation for the create-before-binding crash window, provider health reporting, and provider-aware task routing when heterogeneous workers share a control plane. Pause, snapshot, fork, quotas, and eviction remain optional capabilities rather than requirements of the core interface.

Remote provider configuration

Credentials stay in worker configuration. They are never written to PostgreSQL or returned by the Managed Agents API.

ProviderRequiredCommon optional values
e2bE2B_API_KEYE2B_API_URL, E2B_TEMPLATE_ID, E2B_DOMAIN, E2B_IDLE_TIMEOUT
cubeCUBE_API_URL, CUBE_TEMPLATE_IDCUBE_API_KEY, CUBE_SANDBOX_DOMAIN, CUBE_PROXY_*, CUBE_IDLE_TIMEOUT
opensandboxOPEN_SANDBOX_DOMAINOPEN_SANDBOX_API_KEY, OPEN_SANDBOX_IMAGE, OPEN_SANDBOX_USE_SERVER_PROXY
daytonaDAYTONA_API_KEYDAYTONA_API_URL, DAYTONA_TARGET, DAYTONA_SNAPSHOT, DAYTONA_IMAGE, DAYTONA_AUTO_PAUSE_MINUTES

For local development, make dev-env-init creates ~/.config/mango/dev.env from config/dev.env.example with mode 0600. scripts/with-dev-env <command> loads it explicitly and works across worktrees.

Live conformance is opt-in:

scripts/with-dev-env env MANGO_LIVE_E2B=1 \
go test ./internal/sandbox -run '^TestE2BLiveConformance$' -count=1

scripts/with-dev-env env MANGO_LIVE_OPENSANDBOX=1 \
go test ./internal/sandbox -run '^TestOpenSandboxLiveConformance$' -count=1

The equivalent gates are MANGO_LIVE_CUBE and MANGO_LIVE_DAYTONA. Ordinary tests never contact a service or create billable resources.

The upstream behavior informing the session/environment distinction is documented in Claude's cloud environment setup and self-hosted sandbox guides. managed-agent-go remains an independent implementation and does not claim Anthropic's hosted isolation properties.

Adding a backend

A backend contribution should:

  • keep its external dependency optional and fail fast when explicitly selected but unavailable;
  • register a lazy factory under a stable lowercase provider name and pass the shared sandboxtest lifecycle suite;
  • preserve the session-scoped ownership contract;
  • document its trust boundary, network defaults, resource controls, host requirements, and unsupported lifecycle features;
  • keep default tests offline and make daemon/network-dependent tests opt-in;
  • avoid changing the AgentRuntime or public HTTP API for provider-specific mechanics;
  • avoid a production or multi-tenant safety claim without evidence and an explicit security review.

Open an issue before a substantial backend integration so the intended use case and lifecycle implications can be reviewed independently of the adapter code.