Documentation

vaaya / docs / reference

Compute & sandboxes

Isolated boxes for running code your agent wrote or can’t trust: Modal for cheap one-off runs (and the only GPU path), plus five stateful session sandboxes — E2B, Daytona, Vercel, Runloop, Fly — where installs, files, and process state persist across commands. One rule above all: every box you open must be torn down — an abandoned sandbox keeps billing until it stops.

Reach for compute only when you actually need to *run code* — untrusted or AI-generated code, data-processing scripts, test suites in isolation, temporary batch jobs, or validating generated code before showing it to a user. If you just need data, a search or scraping call is cheaper and faster; if you need to click and type in a real browser, that’s the Browser service.

When to use which

NeedCallPricePick when
Quick one-off runmodal/sandbox-createsandbox-execsandbox-terminate~3¢ + 1¢ + 1¢The default. A single execute-and-read, ≤300s.
GPU run (inference / CUDA)modal/sandbox-create with gpu~2–21¢ by tierThe only GPU path.
Stateful multi-step sessione2b/create_session~5¢/vCPU-hrThe default stateful box — Firecracker microVM isolation for untrusted code.
Stateful, fastest cold startdaytona/create_session~5¢/vCPU-hr~30–90ms starts; Docker isolation, so trusted code only.
Stateful, microVM isolationvercel/create_session~5¢/vCPU-hrFirecracker microVM; US-East only, sessions ≤5h.
Coding-agent devboxrunloop/create_session~5¢/vCPU-hrPersistent devbox with snapshot/resume.
Long-running, $0 when idlefly/create_session7¢/CPU-hr + 4.375¢/GB-hrState must survive and idle time should cost nothing.

The routing rule: default to Modal for a one-off execute-and-read — it’s per-call, cheap, and ephemeral. Escalate to a stateful session when the work is multi-step (installs + iteration), needs filesystem state to carry between commands, or runs longer than Modal’s 300-second lifetime.

Price
≤5¢ CPU (bills the actual price, ~3¢) · GPU by tier
Latency
slow — container startup; GPU images slower still
Lifetime
up to 300s by default

Creates a sandboxed environment and returns its sandbox_id. All params are optional: image (defaults to a slim Debian container), command (an optional entrypoint run at startup), timeout (max lifetime in seconds, default 300), and gpu (one of T4, L4, A10G, A100, H100 — omit for CPU).

GPU sandboxes

Pass gpu to get a GPU-backed box — this is the path for model inference and CUDA workloads. GPU creates bill the actual price under tiered caps; set max_cost_cents to the tier’s cap so a price move can’t surprise you.

TierTypicalCap (set max_cost_cents here)
T4≈2–5¢25¢
L430¢
A10G40¢
A100≈21¢150¢
H100250¢
curl -X POST https://vaaya.ai/api/run/modal/sandbox-create \
  -H "Authorization: Bearer $VAAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image": "python:3.12", "gpu": "T4", "max_cost_cents": 25}'

Gotchas

  • The sandbox has a hard timeout (default 300s). If your code takes longer, raise timeout — or it gets killed mid-run.
  • Each create costs ~3¢ even if the startup command fails instantly — validate your command before sending.
  • CPU is the default; only pass gpu when the workload actually needs one.
Price
Latency
depends on the command
Returns
{ stdout, stderr, returncode }

Runs a command inside a sandbox created with sandbox-create and returns its output — this is how you actually *use* a sandbox. sandbox_id and command are required; timeout (seconds) is optional. command may be a shell string (run via sh -c, so pipes, quotes, and && work) or an argv array like ["python", "-c", "print(1)"] (no shell).

# 1) create the box — returns only { "sandbox_id": "sb-..." }
curl -X POST https://vaaya.ai/api/run/modal/sandbox-create \
  -H "Authorization: Bearer $VAAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image": "python:3.12"}'

# 2) run code and read the output
curl -X POST https://vaaya.ai/api/run/modal/sandbox-exec \
  -H "Authorization: Bearer $VAAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sandbox_id": "sb-abc123", "command": "echo hello && python --version"}'
# → { "stdout": "hello\nPython 3.12.x\n", "stderr": "", "returncode": 0 }

