View source on GitHub
RUNNING, then talks directly to the sandbox’s
agent-server REST API to run shell commands.
No conversation is created — useful when you want a managed remote workspace
to drive yourself (e.g. for tooling, batch jobs, or programmatic agents).
Two versions are provided:
sandbox_demo_brief.py— ~25 lines, one-numbered-step-per-block, minimal error handling. Best for quickly understanding the API shape.sandbox_demo.py— same flow but split into amain()function with docstrings and type hints, more in line with the rest of the repo.
Want to go further?clone-and-attachbuilds on this example: it clones a repo and runs its.openhands/setup.shin the sandbox, then attaches a conversation to the prepared sandbox.
APIs Used
1. Cloud App Server — manages the sandbox lifecycle
- Base URL:
https://app.all-hands.dev - Auth header:
X-Session-API-Key: <OH_API_KEY> - Endpoints:
POST /api/v1/sandboxes— start a sandbox (optional?sandbox_spec_id=…)GET /api/v1/sandboxes?id=<id>— batch-get sandboxes by id (returnsSandboxInfowithstatus,session_api_key,exposed_urls, …)
2. Agent Server — runs inside the sandbox
- Base URL: the entry in
sandbox.exposed_urlswithname == "AGENT_SERVER". Inside the container the agent server listens on port 60000 (you’ll see that in the sampleps -efoutput below and in theportfield of theexposed_urlsentry); it is reverse-proxied to the public HTTPS URL, so you always talk to it overhttps://…(port 443) — never the internal port. - Auth header:
X-Session-API-Key: <session_api_key>returned by the sandbox-create call (different from your Cloud API key) - All routes are under
/api/.... This example uses:POST /api/bash/execute_bash_command— run a bash command and wait for its result; body{ "command": "...", "timeout": 30, "cwd": "..." }, response includesstdout,stderr,exit_code
Full Agent Server schema is available at<agent_server_url>/openapi.jsononce the sandbox isRUNNING.
What it prints
/workspace is the sandbox’s working tree. The agent-server is the binary
target built from the
software-agent-sdk Dockerfile.
You’ll see two processes: a uvicorn parent and a worker.
Run it
sandbox_demo.py also takes flags / env vars so you can reuse it as-is:
Neither script deletes the sandbox at the end so you can poke at it.
Clean up with the
DELETE endpoint — note the sandbox id goes in both the
path and a required sandbox_id query parameter:
Notes
- A freshly created sandbox starts in
STARTING;session_api_keyandexposed_urlsarenulluntil it becomesRUNNING. Polling every few seconds is sufficient. - The Cloud API has no single-sandbox
GET /sandboxes/{id}— use the batch-get endpointGET /sandboxes?id=<id>and read the first item. - To pick a specific runtime image, pass
?sandbox_spec_id=<id>to thePOST /api/v1/sandboxescall. List available specs withGET /api/v1/sandbox-specs/search.
Related
clone-and-attach
Clone a repo and attach a conversation
archive-sandbox
Delete conversations and release PVCs
OpenHands API Reference
Full API documentation

