Skip to main content
Bind secrets when you create a sandbox with the secrets option — a map of environment variable → secret name:
import { Sandbox } from "@superserve/sdk"

const sandbox = await Sandbox.create({
  name: "research-agent",
  secrets: {
    ANTHROPIC_API_KEY: "anthropic-prod",
    GITHUB_TOKEN: "github-token",
  },
})
Inside the sandbox, ANTHROPIC_API_KEY is set like any environment variable — but its value is a stand-in token, not your real key. Code in the sandbox uses it normally:
# Inside the sandbox — the code has no idea it's not the real key.
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{ ... }'
The request leaves the sandbox, the platform swaps the stand-in token for your real credential on the way to api.anthropic.com, and Anthropic sees the real key. If code in the sandbox prints $ANTHROPIC_API_KEY, dumps its environment, or leaks it some other way, all it has is the stand-in token — worthless anywhere except authenticated requests to the secret’s hosts.

Attach and detach on a running sandbox

You can also change a sandbox’s bindings after it exists — useful when an agent session is already up and needs a new credential, or when you want to remove one. Works on active and paused sandboxes.
// Add a binding.
await sandbox.attachSecret("ANTHROPIC_API_KEY", "anthropic-prod")

// Remove it later.
await sandbox.detachSecret("ANTHROPIC_API_KEY")
A binding takes effect for processes started after the call — a process already running keeps the environment it started with until it re-execs. Detaching cuts the credential’s access for new processes immediately and for an already-running process within about a minute. A paused sandbox applies either change when it resumes.

Inspecting bindings

A sandbox reports the secrets bound to it:
for (const b of sandbox.secrets ?? []) {
  console.log(b.envKey, "", b.secretName, b.revoked ? "(revoked)" : "")
}
revoked flips to true when the underlying secret has been deleted — the env var still holds the (now-inert) stand-in token, and any request that relies on it fails rather than falling back to a stale credential. To go the other way — from a secret to the sandboxes using it — see getSandboxes().
secrets and envVars both set environment variables, so a given name can come from one or the other — not both. Reusing the same name across them is rejected.

Combine with network rules

Secrets pair naturally with network rules: attach the credential and restrict the sandbox to only the hosts it should reach. A sandbox that can authenticate to api.anthropic.com and reach nothing else is hard to misuse.
const sandbox = await Sandbox.create({
  name: "locked-down",
  secrets: { ANTHROPIC_API_KEY: "anthropic-prod" },
  network: {
    allowOut: ["api.anthropic.com"],
    denyOut: ["0.0.0.0/0"],
  },
})