# 3) tear down
curl -X POST https://vaaya.ai/api/run/modal/sandbox-terminate \
  -H "Authorization: Bearer $VAAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sandbox_id": "sb-abc123"}'
  • The sandbox must still be running (within its timeout window) — exec against a terminated or expired sandbox fails. Create → exec → terminate.
Price
1¢ each
Latency
fast

sandbox-status checks whether a sandbox is running, finished, or failed (sandbox_id is the only param). sandbox-terminate stops it and frees its resources.

  • Status costs 1¢ per check — don’t poll in a tight loop. Check once after a reasonable delay.
  • Always terminate when done — abandoned sandboxes keep burning balance until they hit their timeout.

Stateful sessions

Price
~5¢/vCPU-hr metered (Fly: 7¢/CPU-hr + 4.375¢/GB-hr, $0 idle)
Lifecycle
create_sessionsession (repeat) → close
State
filesystem + installs persist across commands

Five providers share one lifecycle. Opening a box is a normal HTTP call to POST /api/run/{provider}/create_session — it returns { session_id } immediately and reserves a small credit hold, released in full when you close. Optional params: template and envs. The box then stays alive — and metered — until you close it or your balance runs out, at which point it is force-closed.

curl -X POST https://vaaya.ai/api/run/e2b/create_session \
  -H "Authorization: Bearer $VAAYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template": "base"}'
# → { "session_id": "..." }

Running commands in the box and closing it happen through the session and close tools on the MCP surface — connect with the same key. session takes session_id plus either command (a shell string) or code with an optional language (python, the default, javascript, or bash), and returns stdout/stderr/exit code. The same box is reused across calls, so installs and files persist.

# run — repeat as needed; the SAME box is reused between calls
session({ "session_id": "...", "command": "pip install pandas && python analysis.py" })

# close — required; stops the meter and settles. Idempotent.
close({ "session_id": "..." })

Which stateful sandbox

ProviderPriceIsolationPick when
e2b~5¢/vCPU-hrFirecracker microVMThe default — untrusted or hostile code.
daytona~5¢/vCPU-hrDockerCold-start latency matters (~30–90ms) and the code is trusted.
vercel~5¢/vCPU-hrFirecracker microVMStrong isolation; US-East only, sessions ≤5h.
runloop~5¢/vCPU-hrdevboxA persistent coding-agent devbox with snapshot/resume.
fly7¢/CPU-hr + 4.375¢/GB-hr · $0 idlespriteLong-running work where state must survive and idle is free.

e2b

The default stateful box: Firecracker microVM isolation, so it’s the right home for untrusted or hostile code. Metered by uptime at ~5¢/vCPU-hr.

daytona

The fastest cold start (~30–90ms). template picks the language: python (default), typescript, or javascript. Daytona has a stateful interpreter — variables persist across code calls, not just the filesystem.

  • Isolation is Docker, not a microVM — prefer E2B for hostile untrusted code.

vercel

A Firecracker microVM with strong isolation, metered by wall-clock uptime (~5¢/vCPU-hr) whether the box is busy or idle. US-East only, sessions capped at 5 hours.

  • No stateful interpreter — code runs as a one-shot subprocess, so in-memory variables do not persist between code calls. Use the filesystem or shell commands to carry state.
  • python3 availability depends on the runtime — prefer a shell command for non-JS work unless you know the box has the interpreter.

runloop

A persistent coding-agent devbox with snapshot/resume; slower cold start than Daytona. Metered by uptime at ~5¢/vCPU-hr.

  • No stateful interpreter — code runs via python3 -c / node -e, so language-level variable state does not persist across code calls (filesystem and installed packages do).

fly

A persistent sprite: filesystem, installed packages, and process state survive across commands, and it is $0 when idle — you pay only CPU-hr + GB-hr while it’s actively running (7¢/CPU-hr + 4.375¢/GB-hr at the default 1 CPU / 1 GB size).

  • No auto-expire. If you forget to close, nothing self-stops the box — closing it is on you.
  • envs is not applied at create on Fly today — export env vars inside a session command instead.
  • code runs one-shot (python3 -c / node -e): in-memory variables don’t persist across code calls, though filesystem and installed packages do.

To stage inputs into a box or keep its outputs, pair sessions with Files & storage — upload once, download inside the sandbox from the file’s URL.