Docs

API Reference

Complete API reference for Alien Sandbox bindings.

Every method below is reached through the binding, not the resource declaration. The declaration provisions the parent; these create and drive sessions at runtime.

Where a platform lacks a capability the call returns a typed AlienError naming both the platform and the capability. It never no-ops and never returns a null-ish success — you will know, and the error will tell you what to change.

capabilities()

const caps: string[] = await box.capabilities()
if (caps.includes("files")) { /* ... */ }

Returns what this platform's backend actually supports — a list of capability names in TypeScript, a struct of booleans in Rust. Branch on it rather than catching errors, when you have a sensible fallback.

CapabilityAWSAzureGCPKubernetesLocal
filesyesnoyesyesyes
reconnectyesyesnoyesyes
previewyesnononoyes
suspendResumeyesnononono
snapshotnonononono
egressDenyyesnoyesyesyes
domainEgressRulesnonononono
enforcedLimitsyesnonoyesyes
processLimitnonononoyes
sessionLifetimeyesnonoyesno
supervisorPidNamespacenonononono

Sessions

create / getOrCreate / get / list

const session = await box.create({ sessionId: "turn-1" })

create takes a session id and, optionally, a tenant key. It takes no image, cpu, memory or port arguments — those come from your alien.Sandbox declaration. An application cannot raise its own ceilings by asking, which is the point.

get requires reconnect. On GCP it returns the typed error rather than null: a null reads as "the session expired", when the truth is that GCP cannot address a session from another instance at all. getOrCreate is the one call that degrades instead — where reconnect is unavailable it creates a fresh session.

list enumerates this sandbox's sessions on Kubernetes and Local only. AWS, Azure and GCP raise rather than enumerate — none of their APIs can list sessions scoped to one sandbox. Reach a session whose id you hold with get.

terminate

await box.terminate(session.sessionId)

Terminating a session that is already gone succeeds on Azure and Kubernetes, because terminate is the cleanup path and a cleanup that fails on an absent session turns teardown into a retry loop. AWS and Local raise instead — they check the session exists before acting — so treat a not-found error from terminate as success if you are writing a teardown that must converge.

runCommand

for await (const frame of sandbox.runCommand(sessionId, ["python3", "main.py"], {
  deadlineMs: 30_000,
})) {
  if (frame.kind === "stdout") process.stdout.write(frame.data)
  if (frame.kind === "exit") console.log(frame.exitCode)
}

Streams output frames, then exactly one terminal frame.

  • deadline is required. A request without one is rejected rather than defaulted — a default deadline is a hang waiting for a slow day.
  • seq is monotonic across stdout and stderr together on AWS, Kubernetes and GCP, so you can interleave them in the order they were produced. Azure and Local return an already-buffered response and number it stdout-then-stderr, which does not reconstruct production order.
  • Exactly one terminal exit frame, always last. Frames are stdout, stderr and exit — a failure is a thrown error in TypeScript and a stream Err in Rust, not a frame. A stream that ends without an exit is a transport failure, not a clean exit 0.
  • Output carries backpressure on AWS, Kubernetes and GCP: a consumer that stops reading stops the sandbox's writer rather than filling memory. Azure and Local buffer the whole response first.

Files

await box.writeFiles(sessionId, { "/work/main.py": bytes })
const out = await box.readFile(sessionId, "/work/out.txt")
await box.mkdir(sessionId, "/work/build")

Requires files, which Alien's Azure binding does not implement.

Paths may not escape the session root, and the strength of that varies. On AWS and Kubernetes the agent opens through openat2, so the kernel resolves and opens in one call and refuses .., absolute paths and symlinks rather than following them — code inside the sandbox cannot race a check it never gets to see. Transfers there are bounded at 32 MiB. Local rewrites paths against the session root and rejects .. without resolving symlinks; GCP checks for .. and passes the path through unchanged, and neither applies a size bound.

preview

Rust only. The TypeScript binding exposes no preview method, so capabilities() there never reports it.

let capability = sandbox.preview(session_id, 8080).await?;
ParameterTypeRequiredDescription
sessionIdstringYesThe session to expose.
portnumberYesMust be listed in previewPorts on the resource declaration.

Returns a typed capability, not a URL string. AWS needs auth headers and a port header. A bare URL cannot carry those, and handing you one would push the auth onto you to get wrong. Local returns an unauthenticated capability with no headers and no expiry.

FieldTypeDescription
endpointstringThe address to send requests to.
headersRecord<string, string>Auth headers that must accompany every request.
allowedPortsnumber[]Ports this capability covers.
expiresInSecondsnumberLifetime of the capability.

A port not declared in previewPorts cannot be exposed at runtime, so an application cannot widen its own ingress.

Requires preview, which today means AWS and Local. Kubernetes returns the typed error until the session-scoped ingress gateway exists, GCP has no mechanism, and Azure's is not implemented yet — the platform has a per-port URL closed to anonymous traffic, and the binding does not use it.

suspend / resume / snapshot

await box.suspend(sessionId)
await box.resume(sessionId)

snapshot is Rust-only and unavailable on every platform; TypeScript exposes no method for it.

suspend/resume need suspendResume, which today is AWS only. snapshot is not available on any platform yet: AWS has no user-callable session snapshot, and Azure's full-VM capture is not wired into the binding.

Unsupported Surface

The surface is close enough to Vercel's that porting is small. Two differences will show up when you do:

  1. snapshot() is capability-gated, not universal, and no platform advertises it today. AWS has build-time image capture and suspend/resume but no user-callable session snapshot; Azure captures full VM state and the binding does not use it yet. Both return the typed error.
  2. preview() returns a capability, not a URL — see above.

On this page