Engine HTTP API (`abx-engine/1`)
在 GitHub 查看 ↗Engine HTTP API (abx-engine/1)
The engine is a local process that hosts the provider layer once, so the CLI and every SDK (Python today; Node, Go and Java later) call the same provider code. It is the Node.js CLI running abx provider engine serve. An SDK that finds no engine starts one and talks to it over loopback HTTP, SSE and WebSocket. Nothing in this API needs gRPC or a code generator: any language with an HTTP client can use it.
Official site: https://www.agent-sandbox.com. Registry website: https://registry.agent-sandbox.com. The CLI installs catalog providers from alibaba-agent-sandbox/awesome-providers//<id>. The Python SDK installer fetches https://registry.agent-sandbox.cn/providers/index.json.
Start, find and stop
abx provider engine serve [--idle-timeout 900] [--port 0] # foreground; SDKs start it detached
abx provider engine status # exit 1 when none is running
abx provider engine stop
A running engine writes ~/.abx/engine.json (mode 0600) and holds ~/.abx/engine.lock, so concurrent starts leave one engine:
{ "protocol": "abx-engine/1", "pid": 4242, "host": "127.0.0.1", "port": 51234, "token": "…", "version": "0.3.0", "started_at": "2026-10-14T12:00:00Z" }
- The engine listens on
127.0.0.1only. A request whoseHostis not loopback, or that carries anOriginheader (a browser page), is refused. - Every request sends
Authorization: Bearer <token>. WebSocket upgrades use the same header. - It exits after
--idle-timeoutseconds without requests (default 900). Sessions idle for 600 s are closed. A client that gets a connection error, or a 401 after a restart, readsengine.jsonagain and starts a new engine. - The log is
~/.abx/engine.log. An SDK launches the CLI named byABX_BIN(a command line) orabxonPATH.
The connection
The engine keeps no account of its own. Each request carries the connection the client resolved (its own config, env and .env layers):
{ "provider": "e2b", "provider_options": { "base_url": "…" }, "api_key": "…", "api_url": "…", "domain": "…", "access_key_id": "…", "access_key_secret": "…" }
Send it as the header X-Abx-Connection (base64url of the JSON, no padding) or, on POST bodies, as the same fields. Sessions are keyed by a fingerprint of the connection plus the sandbox id, so two accounts never share a session. A session that the backend no longer knows is rebuilt through connect once.
Routes
All paths start with /v1. Bodies are JSON unless noted. :id is the provider's sandbox id.
| Method and path | Purpose |
|---|---|
GET /health |
{protocol, version, pid, uptime_s, sessions} |
POST /shutdown |
stop the engine |
GET /providers |
installed providers: id, name, version, kind, trust, features, error |
POST /sandboxes |
create (template, timeout, envs, metadata, cpu, memory, disk, gpu, secure, …); 201 with the sandbox record |
GET /sandboxes?status=&limit=&offset= |
list: {sandboxes: […]} |
POST /sandboxes/:id/connect |
attach to an existing sandbox |
GET /sandboxes/:id · DELETE /sandboxes/:id |
info · kill |
GET /sandboxes/:id/running |
{running} |
POST /sandboxes/:id/timeout |
{timeout} seconds |
POST /sandboxes/:id/pause · /resume |
pause · resume |
GET /sandboxes/:id/ports/:port/url |
{url, headers} for a port |
POST /sandboxes/:id/commands/run |
run to completion: {stdout, stderr, exit_code} |
POST /sandboxes/:id/commands/stream |
SSE: stdout/stderr/exit events then end (body: cmd or cmd + args, env, cwd, user, timeout) |
GET /sandboxes/:id/processes |
running processes |
POST /sandboxes/:id/processes/:pid/signal · /stdin · DELETE …/:pid |
signal · write stdin · kill |
GET / PUT /sandboxes/:id/files/content?path= |
read or write raw bytes (application/octet-stream) |
GET /sandboxes/:id/files/list · /info · /exists |
directory listing, stat, existence (path, depth) |
POST /sandboxes/:id/files/mkdir · /move · DELETE …/files |
make directory · rename · remove |
GET /sandboxes/:id/files/watch |
SSE of file changes |
POST /sandboxes/:id/code/run |
run code: code, language, context_id, envs, timeout |
…/code/contexts |
create, list, restart, delete code contexts |
GET /sandboxes/:id/terminal?cols=&rows=&shell= |
WebSocket PTY: binary frames are bytes in and out; text frames {"type":"resize","cols":…,"rows":…} resize |
A feature the provider did not declare answers 501, the same condition the CLI reports as E8004.
Errors
{ "error": { "type": "SandboxNotFoundError", "code": "E2009", "message": "…", "suggestion": "…", "docs_url": "…" } }
type is the SDK exception class, so a client rebuilds the same exception. Status codes: 404 not found, 401 bad token or provider authentication, 501 capability missing, 400 bad value or configuration, 500 anything else. Inside an SSE stream the same object arrives as an error event.
Which kinds the engine runs
The engine hosts builtin (alicloud-express), rest (e2b-rest/1), exec (EPP/1 child processes of third-party plugins) and node (in-process node/1 modules: opensandbox, e2b, cubesandbox, alicloud-container) providers. A client never sees the difference.
The Python gRPC engine in agent_sandbox.engine is superseded by this one for catalog providers. The built-in Python alicloud-express path still has its own copy.