E2B
E2B leases isolated sandboxes for code an agent wrote. Here that is /v1/sandbox, with /v1/exec for the one-shot snippet case.
E2B leases an isolated computer, runs code in it, and gives you its filesystem.
/v1/sandbox (19 operations) is the same thing: lease, run, read, write, end.
POST /v1/exec is the short path — one snippet, one answer, no lease to manage.
Start here
Mint a key, run one whole program, and take a lease only when the work has to outlive its own call.
# 1. mint a key — sk- belongs on a server, pk- is safe in a browser
curl -sS -X POST https://api.hanzo.ai/v1/account/keys \
-H "Authorization: Bearer $HANZO_SESSION" \
-H 'Content-Type: application/json' \
-d '{"type":"secret"}'
# 2. run a program in a throwaway sandbox — no lease to manage, nothing to clean up
curl -sS -X POST https://api.hanzo.ai/v1/exec \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"lang":"py","code":"print(1 + 1)"}'
# 3. hold the machine instead — dev attaches the project's disk, exec keeps nothing
curl -sS -X POST https://api.hanzo.ai/v1/sandbox/lease \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"class":"dev","project":"demo","ttlSec":900}'Step 2 answers stdout, stderr, the files the program wrote, and the
session_id of the sandbox it leased for you — send that id with the next run
and it sees the same filesystem, which is the whole of runCode(). Step 3 is
that computer held open under a name you keep: id is the argument run,
read, write and end all take, and workdir is what a relative path in
them resolves against.
Core capabilities
| Capability | What it does | Operations |
|---|---|---|
/v1/sandbox | Leases a real computer with its own filesystem, runs commands in it, reads and writes its files, and ends it. Terminal and screen are WebSockets behind a ticket. | 19 |
/v1/exec | Runs one whole program in a throwaway sandbox across thirteen languages, returns what it printed and what it wrote, and keeps the filesystem when you reuse session_id. | 4 |
/v1/account/keys | Mints, lists and revokes the sk- and pk- keys every call above authenticates with. Minting a class again rotates it in one step. | 3 |
Nouns
| E2B | Hanzo |
|---|---|
Sandbox.create() | POST /v1/sandbox/lease |
| The sandbox id you reconnect with | id in the lease answer, passed in every later body |
sandbox.commands.run(cmd) | POST /v1/sandbox/run |
sandbox.files.write(path, bytes) | POST /v1/sandbox/write, data base64 |
sandbox.files.read(path) | POST /v1/sandbox/read, data base64, or entries for a directory |
sandbox.kill() | POST /v1/sandbox/end |
timeoutMs / timeout | ttlSec on the lease |
| Template | class — exec, dev, desktop or android — a closed set, not an image you build |
| Persistent template data | project on the lease, which names the volume the work persists on |
@e2b/code-interpreter runCode() | POST /v1/exec with lang and code |
| Interactive terminal (PTY) | POST /v1/sandbox/{id}/terminal/ticket, then the socket at /v1/sandbox/{id}/terminal/ws |
| Desktop stream | POST /v1/sandbox/{id}/screen/ticket, then /v1/sandbox/{id}/screen/ws |
| Listing your sandboxes | GET /v1/sandbox |
dev and desktop require a project; exec does not.
The call
E2B:
from e2b import Sandbox # E2B_API_KEY in the environment
with Sandbox.create(timeout=60) as sandbox:
sandbox.files.write("/home/user/main.py", b"print(1 + 1)")
result = sandbox.commands.run("python /home/user/main.py")
print(result.stdout)Hanzo:
# 1. Lease. The answer carries id, class, runtime, status and workdir.
SB=$(curl -sS -X POST https://api.hanzo.ai/v1/sandbox/lease \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"class":"exec","ttlSec":60}' | jq -r .id)
# 2. Write. `data` is base64.
curl -sS -X POST https://api.hanzo.ai/v1/sandbox/write \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"id\":\"$SB\",\"path\":\"main.py\",\"data\":\"$(printf 'print(1 + 1)' | base64 -w0)\"}"
# 3. Run. Answers exitCode, stdout, stderr.
curl -sS -X POST https://api.hanzo.ai/v1/sandbox/run \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"id\":\"$SB\",\"command\":\"python main.py\"}"
# 4. Release it.
curl -sS -X POST https://api.hanzo.ai/v1/sandbox/end \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"id\":\"$SB\"}"If all you want is one snippet, skip the lease entirely:
curl -X POST https://api.hanzo.ai/v1/exec \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"lang":"py","code":"print(1 + 1)"}'A non-zero exit is a 200 carrying a failed program. "The tests failed" and "the sandbox is broken" are different facts and they get different status codes.
Pass a session name to run and the command's output is appended to that
session's live log as it is produced, so a long agentic run can be watched
rather than waited on.
What does not carry
No snapshots and no forking. E2B pauses a sandbox with its full state and
boots new ones from that state. Leasing the same id again resumes a lease that
is still running, which is reattachment, not restoration. When a lease ends,
the sandbox is gone; purge on the end call decides whether the project volume
goes with it.
No template build. E2B builds a template from your Dockerfile and caches it.
Here class picks from a closed set of four, and the image behind the one you
pick is the fleet's. There is no template registry to push to.
No environment variables on the lease. The lease body is class, id,
project, runtime and ttlSec — nothing else. Set variables in the command
you run.
No lifecycle events, metrics or OTel export. E2B emits sandbox lifecycle
webhooks and per-sandbox metrics. GET /v1/sandbox answers from the org's own
store rather than the cluster, so a sandbox whose pod has died still appears with
the status it was last known to have — deliberate, because a lease you are being
charged for should not vanish from the list.
No SSH and no git methods. The terminal is a WebSocket behind a ticket. Git work is a command you run, like any other.
How is this guide?
Composio
Composio gives an agent authenticated tools across third-party apps. Here that is /v1/integrations for the org's credential, /v1/integrations/connectors for a user's own, and /v1/tools for the actions they reach.
Tavily
Tavily searches the live web and pulls pages back as text for agents. Here that is /v1/websearch for the search and /v1/crawl for the page.