Providers
A provider is a place code can be run — the Datalayer platform, a Jupyter Server, E2B, Modal, a container on this very machine. Each ships its own environments and needs its own credentials, and each is reached through the same API. This section is one page per provider: what it is, what it needs, and what it can and cannot do.
Creating a Sandbox​
Use Sandbox.create() to create a new sandbox:
Canonical variant names are cloudflare, coreweave, datalayer,
daytona, docker, e2b, eval, google-colab, jupyter-server, kaggle,
modal, and monty. Older local-* names are no longer supported.
A name is read in whatever spelling it arrives in: google-colab,
google_colab and Google Colab all name the same variant.
from code_sandboxes import Sandbox
# Create with defaults (datalayer variant)
sandbox = Sandbox.create()
# Create with specific variant
sandbox = Sandbox.create(variant="datalayer")
# Create with timeout and environment
sandbox = Sandbox.create(
variant="datalayer",
timeout=300,
environment="ai-agents-env",
)
# Create with GPU support
sandbox = Sandbox.create(
variant="datalayer",
gpu="T4",
cpu=4.0,
memory=8192,
)
# Create with network policy
sandbox = Sandbox.create(
variant="eval",
network_policy="none", # block all outbound connections
)
Sandbox Variants​
Concrete implementations are available from top-level modules:
from code_sandboxes.jupyter_server_sandbox import JupyterServerSandbox
from code_sandboxes.docker_sandbox import DockerSandbox
from code_sandboxes.eval_sandbox import EvalSandbox
from code_sandboxes.datalayer_sandbox import DatalayerSandbox
Each page below explains how to configure each variant.
| Variant | Summary |
|---|---|
cloudflare | Container on Cloudflare's edge, through a deployed sandbox bridge Worker |
coreweave | Container on CoreWeave with a session process and an optional GPU |
datalayer | Datalayer managed runtime with optional GPU |
daytona | Daytona cloud sandbox with a stateful interpreter |
docker | Jupyter execution in a Docker container |
e2b | E2B Firecracker microVM with a Jupyter kernel and rich outputs |
eval | In-process exec() for fast development-only runs |
google-colab | Google Colab runtime via runtime proxy |
jupyter-server | Jupyter kernel-backed execution with persistent state |
kaggle | Kaggle runtime (interactive or batch) |
modal | Modal container execution |
monty | Secure in-process Python subset via Monty |
Environments​
List available environments for a sandbox variant and pick one when creating a sandbox.
from code_sandboxes import Sandbox
environments = Sandbox.list_environments(variant="datalayer")
for env in environments:
print(f"{env.name}: {env.title}")
# Select the first environment
if environments:
sandbox = Sandbox.create(
variant="datalayer",
environment=environments[0].name,
)
sandbox.start()
sandbox.terminate()
Code Execution​
Execute Python code with run_code():
with Sandbox.create() as sandbox:
# Simple execution
result = sandbox.run_code("print('hello')")
print(result.stdout) # "hello"
# Check success
if result.success:
print("Code executed successfully")
elif not result.execution_ok:
print(f"Execution error: {result.execution_error}")
elif result.exit_code not in (None, 0):
print(f"Process exited with code: {result.exit_code}")
else:
print(f"Code error: {result.code_error}")
# Multi-statement blocks return the last expression
result = sandbox.run_code("""
x = 10
x * 2
""")
print(result.text)
Async Execution​
Use await directly in run_code() when the sandbox supports async execution
(eval, jupyter, and datalayer). The last expression is
returned in results just like sync code.
with Sandbox.create(variant="eval") as sandbox:
result = sandbox.run_code("""
import asyncio
async def fetch_value():
await asyncio.sleep(0.01)
return 21
value = await fetch_value()
print(f"value: {value}")
value * 2
""")
assert result.success
print(result.stdout) # "value: 21"
print(result.text) # "42"
State Persistence​
Most sandbox variants keep state (variables, imports, and definitions) within the same sandbox instance. For example:
with Sandbox.create() as sandbox:
sandbox.run_code("counter = 1")
sandbox.run_code("counter += 1")
result = sandbox.run_code("counter")
print(result.text) # 2
What a variant cannot do is hold a namespace open when its backend gives it
nothing to hold one with. cloudflare runs each snippet in a
process of its own for that reason, and its page says what to do instead;
coreweave keeps a session process and falls back to the same
arrangement when that process cannot be started.
Streaming Output​
from code_sandboxes import OutputMessage
def on_output(msg: OutputMessage):
print(f"[{msg.stream}] {msg.line}")
with Sandbox.create() as sandbox:
result = sandbox.run_code(
"for i in range(5): print(f'Step {i}')",
on_stdout=on_output,
)
Filesystem Operations​
Access files within the sandbox:
with Sandbox.create() as sandbox:
# Write files
sandbox.files.write("/data/test.txt", "Hello World")
# Read files
content = sandbox.files.read("/data/test.txt")
# List directory
for f in sandbox.files.list("/data"):
print(f"{f.name} ({f.size} bytes)")
# Create directories
sandbox.files.mkdir("/data/subdir")
# Upload/download
sandbox.files.upload("local.txt", "/remote/file.txt")
sandbox.files.download("/remote/file.txt", "downloaded.txt")
Command Execution​
Run shell commands in the sandbox:
with Sandbox.create() as sandbox:
# Run command and wait
result = sandbox.commands.run("ls -la /")
print(result.stdout)
# Execute with streaming output
process = sandbox.commands.exec("python", "-c", "print('hello')")
for line in process.stdout:
print(line, end="")
# Install system packages
sandbox.commands.install_system_packages(["curl", "wget"])
Lifecycle Management​
Reconnecting to a Sandbox​
# Get sandbox ID for later
sandbox = Sandbox.create(variant="datalayer")
sandbox_id = sandbox.sandbox_id
sandbox.start()
# Later: reconnect
sandbox = Sandbox.from_id(sandbox_id)
result = sandbox.run_code("print('Still running!')")
Listing Sandboxes​
# List all sandboxes
sandboxes = Sandbox.list(variant="datalayer")
for info in sandboxes:
print(f"{info.sandbox_id}: {info.status}")
Termination​
sandbox = Sandbox.create()
sandbox.start()
# Graceful shutdown
sandbox.terminate()
# Force kill
sandbox.kill()
# Or use context manager for automatic cleanup
with Sandbox.create() as sandbox:
sandbox.run_code("print('auto cleanup')")
Snapshots​
Save and restore sandbox state (datalayer only):
with Sandbox.create(variant="datalayer") as sandbox:
# Set up environment
sandbox.run_code("import pandas as pd")
sandbox.run_code("df = pd.DataFrame({'a': [1,2,3]})")
# Create snapshot
snapshot = sandbox.create_snapshot("my-setup")
print(f"Snapshot: {snapshot.id}")
# Later: restore from snapshot
with Sandbox.create(
variant="datalayer",
snapshot_name="my-setup"
) as sandbox:
result = sandbox.run_code("print(df)") # State restored
Timeout Management​
# Set timeout at creation
sandbox = Sandbox.create(timeout=60)
# Update timeout
sandbox.set_timeout(120)
Tags and Metadata​
# Create with tags
sandbox = Sandbox.create(tags={"project": "demo", "env": "dev"})
# Update tags
sandbox.set_tags({"project": "demo", "env": "prod"})