Skip to main content
Prerequisites: You must create an environment before you can create sandboxes. Sandboxes require a parent environment and inherit workspace permissions from it.

What is a Sandbox?

A sandbox is an isolated container for executing arbitrary code. Sandboxes provide secure, temporary compute resources for running untrusted agent code. Key characteristics:
  • On-Demand: Created when needed, not pre-provisioned
  • Isolated: Strong security boundaries with optional network blocking
  • Flexible: Configurable image, resources, and environment variables

Why Use Sandboxes?

Security

Sandboxes provide isolation for untrusted code:
  • Run agent-generated code safely
  • Optional network blocking to prevent data exfiltration
  • Automatic cleanup prevents resource leaks

Flexibility

Configure sandboxes for your needs:
  • Choose any container image
  • Set CPU and memory resources
  • Add environment variables
  • Mount cloud storage for data access

Convenience

Sandboxes are managed automatically:
  • Created on demand (no pre-provisioning)
  • Automatic deletion after timeout
  • No manual cleanup needed
  • Pay only for active usage

Sandbox Lifecycle

1. Creation

Create sandboxes via the Python SDK:
from openreward import OpenReward, SandboxSettings

client = OpenReward(api_key="your-api-key")

settings = SandboxSettings(
    environment="username/environment-name",  # Required: parent environment
    image="python:3.11-slim",                 # Required: container image
    machine_size="1:2",                       # Required: CPU:Memory
    env={"DEBUG": "true"},                    # Optional: environment variables
    block_network=False,                      # Optional: network isolation
)

sandbox = client.sandbox(
    settings=settings,
)

await sandbox.start()  # Creates the sandbox
What happens:
1. Request sent to OpenReward

2. Parent environment validated

3. Sandbox provisioned (5-30 seconds)

4. Container starts running

5. Ready for command execution

2. Command Execution

Once created, execute commands in the sandbox:
# Run a command
output, exit_code = await sandbox.run("python script.py")
if exit_code == 0:
    print(f"Success: {output}")

# Run with check (raises on non-zero exit)
output = await sandbox.check_run("pytest tests/")

# Upload file
await sandbox.upload(
    local_path="./data.csv",
    container_path="/app/input.csv"
)

# Download file
content = await sandbox.download("/app/output.json")
Available operations:
  • run(): Execute command and return output
  • check_run(): Execute command, raise on error if it returns a non-zero exit code
  • upload(): Upload files to sandbox
  • download(): Download files from sandbox

3. Deletion

Explicit deletion:
await sandbox.stop()  # Immediately delete sandbox
Automatic deletion (recommended):
async with client.sandbox(settings) as sandbox:
    # Sandbox automatically deleted on exit
    await sandbox.run("echo hello")
# Sandbox deleted here, even if error occurs

Storage Integration

Cloud Storage Mounts

Sandboxes can access your environment’s cloud storage for persistent data:
from openreward import SandboxSettings, BucketConfig

settings = SandboxSettings(
    environment="username/env-name",
    image="python:3.11-slim",
    machine_size="1:2",
    bucket_config=BucketConfig(
        mount_path="/workspace",           # Where to mount in container
        only_dir="datasets/subset",        # Optional: mount only subdirectory
    )
)
See Storage & Buckets for detailed configuration.

Relationship to Environments

Parent Environment Requirement

Every sandbox must specify a parent environment. The environment must exist before sandbox creation, and you must have access to it.
Why this requirement?
  1. Access Control: Sandbox inherits permissions from environment
  2. Permission Validation: Ensures you have access to resources
  3. Billing Attribution: Sandbox usage billed to environmentces
Example:
# ❌ ERROR: No such environment
sandbox = client.sandbox(SandboxSettings(
    environment="nonexistent/env",
    image="python:3.11",
    machine_size="1:2"
))
# Raises: Environment 'nonexistent/env' not found

# ✅ Correct: Environment exists
sandbox = client.sandbox(SandboxSettings(
    environment="myusername/my-environment",  # This environment must exist
    image="python:3.11",
    machine_size="1:2"
))

Configuration Options

Machine Sizes

machine_size="CPU:Memory"

# Available sizes:
"0.1:0.1"   # Absolute minimum — tiny jobs, health checks, cron-like tasks
"0.5:0.5"   # Light balanced — simple services, low traffic
"1:1"       # Baseline balanced — small production services
"2:2"       # Solid balanced — steady traffic, moderate load
"4:4"       # Heavy balanced — CPU-bound or busy services

"0.1:0.2"   # Memory-lean — tiny CPU, slightly memory sensitive tasks
"0.5:1"     # Memory-biased light — small services with caching
"1:2"       # Memory-biased baseline — typical web apps
"2:4"       # Memory-biased heavy — APIs, JVMs, Python services
"4:8"       # Memory-heavy — large caches, in-memory workloads

"0.1:0.4"   # Extreme memory skew — config-heavy or idle memory holders
"0.5:2"     # Low CPU, high memory — background workers, queues
"1:4"       # High memory — analytics, batch jobs
"2:8"       # Very high memory — data processing, embeddings
"4:16"      # Maxed memory — serious data or model workloads

Network Isolation

Default: All egress allowed (full internet access) Blocked: Only essential services allowed (DNS, etc.)
settings = SandboxSettings(
    environment="username/env",
    image="python:3.11",
    machine_size="1:2",
    block_network=True  # Enable network isolation
)
Use cases for network blocking:
  • Running untrusted agent code
  • Preventing data exfiltration
  • Ensuring deterministic environments
  • Security-sensitive evaluations

Sidecar Containers

Add additional containers to run alongside your main container:
from openreward import SidecarContainer

settings = SandboxSettings(
    environment="username/env",
    image="python:3.11",
    machine_size="1:2",
    sidecars=[
        SidecarContainer(
            name="redis",
            image="redis:7-alpine",
            machine_size="0.5:1",
            env={"REDIS_PASSWORD": "secret"},
            command=["redis-server"],
            args=["--maxmemory", "256mb"],
            ports=[6379]
        )
    ]
)
Use cases:
  • Running databases (Redis, PostgreSQL)
  • Starting services (web servers, message queues)
  • Running monitoring tools
Note: Sidecars share the network namespace with the main container (accessible via localhost).

Host Aliases

Add custom DNS entries to /etc/hosts:
from openreward import HostAlias

settings = SandboxSettings(
    environment="username/env",
    image="python:3.11",
    machine_size="1:2",
    host_aliases=[
        HostAlias(
            ip="127.0.0.1",
            hostnames=["myapp.local", "api.local"]
        )
    ]
)

Next Steps