a2a_pack.sandbox
Code-execution sandbox surface available to agents via ctx.sandbox.
The abstract :class:SandboxClient is what agent code programs against. The
runtime layer (host-side microsandbox + FUSE-mounted MinIO, in-cluster
DaemonSet, hosted SaaS) supplies a concrete implementation.
The sandbox is general-purpose code execution, not Python-only. Agents can:
- run arbitrary shell pipelines:
await ctx.sandbox.run_shell("git clone … && cargo build") - exec a binary with explicit args (no shell parsing):
await sb.exec("/usr/bin/git", ["clone", url]) - pick any OCI image:
run_shell("npx @openai/codex …", image="node:20-slim")
run_python is just a convenience for the common Python-snippet case.
Why an abstract here when microsandbox itself already has a Python SDK?
The platform owns the policy layer — bucket selection, network egress,
write-path restrictions, resource caps, audit logging. Agents must depend on
the policy-respecting surface, not on the raw SDK, so the same agent code
runs unchanged across local dev / cluster / hosted environments.
ExecResult (class)
ExecResult(stdout: 'str', stderr: 'str' = '', exit_code: 'int' = 0, truncated: 'bool' = False) -> NoneResult of a command run inside a sandbox.
__init__ (method)
__init__(self, stdout: 'str', stderr: 'str' = '', exit_code: 'int' = 0, truncated: 'bool' = False) -> NoneInitialize self. See help(type(self)) for accurate signature.
SandboxClient (class)
SandboxClient()Negotiation surface handed to agents via ctx.sandbox.
create (method)
create(self, spec: 'SandboxSpec') -> 'SandboxHandle'(no docstring)
get (method)
get(self, name: 'str') -> 'SandboxHandle'(no docstring)
list (method)
list(self) -> 'list[str]'(no docstring)
remove (method)
remove(self, name: 'str') -> 'None'(no docstring)
run_python (method)
run_python(self, code: 'str', *, image: 'str' = 'python:3.11-slim', **kwargs: 'Any') -> 'ExecResult'Convenience: spin a one-shot sandbox, run inline Python, tear down.
Equivalent to create(SandboxSpec(image=image)).exec("python", ["-c", code]).
Use the lower-level surface when you need persistence, multiple
commands, or non-Python tools.
run_shell (method)
run_shell(self, script: 'str', *, image: 'str' = 'python:3.11-slim', **kwargs: 'Any') -> 'ExecResult'Convenience: spin a one-shot sandbox, run an arbitrary shell script, tear down.
Pass image= to pick the toolchain (e.g. "node:20-slim" for
npm-based tools like codex, "rust:1-slim" for cargo,
"alpine/git" for plain git ops). The default python:3.11-slim
already has bash/coreutils/curl/git so most one-liners just work.
SandboxHandle (class)
SandboxHandle()Live handle to a running sandbox VM.
exec (method)
exec(self, cmd: 'str', args: 'Sequence[str] | None' = None, *, timeout: 'float | None' = None) -> 'ExecResult'(no docstring)
kill (method)
kill(self) -> 'None'(no docstring)
logs (method)
logs(self, *, tail: 'int | None' = None) -> 'str'(no docstring)
shell (method)
shell(self, script: 'str', *, timeout: 'float | None' = None) -> 'ExecResult'(no docstring)
stop (method)
stop(self) -> 'None'(no docstring)
SandboxSpec (class)
SandboxSpec(name: 'str', image: 'str' = 'python:3.11-slim', memory_mib: 'int' = 512, cpus: 'int' = 1, workspace: 'str | None' = None, secrets: 'tuple[str, ...]' = (), egress: 'tuple[str, ...]' = (), labels: 'dict[str, str]' = <factory>) -> NoneCaller request shape for :meth:SandboxClient.create.
__init__ (method)
__init__(self, name: 'str', image: 'str' = 'python:3.11-slim', memory_mib: 'int' = 512, cpus: 'int' = 1, workspace: 'str | None' = None, secrets: 'tuple[str, ...]' = (), egress: 'tuple[str, ...]' = (), labels: 'dict[str, str]' = <factory>) -> NoneInitialize self. See help(type(self)) for accurate signature.
SandboxUnavailable (class)
Raised when ctx.sandbox is accessed but no runtime is attached.
Source: apps/a2a/a2a_pack/sandbox.py