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?
- Access Control: Sandbox inherits permissions from environment
- Permission Validation: Ensures you have access to resources
- 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