This reference describes the ProviderSandbox extension API. Root Sandbox / AsyncSandbox follow the independent standard contract described in E2B migration.
from agent_sandbox import ProviderSandbox as Sandbox@classmethod
async def create(
cls,
template: str = "base",
*,
timeout: int = 300,
request_timeout: float | None = None,
metadata: dict[str, str] | None = None,
envs: dict[str, str] | None = None,
volume_mounts: dict[str, str] | None = None,
cpu: int | None = None,
memory: int | None = None,
disk: int | None = None,
gpu: str | None = None,
secure: bool | None = None,
sandbox_api_key: str | None = None,
sandbox_base_url: str | None = None,
sandbox_domain: str | None = None,
access_key_id: str | None = None,
access_key_secret: str | None = None,
) -> SandboxCreate a new sandbox.
| Parameter | Type | Default | Description |
|---|---|---|---|
template |
str |
"base" |
Sandbox template name |
timeout |
int |
300 |
Sandbox lifetime (TTL) in seconds (1–86400); not an HTTP timeout |
request_timeout |
float |
None |
Per-request HTTP timeout (seconds) for the create call only. When None, uses ABX_HTTP_TIMEOUT / http_timeout. Aligns with the E2B SDK. Raising it does not work around platform-side create stalls. |
metadata |
dict |
None |
Arbitrary metadata key-value pairs |
envs |
dict |
None |
Injected environment variables |
volume_mounts |
dict[str, str] |
None |
Built-in provider only: normalized absolute sandbox path → existing Volume name. Omitted/empty means no mounts. Other providers reject nonempty hints with E8004. See mount requirements and wire schema. |
cpu |
int |
None |
Number of CPU cores |
memory |
int |
None |
Memory in MB |
disk |
int |
None |
Disk in MB |
gpu |
str |
None |
GPU specification (e.g., "A10") |
secure |
bool |
None |
Secure mode (port access requires token) |
sandbox_api_key |
str |
None |
API Key override |
sandbox_base_url |
str |
None |
Platform API URL override |
sandbox_domain |
str |
None |
Domain override |
access_key_id |
str |
None |
Alibaba Cloud AK |
access_key_secret |
str |
None |
Alibaba Cloud SK |
Returns: Sandbox instance
Sync version: Sandbox.create_sync(...)
@classmethod
async def connect(
cls,
sandbox_id: str,
*,
sandbox_api_key: str | None = None,
sandbox_base_url: str | None = None,
sandbox_domain: str | None = None,
access_key_id: str | None = None,
access_key_secret: str | None = None,
) -> SandboxConnect to an existing sandbox.
Returns: Sandbox instance
Sync version: Sandbox.connect_sync(...)
@classmethod
async def list(
cls,
*,
status: SandboxStatus | None = None,
limit: int = 100,
offset: int = 0,
sandbox_api_key: str | None = None,
sandbox_base_url: str | None = None,
access_key_id: str | None = None,
access_key_secret: str | None = None,
) -> list[SandboxInfo]List sandboxes (class method, no instance required).
Returns: list[SandboxInfo]
Sync version: Sandbox.list_sync(...)
@classmethod
async def kill_by_id(
cls,
sandbox_id: str,
*,
sandbox_api_key: str | None = None,
sandbox_base_url: str | None = None,
access_key_id: str | None = None,
access_key_secret: str | None = None,
) -> NoneDestroy a sandbox by ID (class method, no prior connection required).
Sync version: Sandbox.kill_by_id_sync(...)
| Method | Signature | Description | Sync Version |
|---|---|---|---|
kill() |
async def kill() -> None |
Destroy the sandbox and release resources | kill_sync() |
set_timeout() |
async def set_timeout(timeout: int) -> None |
Update timeout duration | set_timeout_sync() |
is_running() |
async def is_running() -> bool |
Check running status (makes an API call) | is_running_sync() |
pause() |
async def pause() -> None |
Pause the sandbox | pause_sync() |
resume() |
async def resume() -> None |
Resume a paused sandbox | resume_sync() |
refresh_info() |
async def refresh_info() -> SandboxInfo |
Refresh sandbox info | refresh_info_sync() |
async def run_code(
self,
code: str,
*,
language: str = "python",
timeout: int = 30,
envs: dict[str, str] | None = None,
on_stdout: Callable[[str], None] | None = None,
on_stderr: Callable[[str], None] | None = None,
on_result: Callable[..., None] | None = None,
) -> CodeResultExecute code via the Code Interpreter. Requires the code capability.
Returns: CodeResult (with text, stdout, stderr, exit_code, execution_time, output_files)
Raises: CapabilityNotSupportedError (E3004) — if the code capability is not enabled
Sync version: run_code_sync()
async def get_terminal(
self,
*,
cols: int = 80,
rows: int = 24,
shell: str = "/bin/bash",
) -> TerminalSessionOpen an interactive PTY terminal session. Logically associated with the terminal capability (no runtime gate).
Returns: TerminalSession (WebSocket connection)
Sync version: get_terminal_sync()
async def list_commands(
self,
*,
server_port: int = 9000,
) -> list[ServerCommand]List the named commands registered on the sandbox's SandboxServer (GET /commands). Commands are registered inside the sandbox with @sandbox.register or the server's CommandRegistry.
Returns: List of ServerCommand (name, description, args)
Raises: ProviderFeatureNotSupportedError (E8004) when the provider has no HTTP data plane; ConnectionError_ when the server is unreachable
Sync version: list_commands_sync()
async def run(
self,
name: str,
/,
*,
server_port: int = 9000,
**kwargs: Any,
) -> AnyCall a named command registered on the sandbox's SandboxServer: sandbox.run("name", x=1) is POST /commands/name with kwargs as the JSON body. This is the only way to call a named command. For a raw shell command use sandbox.commands.run(cmd, ...).
Returns: The command's result value
Raises: CommandNotFoundError (404), ServerAPIError (other server errors), ProviderFeatureNotSupportedError (E8004)
Sync version: run_sync()
| Property | Type | Description |
|---|---|---|
id |
str |
Sandbox ID |
status |
SandboxStatus |
Current status (cached value; call refresh_info() to update) |
url |
str |
envd URL |
info |
SandboxInfo |
Full sandbox info |
capabilities |
frozenset[str] |
Effective capability set |
| Property | Type | Description |
|---|---|---|
commands |
CommandsModule |
Shell command execution |
files |
FilesModule |
Filesystem operations |
network |
NetworkModule |
Port URL computation |
code |
CodeContextModule |
Code Interpreter operations |
async with await Sandbox.create() as sandbox:
... # Automatically calls kill() on exitsandbox.commands # CommandsModule instance| Method | Signature | Description |
|---|---|---|
run() |
async def run(cmd, *, timeout=60, env=None, cwd="", user="", background=False) -> ProcessResult | StreamReader |
Execute a command and wait. Returns StreamReader when background=True |
stream() |
async def stream(cmd, *, timeout=60, env=None, cwd="", user="") -> AsyncIterator[ProcessChunk] |
Stream command output |
start() |
async def start(cmd, *, timeout=60, env=None, cwd="", user="") -> StreamReader[ProcessChunk] |
Start a command in the background, return StreamReader |
list() |
async def list() -> list[ProcessInfo] |
List running processes |
kill() |
async def kill(pid: int) -> None |
Terminate a process |
send_input() |
async def send_input(pid: int, data: str) -> None |
Send data to process stdin |
send_signal() |
async def send_signal(pid: int, signal: int = 15) -> None |
Send SIGTERM (15) or SIGKILL (9) to a process; any other number raises ValueError (envd only delivers these two) |
Logically associated with the shell capability (declared in template.yaml; no runtime gate — requests are forwarded to the sandbox regardless). Each async method has a _sync suffixed sync version (e.g., run_sync()).
sandbox.files # FilesModule instance| Method | Signature | Description |
|---|---|---|
read() |
async def read(path, *, encoding="utf-8") -> str |
Read a text file |
read_bytes() |
async def read_bytes(path) -> bytes |
Read a binary file |
write() |
async def write(path, content: str | bytes) -> None |
Write a file |
list() |
async def list(path="/") -> list[FileInfo] |
List a directory |
remove() |
async def remove(path) -> None |
Delete a file/directory |
exists() |
async def exists(path) -> bool |
Check if a path exists |
make_dir() |
async def make_dir(path) -> None |
Create a directory (including parents) |
upload() |
async def upload(local_path, remote_path) -> None |
Upload a local file to the sandbox |
download() |
async def download(remote_path, local_path) -> None |
Download a sandbox file to local |
watch() |
async def watch(path) -> StreamReader[WatchEvent] |
Watch for directory changes |
move() |
async def move(source, destination) -> None |
Move/rename |
get_info() |
async def get_info(path) -> FileInfo |
Get file info |
upload_url() |
async def upload_url(path) -> str |
envd /files URL. The request must send X-Access-Token; this is not a signed URL |
download_url() |
async def download_url(path) -> str |
Same as upload |
Logically associated with the files capability (declared in template.yaml; no runtime gate). Each async method has a _sync suffixed sync version.
sandbox.network # NetworkModule instanceAll methods are local computations with no network requests. Logically associated with the ports capability (no runtime gate).
| Method | Signature | Description |
|---|---|---|
get_host() |
def get_host(port: int) -> str |
Returns {port}-{sandbox_id}.{domain} |
get_url() |
def get_url(port: int) -> str |
Returns https://{port}-{sandbox_id}.{domain} |
get_access_headers() |
def get_access_headers() -> dict[str, str] |
Secure mode: X-Access-Token for the platform gateway. Not sent by sandbox.run |
sandbox.code # CodeContextModule instance| Method | Signature | Description |
|---|---|---|
run() |
async def run(code, *, language="python", timeout=30, context_id=None, mode="stateless", envs=None, on_stdout=None, on_stderr=None, on_result=None) -> CodeResult |
Execute code |
create_context() |
async def create_context(*, language="python") -> dict |
Create an execution context |
list_contexts() |
async def list_contexts() -> list[dict] |
List all contexts |
restart_context() |
async def restart_context(context_id) -> dict |
Restart a context |
remove_context() |
async def remove_context(context_id) -> None |
Delete a context |
Each method requires its exact provider operation: run() defaults to code.execute; mode="default-context" selects code.default-context.execute, and a nonempty context_id selects code.context.execute. Context create/list/restart/delete are separate operations. Callbacks additionally require code.stream. Unsupported adapter operations raise E8004 before payload; missing runtime/HTTP 404 never falls back to shell. Each async method has a _sync suffixed version. See workflows for current adapter boundaries and the independent pinned standard clients.
from agent_sandbox.api import ServerClient, ServerCapabilitiesTyped client for the template-authored SandboxServer (port 9000, PTY WebSocket on 9001). It is separate from
the envd-backed sandbox.files / sandbox.commands: use Sandbox.server when the template ships a server and
you want policy-scoped, scope-checked access, or need endpoints envd lacks (files.search, files.archive,
files.watch, process.output, git, browser). Every coroutine has a *_sync twin; async generators
(files.watch, process.shell_stream, process.follow) have collecting coroutines (files.watch_for,
process.run_stream) instead. Models live in agent_sandbox.models.server.
| Member | Signature | Description |
|---|---|---|
ServerClient() |
(base_url, *, token=None, headers=None, pty_url=None, timeout=30.0, http_client=None, expires_at=None) |
token is sent as Authorization: Bearer; headers carry the gateway X-Access-Token |
ProviderSandbox.application_client() |
async (port=9000, *, token=None, timeout=30.0) -> ServerClient |
Resolves the provider application gateway descriptor, preserves its prefix/query and gateway headers, and uses a separate application token. Recommended across providers |
Sandbox.server |
cached_property -> ServerClient |
Client for port 9000. Native local URL helper; use application_client for a provider gateway descriptor |
Sandbox.server_at() |
(port=9000, *, token=None, pty_port=9001, timeout=30.0) -> ServerClient |
A fresh client. Native local URL helper; use application_client for a provider gateway descriptor; token is ABX_SERVER_TOKEN |
Sandbox.start_server() |
async (*, port=9000, commands=None, policy=None, token=None, env=None, command=None, wait=True, timeout=30.0) -> ServerClient |
Starts agent-sandbox-server serve as a background envd command and polls /health; policy is a dict (ABX_SERVER_POLICY) or a preset name; raises ConnectionError_ on timeout |
health() |
async -> bool |
GET /health, never raises for an unreachable server |
discover() |
async -> ServerCapabilities |
GET /capabilities; requires exact integer api_version=2 and an endpoint map before enabling calls; caches the checked document |
forget_discovery() |
() -> None |
Drop the cache (policy changed) |
check() |
async (endpoint, path=None, op=None) -> PathDecision |
POST /capabilities/check |
with_token() |
(token) -> ServerClient |
Same server, another identity |
aclose() |
async |
Close the HTTP session |
Sub-APIs (all return typed models; see Server HTTP API for the wire format):
| Sub-API | Methods |
|---|---|
files |
list, stat, exists, mkdir, delete, move, search, archive, watch/watch_for, upload, download, read_text, upload_file, download_file (the /upload and /download endpoints) |
process |
shell, shell_stream/run_stream, start, list, get, signal, terminate, kill, send_stdin, close_stdin, output, follow, wait |
pty |
create, list, get, resize, delete, connect (WebSocket PtyConnection) |
system |
info, metrics, env, set_env, ports, packages |
devtools |
run_code, git_status, git_diff |
browser |
navigate, screenshot, content, click, type, evaluate, pdf, console |
commands |
list, run |
ServerClient.ENDPOINT_METHODS maps every server endpoint id to its client methods (a test asserts that every
route of the server's default table is present).
Returned by discover(). There is no legacy mode: a server whose /capabilities lacks endpoints is not supported.
| Member | Description |
|---|---|
can(endpoint) |
True when the endpoint exists, is enabled and the identity may call it |
denial(endpoint) |
Reason string (endpoint_disabled, unknown_endpoint, missing_scope) or None |
rule(endpoint) |
The rule code that disabled the endpoint (policy:groups.file_ops, default:opt-in:dev_tools, ...) or None |
require(endpoint) |
Raises EndpointNotAvailableError / PolicyDeniedError; otherwise returns the EndpointInfo |
info(endpoint) |
EndpointInfo (method, path, group, enabled, allowed, scopes, limits, paths, params) |
limit(endpoint, key, default=None) / param(...) |
A configured limit / parameter |
paths(endpoint) |
EndpointPaths (allow, read_only, deny_count, symlinks) |
endpoints_for(scope) / available() |
Endpoint ids granted by a scope / callable now |
check_path(endpoint, path, op=None) (+ _sync) |
Authoritative server-side path decision (never an existence oracle) |
groups, group_summary |
{group: enabled} and {group: {enabled, total}} derived views; the switch is the endpoint rule |
identity_id, scopes, preset, revision, warnings, api_version, server_version, configured |
Document metadata |
ServerAPIError (E9000) -> ServerAuthError (E9001, also AuthenticationError), PolicyDeniedError (E9002; scope) ->
FilePolicyDeniedError (also PermissionDeniedError), EndpointNotAvailableError (E9003, also
CapabilityNotSupportedError), PayloadTooLargeError (E9004; limit), RateLimitedError (E9005; retry_after).
See Error Codes.
from agent_sandbox.models.sandbox import SandboxStatus
class SandboxStatus(str, Enum):
CREATING = "creating"
RUNNING = "running"
PAUSED = "paused"
STOPPING = "stopping"
STOPPED = "stopped"
ERROR = "error"| Field | Type | Description |
|---|---|---|
sandbox_id |
str |
Sandbox ID |
template |
str |
Template name |
status |
SandboxStatus |
Current status |
envd_url |
str | None |
envd data plane URL |
envd_access_token |
str | None |
envd authentication token |
metadata |
dict |
User metadata |
started_at |
datetime | None |
Creation time |
| Field | Type | Description |
|---|---|---|
text |
str |
stdout (trailing whitespace stripped) |
stdout |
str |
Raw stdout |
stderr |
str |
Raw stderr |
exit_code |
int |
Exit code |
execution_time |
float |
Execution time (seconds) |
output_files |
list |
Output file list |
| Field | Type | Description |
|---|---|---|
name |
str |
File name |
path |
str |
File path |
size |
int |
File size (bytes, default 0) |
mime_type |
str |
MIME type (default "application/octet-stream") |
| Field | Type | Description |
|---|---|---|
stdout |
str |
Standard output |
stderr |
str |
Standard error |
exit_code |
int |
Exit code |
execution_time |
float |
Execution time (seconds) |
success |
bool |
exit_code == 0 (property) |
| Field | Type | Description |
|---|---|---|
type |
ProcessChunkType |
stdout / stderr / exit |
data |
str |
Data content |
exit_code |
int | None |
Exit code (only for exit type) |
pid |
int | str | None |
Native startup acknowledgment identifier; preserved as an integer or opaque string |
| Field | Type | Description |
|---|---|---|
name |
str |
File name |
path |
str |
Absolute path |
type |
FileType |
file / directory |
size |
int |
File size (bytes) |
All exceptions inherit from SandboxError and carry code, message, suggestion, and docs_url attributes.
See Error Codes Reference for the complete error code listing.