OxagenDocs
CLI

Sandbox templates

Portable sandbox templates from the CLI — capture a provider/runtime/tools config once, bind agents to it, and move it between workspaces as a manifest that never carries secret values.

When an agent runs code it does so inside a sandbox — a provisioned, isolated environment with a provider (Modal, Vercel, or Docker), a runtime image, resource caps, a network posture, some non-secret config, a set of preloaded tools, and the workspace secrets it is allowed to see. A sandbox template captures that whole recipe once, under an environment, so every agent bound to it provisions the same way. Templates are portable: you can export one as a manifest and import it into another workspace or organization.

A manifest never carries secret values. Export writes the required secret key names only (e.g. EVAL_API_KEY), so a shared template shows the recipient exactly which credentials to fill in — without ever leaking yours. Import upserts those empty key rows into the destination vault.

Everything here requires platform auth (oxagen login), and template writes are Owner/Admin only. The same capabilities back the API, MCP tools, and the app — the CLI is just the flag-driven surface.

Environments

A template always lives under an environment (env_…). Manage those with oxagen env; most template commands take --env <slug> to pick or disambiguate one. Secrets are managed per-environment with oxagen secret — a template's secretSelection decides which of those keys resolve into the sandbox at run time.

List and inspect

oxagen sandbox template list                 # every template in the workspace
oxagen sandbox template list --env staging    # just one environment
oxagen sandbox template list --json           # machine-readable, for scripting

oxagen sandbox template get swe-bench-prewarmed
oxagen sandbox template get sbx_abc123 --json

get accepts a slug or a sbx_… public id. When a slug is ambiguous across environments, add --env <slug> to pin it. In pretty mode it prints the resources, network mode, secret selection, literal env, and preloaded tools; --json emits the full template object on one line.

Create a template

oxagen sandbox template create \
  --env staging \
  --name "SWE-bench prewarmed" \
  --slug swe-bench-prewarmed \
  --provider modal \
  --runtime "ghcr.io/acme/swe-bench-prewarmed@sha256:…" \
  --vcpu 2 --memory-mb 4096 --timeout-ms 300000 \
  --network-mode public \
  --env-var SWEBENCH_SPLIT=verified \
  --set-default

Only --env, --name, and --slug are required; every other field falls back to a driver default. Notes:

  • --provider is modal, vercel, or docker. The provisioner fails fast if that driver has no credentials configured.
  • Resource caps are bounded: --vcpu ≤ 4, --memory-mb ≤ 8192, --timeout-ms ≤ 300000, --disk-mb ≤ 20480. Each must be a positive integer.
  • --network-mode is one of public, static_egress, aws_privatelink, gcp_psc, reverse_tunnel, ssh_bastion. Only public and static_egress are implemented today; the others fail fast at provision time.
  • --env-var KEY=value is repeatable and is for non-secret literal config only — injected at lowest precedence. Real credentials belong in the vault (oxagen secret set), never here.
  • --set-default promotes the new template to its environment's default. Runs that don't name a template resolve to it.

Exactly one template per (workspace, environment) is the default. --set-default atomically swaps it.

Promote a default, remove a template

oxagen sandbox template set-default python-worker --env staging
oxagen sandbox template rm old-worker --env staging --yes

rm soft-deletes and requires --yes. A default template can't be deleted — promote another one in the same environment first.

Export and import (portability)

Export a template to a portable manifest — to stdout by default, or to a file:

oxagen sandbox template export swe-bench-prewarmed              # prints JSON
oxagen sandbox template export swe-bench-prewarmed -o swe.json   # writes a file

Import is preview-then-commit, like oxagen secret import. Without --yes you get a summary and warnings and nothing is written:

# Preview only — no changes:
oxagen sandbox template import --env staging -f swe.json

# Apply it, overriding the slug to avoid a collision, as the new default:
oxagen sandbox template import --env staging -f swe.json --slug swe-2 --set-default --yes

The preview flags required secret keys (created empty in the destination — fill them before provisioning) and any structural problems. On commit the server is the authoritative validator and returns warnings for a slug collision or for tool refs not installed in the destination workspace — those tools are simply skipped at provision time, so a template stays portable even if the target hasn't installed every plugin it references.

Bind an agent to an environment

A template only takes effect once an agent is pointed at its environment. Bind a platform agent (a agt_… id, slug, or agent-key) with oxagen agent env:

oxagen agent env bind coder --env staging --template swe-bench-prewarmed --primary
oxagen agent env list coder
oxagen agent env unbind coder --env staging

Omit --template to bind to the environment and let it resolve to that environment's default template at run time. The agent's first binding becomes its primary automatically; --primary promotes another and atomically demotes the previous. Unbinding the primary falls back to the workspace default environment and its default template.

Scripting

Every read supports --json (one JSON value on stdout; progress and warnings stay on stderr), so templates compose cleanly with jq:

# The default template's runtime image in staging:
oxagen sandbox template list --env staging --json \
  | jq -r '.[] | select(.isDefault) | .runtime'

# Copy a template from one workspace to another:
oxagen sandbox template export swe-bench-prewarmed -o /tmp/t.json
OXAGEN_WORKSPACE_ID=ws_other oxagen sandbox template import --env default -f /tmp/t.json --yes

On this page