How to run the in-sandbox server. Route shapes are in the template server HTTP API. Path and command limits are in File and command controls.
agent_sandbox.server does not select a sandbox provider and does not read --provider. A template's commands.py imports only agent_sandbox.server and calls start(9000) under if __name__ == "__main__".
Which FROM line, whether the Dockerfile may contain CMD or ENTRYPOINT, and the platform start_cmd live in the CLI provider profile (abx-provider.toml [template], or the built-in alicloud-express constant). The HTTP routes do not change with that image. The client SDK does not pick the profile either.
The server has nine capability groups. core stays on (GET /health, GET /capabilities). These start enabled: commands, file_ops, process, terminal, system. These start disabled: dev_tools, browser, agents.
A group is only a name for the endpoints that declare it; the endpoint rule is the one switch. Turn a default group off in the template policy, as a map:
server:
groups:
terminal: false
process: falsecore cannot be turned off. Turn an opt-in group on with a policy list (groups: [dev_tools]), with default_table().enable_group(CapabilityGroup.DEV_TOOLS) in commands.py, or with the environment variable ABX_SERVER_ENABLED_GROUPS=dev_tools. That variable only turns groups on; there is no variable that turns one off. GET /capabilities lists every endpoint with the rule that disabled it.
shell, code_run, and a PTY can run a program that reads any path the process can see. A path rule does not hold for an identity that also has those endpoints. For a template that only moves files, start from the transfer-only or read-only preset. See File and command controls.
The Agents routes stay off until the process is started with ABX_SERVER_ENABLED_GROUPS=agents (or default_table().enable_group(CapabilityGroup.AGENTS) in commands.py, or groups: [agents] in the policy). With the group off, those paths answer 404 with code: endpoint_disabled and the rule that decided (default:opt-in:agents).
Codex and Qwen Code are supported today. Checklist, the local header, and the 404s: Hosted agents — Best practices.
Install only the CLI you are going to call. Installing both Codex and Qwen Code makes the image large.
The server's order is codex, then qwen-code. A request that does not name an adapter uses the first. GET /v1/agents/runtimes?order=asc returns them in that order. The list's default order is desc. default: true marks the one in effect. It does not follow the array index.
npm install -g @openai/codexTo use Qwen Code, send adapter, runtime, or the X-ABX-Adapter header, or set model to qwen-code (aliases qwen and qwencode). A model id such as gpt-5 is passed to the selected CLI. It does not switch the adapter.
Move the default off the first entry:
export ABX_AGENTS_DEFAULT=qwen-codeA JSON file named by ABX_AGENTS_CONFIG does the same with a top-level default or agents.default. claude-code, Cursor, and Qoder stay 404.
groups.agents: true is only the gate for this group. Each Agents route has its own endpoint id, the same way upload and shell do. The default scope is agents:use. This opens session create and nothing else:
from agent_sandbox.server import SandboxServer, ServerPolicy, default_table
policy = ServerPolicy.only("agents_sessions_create").with_options(groups={"agents": True})
server = SandboxServer(route_table=default_table(), policy=policy)The same policy in YAML:
groups:
agents: true
endpoints:
"*":
enabled: false
agents_sessions_create:
enabled: trueThese endpoints do not accept paths or specialised params. A policy that sets either fails to load. The full endpoint id list is in Fine-grained capabilities.
GET /env omits a variable whose name contains TOKEN, SECRET, KEY, PASSWORD, or CREDENTIAL. When a policy is loaded it also omits ABX_SERVER_TOKEN, ABX_SERVER_POLICY, ABX_SERVER_POLICY_FILE, every token_env name, and every name that starts with ABX_SERVER_.
POST /env returns the names it updated ({"updated": [...]}), not the values. It refuses PATH, HOME, USER, SHELL, ABX_SERVER_TOKEN, and every ABX_* name. A policy can refuse more names with params.allow_vars / params.deny_vars on env_get and env_set.
A child process started while a policy with identities is active inherits the environment with those secret names removed. Passing one of them in a shell env object is env_var_not_allowed.
On the Agents routes, MCP header values come back as "***". A vault credential's value, prefix, length, and hash are absent from responses, errors, and events.