Examples

Each example starts with a concrete task against a live aiod daemon, exercises one sandbox capability, and checks the result. The code is runnable as written.

Conventions

BASE_URL and the API key follow Quick Start. Every JSON response uses the envelope {"success": bool, "message": str, "data": ..., "hint": null|str}; validation failures answer 422 with a top-level errors list. See Error Handling.

Every example is written twice — a v2 form and a v1 form — and the API Preference switch in the sidebar picks which one you see. The v2 form calls the routes through the small Aio helper below; the v1 form uses the 1.x SDK (agent_sandbox.Sandbox in Python, SandboxClient from @agent-infra/sandbox in TypeScript), and falls back to the same helper on the /v1 route for the few calls the SDK has no method for. Wherever the helper is used, the example starts with sb = Aio(BASE_URL).

Python
TypeScript
import httpx


class Aio:
    """Envelope-aware client for the v2 routes; raises on success=false."""

    def __init__(self, base_url, api_key=None, timeout=120):
        headers = {"x-api-key": api_key} if api_key else {}
        self.http = httpx.Client(base_url=base_url, headers=headers, timeout=timeout)

    def call(self, method, route, **kw):
        body = self.http.request(method, route, **kw).json()
        if not body.get("success"):
            raise RuntimeError(f"{method} {route}: {body.get('message')}")
        return body["data"]

    def get(self, route, **params):
        return self.call("GET", route, params=params)

    def post(self, route, **body):
        return self.call("POST", route, json=body)

    def delete(self, route, **params):
        return self.call("DELETE", route, params=params)

sb.post("/v2/commands", command="wc -l /tmp/x") posts a JSON body; sb.get/sb.delete take query params the same way — the first positional argument is route, so sb.post("/v2/fs/read", path="/tmp/x") works directly. Binary routes (download, screenshot) read sb.http.get(...) / fetch directly, bypassing the envelope check.

First call

Confirm the daemon is up and read its capabilities:

curl "$BASE_URL/health"
curl "$BASE_URL/v2/sandbox" | python3 -m json.tool
curl "$BASE_URL/v1/capabilities" | python3 -m json.tool

A missing capability turns its own routes into 503; the daemon still starts.

All examples

ExampleShowsNeeds
Agent Calls the SandboxWrite a file, run a command, execute Python, read the resultfiles, exec, code_interpreter
MCPThe same task through one JSON-RPC endpoint, and how tool errors lookexec, files, code_interpreter
Browser (CDP)Playwright and Puppeteer against the sandbox's Chromiumbrowser
Browser UseBuild a page in the sandbox, then fill it, click it, and check the resultbrowser, files, exec
Interactive TerminalA live PTY over WebSocket from a minimal clientexec with pty
Code ExecutionA data-analysis session: CSV in, pandas, chart back as PNGcode_interpreter
File OperationsScaffold a project, search and edit it, watch it, and the error contractfiles
Computer UseNavigate Chromium and follow a link through the accessibility treecomputer

One task, three ways

The four-step task on Agent Calls the Sandbox exists in three forms: the v2 routes, the 1.x SDK, and one JSON-RPC endpoint on MCP. The steps, the file names and the result 27 are the same in all three; only the transport changes, so an agent can use whichever protocol its framework already speaks.

SDK

Both SDKs target the v1 routes (Python agent-sandbox, TypeScript @agent-infra/sandbox):

Python
TypeScript
from agent_sandbox import Sandbox

client = Sandbox(base_url="http://127.0.0.1:18091")
# headers={"x-api-key": "<key>"} when AIO_API_KEY is set
client.bash.exec(command="uname -a")

Which calls work, which need a raw HTTP call, and which routes are gone: 1.x SDK compatibility. /v2 is called through the HTTP API; see the API Reference.