Sandboxes
Scannednpx machina-cli add skill samarth777/modal-skills/sandboxes --openclawModal Sandboxes Reference
Detailed reference for running arbitrary code in isolated containers.
Overview
Sandboxes are containers you can create, interact with, and terminate at runtime. They're ideal for:
- Executing LLM-generated code
- Running untrusted user code
- Interactive development environments
- Dynamic code analysis
Basic Usage
import modal
# Get or create an App reference
app = modal.App.lookup("sandbox-app", create_if_missing=True)
# Create a sandbox
sb = modal.Sandbox.create(app=app)
# Execute commands
p = sb.exec("python", "-c", "print('Hello!')")
print(p.stdout.read()) # "Hello!\n"
# Clean up
sb.terminate()
Configuration
Custom Images
image = (
modal.Image.debian_slim()
.pip_install("pandas", "numpy", "matplotlib")
)
with modal.enable_output(): # Show build logs
sb = modal.Sandbox.create(
image=image,
app=app,
)
Volumes
volume = modal.Volume.from_name("my-volume", create_if_missing=True)
sb = modal.Sandbox.create(
volumes={"/data": volume},
app=app,
)
# Files written to /data persist across sandboxes
sb.exec("bash", "-c", "echo 'hello' > /data/output.txt").wait()
Secrets
secret = modal.Secret.from_dict({"API_KEY": "xxx"})
sb = modal.Sandbox.create(
secrets=[secret],
app=app,
)
p = sb.exec("bash", "-c", "echo $API_KEY")
print(p.stdout.read()) # "xxx\n"
GPU Access
sb = modal.Sandbox.create(
gpu="A100",
app=app,
)
p = sb.exec("nvidia-smi")
print(p.stdout.read())
Timeouts
sb = modal.Sandbox.create(
timeout=600, # Max 10 minutes total
idle_timeout=60, # Auto-terminate after 60s idle
app=app,
)
Working Directory
sb = modal.Sandbox.create(
workdir="/app",
app=app,
)
Executing Commands
Basic Execution
# Simple command
p = sb.exec("python", "-c", "print(1+1)")
p.wait() # Wait for completion
print(p.returncode) # 0
# Read output
print(p.stdout.read()) # "2\n"
print(p.stderr.read()) # ""
Streaming Output
p = sb.exec("bash", "-c", "for i in {1..5}; do echo $i; sleep 1; done")
# Stream line by line
for line in p.stdout:
print(line, end="")
With Timeout
p = sb.exec("sleep", "100", timeout=5)
# Raises TimeoutError after 5 seconds
With Entrypoint
Run a single command as the sandbox's main process:
sb = modal.Sandbox.create(
"python", "-m", "http.server", "8080",
app=app,
timeout=60,
)
# Sandbox runs until command completes or timeout
for line in sb.stdout:
print(line, end="")
File System Access
Filesystem API (Alpha)
# Write file
with sb.open("output.txt", "w") as f:
f.write("Hello, World!")
# Read file
with sb.open("output.txt", "r") as f:
content = f.read()
# Binary mode
with sb.open("data.bin", "wb") as f:
f.write(b"\x00\x01\x02")
# Directory operations
sb.mkdir("/app/data")
files = sb.ls("/app")
sb.rm("/app/data/temp.txt")
Using Volumes
# Ephemeral volume (auto-cleanup)
with modal.Volume.ephemeral() as vol:
# Upload files
with vol.batch_upload() as batch:
batch.put_file("local.txt", "/remote.txt")
batch.put_directory("./local_dir", "/remote_dir")
sb = modal.Sandbox.create(
volumes={"/data": vol},
app=app,
)
# Work with files
sb.exec("cat", "/data/remote.txt").wait()
sb.terminate()
sb.wait(raise_on_termination=False)
# Read files after sandbox terminates
for chunk in vol.read_file("output.txt"):
print(chunk)
Syncing Volume Changes
For Volumes v2, explicitly sync changes:
sb.exec("bash", "-c", "echo 'data' > /data/file.txt").wait()
sb.exec("sync", "/data").wait() # Persist changes immediately
Networking
Port Forwarding with Tunnels
sb = modal.Sandbox.create(
"python", "-m", "http.server", "8080",
app=app,
)
tunnel = sb.tunnels()[8080]
print(f"Access at: {tunnel.url}")
Network Isolation
# Block all network access
sb = modal.Sandbox.create(
block_network=True,
app=app,
)
Snapshots
Filesystem Snapshots
Save sandbox state as a new image:
sb = modal.Sandbox.create(app=app)
# Set up environment
sb.exec("pip", "install", "pandas").wait()
sb.exec("mkdir", "/app/data").wait()
# Create snapshot
image = sb.snapshot_filesystem()
sb.terminate()
# Use snapshot for new sandbox
sb2 = modal.Sandbox.create(image=image, app=app)
sb2.exec("python", "-c", "import pandas; print(pandas.__version__)").wait()
Security Best Practices
For Untrusted Code
sb = modal.Sandbox.create(
# Restrict Modal API access
restrict_modal_access=True,
# Block network
block_network=True,
# Set timeout
timeout=30,
# Minimal image
image=modal.Image.debian_slim(),
app=app,
)
LLM Code Execution
def execute_llm_code(code: str) -> dict:
app = modal.App.lookup("code-executor", create_if_missing=True)
sb = modal.Sandbox.create(
image=modal.Image.debian_slim().pip_install("numpy", "pandas"),
timeout=30,
block_network=True,
app=app,
)
try:
# Write code to file
with sb.open("/tmp/code.py", "w") as f:
f.write(code)
# Execute
p = sb.exec("python", "/tmp/code.py", timeout=10)
p.wait()
return {
"stdout": p.stdout.read(),
"stderr": p.stderr.read(),
"returncode": p.returncode,
}
finally:
sb.terminate()
Lifecycle Management
Graceful Shutdown
sb.terminate() # Request termination
sb.wait(raise_on_termination=False) # Wait for cleanup
Check Status
if sb.poll() is None:
print("Still running")
else:
print(f"Terminated with code: {sb.poll()}")
Async Usage
import asyncio
async def run_async():
app = await modal.App.lookup.aio("sandbox-app", create_if_missing=True)
sb = await modal.Sandbox.create.aio(app=app)
p = await sb.exec.aio("python", "-c", "print('async!')")
output = await p.stdout.read.aio()
print(output)
await sb.terminate.aio()
Source
git clone https://github.com/samarth777/modal-skills/blob/main/skills/sandboxes/SKILL.mdView on GitHub Overview
Sandboxes are containers you can create, interact with, and terminate at runtime. They're ideal for executing LLM-generated code, running untrusted user code, interactive development environments, and dynamic code analysis.
How This Skill Works
Using Modal, you obtain an App reference, create a Sandbox via Sandbox.create with optional image, volumes, secrets, and timeouts, and then run commands through sb.exec. The sandbox runs in isolation, streams stdout/stderr, and can be terminated or waited for completion, with data and state optionally persisting via volumes.
When to Use It
- Executing LLM-generated code in a contained environment to limit risk
- Running untrusted user code safely without affecting the host
- Interactive development workflows that require an isolated sandbox
- Dynamic code analysis in a controlled container
- Managing long-running commands with timeouts and idle terminations
Quick Start
- Step 1: Get or create an App reference with modal.App.lookup('sandbox-app', create_if_missing=True)
- Step 2: Create a sandbox with sb = modal.Sandbox.create(app=app)
- Step 3: Run a command, wait for completion, and terminate the sandbox
Best Practices
- Start with a dedicated App reference (modal.App.lookup with create_if_missing=True) to isolate resources
- Choose a minimal, supporting image (e.g., debian_slim) and install needed packages via pip_install when needed
- Use volumes to persist data across sandboxes and for sharing files
- Inject secrets securely (e.g., modal.Secret) and limit their scope to the sandbox
- Configure timeout and idle_timeout to prevent runaway sandboxes and manage costs
Example Use Cases
- Create a sandbox and run a simple Python command, then read stdout
- Persist output to /data/output.txt via a mounted volume and read it after sandbox termination
- Use a Secret to access an API key and print it inside the sandbox
- Enable GPU access and run nvidia-smi to verify GPU availability
- Run a server as the sandbox's entrypoint (e.g., python -m http.server) and stream logs