Official Base Image and the Server SDK
Status: v2 (reviewed; see fine-grained-capabilities-review.md) — reviewed together with the fine-grained capability design in fine-grained-capabilities-review.md. Product requirement: all template builds should be based on the Alibaba Cloud Agent Sandbox (FC Agent Sandbox) base image.
Update. The Python client no longer builds images:
Image,DockerBuilder,Sandbox.deployandagent_sandbox.api.base_imagewere removed. The base-image contract in section 3, the lint and the Dockerfile scaffold are owned by theabxCLI (abx template init|build|deploy). Sections 4, 5, 7 and 8 describe what remains in this repository.
1. What the base image is (evidence)
Sources: repository research (.agents/evidence/research/2026-09-04-fc-claude-code-image-inspection.md,
...-fc-sandbox-official-docs.md), and the official doc page
Build a custom image template
(fetched while writing this design; it currently cites tag v0.0.49, older notes cite v0.0.44).
| Fact | Value | Source |
|---|---|---|
| Registry/name pattern | fc-e2b-registry.<region>.cr.aliyuncs.com/runtime/<name>:<tag>; names: base, code-interpreter-v1, browser, claude-code, ... |
official doc |
| Region rule | image region must equal the sandbox region; public pull, no credentials | official doc |
| Official image as template source | used as-is, no build step (build_config omitted); any other image is auto-processed: copy (re-push) + envdInject |
official doc |
| Process model | ENTRYPOINT ["/.fce2b/entrypoint"] = PID 1 gateway + process manager; supervises envd (49983) and, if enabled, sandbox-code-interpreter (49999); gateway on 5000 |
image inspection |
| Default user / cwd | user, /home/user (documented for the claude-code image; docs say "do not assume the same default user for every image") |
official doc + inspection |
| Hard requirements for custom images | linux/amd64; /bin/bash at that exact path; writable standard /etc/passwd and /etc/group; no ACR image acceleration |
official doc |
| Conditional | python3 on PATH (Python run_code), node (JS run_code), git/ssh/CA certs as needed |
official doc |
| Services started by the template | no template-level startCmd in the docs; services are started with background commands. The platform API accepts start_command / ready_command (used by our create_official_template) |
docs + repo |
| Python | 3.13 on Ubuntu 25.04 for claude-code (PEP 668 "externally managed"), pip config pointing at an Alibaba mirror |
image inspection |
2. Decision
Server-SDK design work is warranted. Template builds default to the official base image through scaffolding, a documented contract, helpers and linting — not by silently changing the behaviour of existing APIs.
Reasoning:
- Correctness, not taste.
create_official_template(envd_inject=False)is our default path: it only yields a working sandbox if the image already contains envd. A template builtFROM ubuntu:22.04has no envd unless the platform builder injects it. Basing on the official image makes the default path valid and lets the platform skip thecopy+envdInjectbuilder function (faster, cheaper, fewer moving parts, envd/gateway versions are the platform's tested ones). - The server SDK has to live somewhere. Layering
agent-sandbox-serveronto the official image gives a well-defined target: known PID 1, known user/HOME (defaultABX_SERVER_BASE_DIR=/home/usermatches), known ports (49983/5000 taken -> 9000/9001 free). - Do not break unconfigured callers. The CLI still accepts any Dockerfile. A non-official base is an advisory warning, not an error.
3. The contract (what a Dockerfile layered on the base image can rely on)
Documented in server-api.md and enforced by the CLI's template lint:
| Item | Contract |
|---|---|
| FROM | fc-e2b-registry.<region>.cr.aliyuncs.com/runtime/base:<tag> |
| Do not override | ENTRYPOINT (gateway PID 1); do not depend on CMD for starting services |
| Server start | platform start_cmd = "agent-sandbox-server serve --port 9000", ready_cmd = "agent-sandbox-server healthcheck --port 9000"; fallback Sandbox.start_server() (envd background command + readiness poll) |
| Ports | 49983 envd, 5000 gateway, 49999 code interpreter (reserved); 9000 server HTTP, 9001 PTY WebSocket |
| User | runs as user (via envd/start cmd); files under /home/user; app code in /home/user/app (legacy /app still works if ABX_SERVER_BASE_DIR includes it) |
| Python | the scaffold guards command -v python3; installs with PIP_BREAK_SYSTEM_PACKAGES=1 (PEP 668) |
| SDK injection | COPY *.whl /tmp/ + pip install with a PyPI fallback pinned to the client's version (lockstep releases) |
| Policy | COPY server-policy.json /etc/agent-sandbox/server-policy.json (auto-loaded, see fine-grained doc 4) |
| Platform | linux/amd64, /bin/bash, writable /etc/passwd, /etc/group (already satisfied by the base) |
4. What gets implemented
server-sdk
agent-sandbox-serverconsole script andpython -m agent_sandbox.server(__main__.py):serve(default;--host --port --commands <file-or-module> --policy <json> --preset <name> --base-dir),healthcheck(HTTP GET/health, exit code 0/1, forHEALTHCHECKandready_cmd),check-config(validate + lint a policy, print effective endpoint table),version.--commandsimports a user module so itsregistry.command(...)/table.route(...)side effects register (whatcommands.pydid withstart()), then serves — a template needs no bespokecommands.pyboilerplate.agent_sandbox.server.contractconstants (ports, paths, env-var names) shared by CLI/server.- Policy auto-load (
/etc/agent-sandbox/server-policy.json). pyproject.toml:[project.scripts] agent-sandbox-server = "agent_sandbox.server.__main__:main".
client-sdk
Sandbox.start_server(...)(remote start + readiness) and theSandbox.serverclient.SandboxTemplate.server(structurally validated policy block). A declarativeSandboxTemplate.base_imagefield was considered and not added: the Dockerfile is the single source of truth for the base, and the lint (B001) reads it from there.
Not implemented (justified)
- No bundling of the server wheel in a custom base image: the wheel injection already covers the "installed from PyPI" and "dev checkout" cases and keeps lockstep versions.
- No second HTTP gateway/proxy: the platform gateway on 5000 already routes
{port}-{sandbox}hosts.
5. CLI-side changes (recorded in cli-followups.md)
Node scaffold abx template init (FROM official base, scaffold per section 3); deploy path
(wheel injection, envd_inject auto-choice, start_cmd/ready_cmd);
template.yaml server: compile; AI template-guide prompt (must start FROM the official base,
never override ENTRYPOINT, use agent-sandbox-server serve).
6. Open questions (cannot be settled from repo/docs)
- Does the gateway honour a Dockerfile
CMDor only the platformstart_command? (we avoid CMD.) - Is
/home/user+ useruserguaranteed for the plainbaseimage (documented forclaude-code)? - Exact default tag: docs say
v0.0.49; we exposeABX_BASE_IMAGE_TAGand a constant so it is one line to bump. - Does the platform tolerate an already-envd-containing non-official image with
envdInjecton?
7. Changes after review (Draft v1 -> v2)
- The claim that the gateway forwards
Authorizationis unverified (OQ-3 in the review log): the server accepts bothX-Access-TokenandAuthorization: Bearer, so either gateway behaviour works. healthcheckuses onlyurllib.requestagainst127.0.0.1(2 s timeout, exit code 0/1) so it can serve as a DockerHEALTHCHECK/ready_cmdwithout heavy imports.- Console script name
agent-sandbox-serververified not to clash withabx.
8. Implementation status
Implemented here: agent-sandbox-server console script (serve, healthcheck,
check-config, version), agent_sandbox.server.contract, and the client's Sandbox.server /
server_at() / start_server(). Tests: tests/test_api/server_e2e/test_sandbox_server_helpers.py,
server-sdk/tests/test_server/test_cli_main.py. The base-image helpers, the lint (B001-B005) and the scaffold
moved to the CLI. Exact CLI-side changes: cli-followups.md.