[ GUIDE / AGENTS ]
Running coding agents in a sandbox
Both CLIs (claude, opencode) are pre-installed in every sandbox; outbound
network is allowed. You can drive them headlessly through the tasks API, or
drop into a shell.
Agents with a lifecycle
A task is more than firing opencode inline: you submit a prompt, stream
progress (SSE), and capture a durable result.
API=http://127.0.0.1:9090
# run a coding agent headlessly — it works in ~/workspace/app
curl -s -XPOST $API/v1/sandboxes/$ID/tasks -H 'content-type: application/json' -d '{
"prompt":"create a Vite app that shows a todo list and run it on port 3000",
"agent":"opencode"
}'
# -> {"id":"<taskId>","status":"running","events_url":"/v1/sandboxes/<id>/tasks/<taskId>/events"}
# stream the agent's progress (Server-Sent Events)
curl -N $API/v1/sandboxes/$ID/tasks/<taskId>/events
# fetch the durable task result
curl -s $API/v1/sandboxes/$ID/tasks/<taskId>
OpenCode runs on its free plan out of the box; pass your own provider key via
env to use your account.
Inside the sandbox, tasks are executed by runtimed, the in-sandbox supervisor
built into the base image (see Architecture).
Injecting provider keys
The clean path is to inject the key at create time so both the tasks API and any shell see it:
# create with the key, then drive OpenCode headlessly via the tasks API:
ID=$(curl -s -XPOST $API/sandbox -H 'content-type: application/json' \
-d '{"ports":[3000],"env":{"ANTHROPIC_API_KEY":"sk-ant-..."}}' \
| sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -s -XPOST $API/v1/sandboxes/$ID/tasks -H 'content-type: application/json' \
-d '{"prompt":"build a Vite todo app and run it on port 3000","agent":"opencode"}'
# stream progress: curl -N $API/v1/sandboxes/$ID/tasks/<taskId>/events
Other ways to supply the key:
# one-off via exec (claude print mode is non-interactive-friendly):
curl -s -XPOST $API/sandbox/$ID/exec -H 'content-type: application/json' \
-d '{"cmd":["bash","-lc","ANTHROPIC_API_KEY=sk-ant-... claude -p \"write hello.py\""]}'
# interactive TUI on the host:
docker exec -it -e ANTHROPIC_API_KEY=sk-ant-... s-$ID bash # then: claude
No agent — just exec
The exec API runs any command non-interactively (no TTY/stdin):
curl -s -XPOST $API/sandbox/$ID/exec -H 'content-type: application/json' \
-d '{"cmd":["bash","-lc","cd ~/workspace && echo hello > index.html && python3 -m http.server 3000"]}'
Writing files directly
You can also write workspace files through the API instead of (or alongside) an agent:
# write a file into the workspace
curl -s -XPUT $API/v1/sandboxes/$ID/files -H 'content-type: application/json' \
-d '{"path":"app/index.html","content":"<h1>hello</h1>","append":false}'
# list / read workspace files
curl -s $API/v1/sandboxes/$ID/files
curl -s "$API/v1/sandboxes/$ID/files/content?path=app/index.html"
See the full endpoint table in the API reference. A complete,
self-contained runbook for driving sandboxd from your own agent is in
AGENTS.md.