Agent Sandbox Registry

python-sdk

Declarative Usage (@sandbox Decorator)

docs/en/guide/declarative-usage.md

Declarative Usage (@sandbox Decorator)

The @sandbox decorator lets you declaratively execute Python functions in a remote sandbox without manually managing the sandbox lifecycle.


Basic Usage

from agent_sandbox.declarative import sandbox

@sandbox(template="code-interpreter-v1")
def analyze(data):
    import pandas as pd
    df = pd.DataFrame(data)
    return df.describe().to_dict()

# When called, it automatically: creates sandbox → uploads function → executes → returns result → destroys sandbox
result = analyze({"col1": [1, 2, 3], "col2": [4, 5, 6]})
print(result)

Parameter Configuration

@sandbox(
    template="code-interpreter-v1",  # Template name (default "code-interpreter-v1")
    timeout=300,                      # Sandbox timeout in seconds (default 300)
    envs={"MY_KEY": "value"},         # Environment variables
    packages=["pandas", "numpy"],     # pip packages to pre-install remotely
    serializer="json",                # Serialization method (default "json")
    sandbox_id=None,                  # Reuse an existing sandbox ID (skips creation when not None)
    keep_alive=False,                 # When True, the sandbox is not destroyed after execution
    api_key=None,                     # API Key override
    api_url=None,                     # Platform API URL override
    domain=None,                      # Domain override
    cpu=None,                         # CPU cores
    memory=None,                      # Memory in MB
)
def my_func():
    pass

Parameter Details

Parameter Type Default Description
template str "code-interpreter-v1" Sandbox template name
timeout int 300 Sandbox timeout in seconds
envs dict None Injected environment variables (envd scope; see Environment Variables Guide)
packages list[str] None pip packages to pre-install remotely
serializer str "json" Serialization mode (only json is supported)
sandbox_id str None Reuse an existing sandbox ID
keep_alive bool False Do not destroy the sandbox after execution
api_key str None API Key override
api_url str None Platform URL override
domain str None Platform domain
cpu int None CPU cores
memory int None Memory in MB

Serialization Rules

The serializer parameter controls how function arguments and return values are serialized. Currently only JSON mode is supported.

Mode Extra Dependencies Supported Types Description
json (default) None JSON-serializable types Safest, cross-language compatible

JSON mode: Arguments are serialized via json.dumps, and results are deserialized via json.loads. Unsupported types fall back to default=str.


Using with async

The decorator automatically detects whether the decorated function is asynchronous:

@sandbox(template="code-interpreter-v1")
async def async_analyze(data):
    import pandas as pd
    df = pd.DataFrame(data)
    return df.describe().to_dict()

# Async call
result = await async_analyze({"col": [1, 2, 3]})

For synchronous functions, the decorator generates a synchronous wrapper. If the synchronous wrapper is called within an existing event loop, it uses a ThreadPoolExecutor to avoid blocking.


Reusing a Sandbox

# Create a sandbox and keep it running
@sandbox(template="code-interpreter-v1", keep_alive=True)
def setup():
    import subprocess
    subprocess.run(["pip", "install", "flask"])
    return "ready"

sandbox_id = "sbx-xxxx"  # Get the sandbox ID

# Reuse the existing sandbox
@sandbox(sandbox_id=sandbox_id)
def use_flask():
    from flask import Flask
    return "Flask imported successfully"

Registration-Style Commands

In addition to the decorator pattern, the sandbox object also supports registration-style commands:

from agent_sandbox.declarative import sandbox

@sandbox.register
def demo(x: int, y: str) -> str:
    """A simple demo command"""
    return f"{y}={x}"

# Sync call
result = sandbox.run("demo", x=1, y="hello")
print(result)  # "hello=1"

# Async call
result = await sandbox.run_async("demo", x=2, y="world")

# List registered commands
commands = sandbox.list_registered()

Registered function parameters only support scalar types: str, int, float, bool.

This is the one mechanism for named commands. A command registered in a template's commands.py (or with @sandbox.register) is served by the in-sandbox server, and a regular Sandbox calls it with await sandbox.run("demo", x=1, y="hello") (POST /commands/demo). template.yaml has no custom_commands key; the client rejects it.

File Transfer

sandbox.register only registers named commands. File upload and download are endpoints of the server's file_ops group (on by default); a client uses sandbox.files or ServerClient.files.

Start the HTTP Server

sandbox.server.start(port=9000, host="0.0.0.0")

Limitations

  1. Parameter serialization: Function arguments and return values must be JSON-serializable (non-serializable types fall back to str)
  2. Function source code: The decorator obtains function source via inspect.getsource() — lambdas and dynamically generated functions are not supported
  3. Imports: Libraries needed in the remote sandbox must be pre-installed via the packages parameter or already included in the template
  4. Registered command parameter types: @sandbox.register only supports scalar types (str/int/float/bool) — complex types are not supported
  5. Closure variables: External variables referenced in the function are not automatically serialized — use explicit parameter passing instead
  6. Execution environment isolation: The decorated function runs in an independent remote Python process and does not share state with the local process

Next Steps