A sandbox is a Firecracker microVM — a fully isolated Linux environment with its own filesystem, process tree, and network namespace. Each sandbox boots in approximately 125 milliseconds and runs until it times out or is explicitly killed.
Sandbox states
| State | Description |
|---|
creating | VM is booting and envd daemon is starting |
running | Sandbox is active and commands can execute |
paused | Memory and filesystem state preserved, no CPU consumed |
killed | Sandbox destroyed and resources freed |
Create a sandbox
from declaw import Sandbox
sbx = Sandbox.create(
api_key="your-key",
domain="localhost:8080",
)
print(sbx.sandbox_id) # sbx-abc123
sbx.kill()
import { Sandbox } from '@declaw/sdk';
const sbx = await Sandbox.create({
apiKey: 'your-key',
domain: 'localhost:8080',
});
console.log(sbx.sandboxId);
await sbx.kill();
Create with full options
from declaw import Sandbox, SecurityPolicy, PIIConfig, ALL_TRAFFIC, SandboxLifecycle
sbx = Sandbox.create(
template="base",
timeout=300, # seconds until auto-kill
envs={"MY_VAR": "value"},
metadata={"project": "my-agent"},
resources={"vcpus": 2, "memory_mb": 512},
network={
"allow_out": ["*.openai.com"],
"deny_out": [ALL_TRAFFIC],
},
security=SecurityPolicy(
pii=PIIConfig(enabled=True, types=["ssn", "credit_card", "email"]),
injection_defense=True,
audit=True,
),
lifecycle=SandboxLifecycle(
on_timeout="pause", # "kill" (default) or "pause"
auto_resume=True,
),
)
import { Sandbox, ALL_TRAFFIC } from '@declaw/sdk';
const sbx = await Sandbox.create({
template: 'default',
timeout: 300,
envs: { MY_VAR: 'value' },
metadata: { project: 'my-agent' },
resources: { vcpus: 2, memory_mb: 512 },
network: {
allowOut: ['*.openai.com'],
denyOut: [ALL_TRAFFIC],
},
});
SandboxInfo model
The SandboxInfo object is returned by create(), get(), and list().
| Field | Type | Description |
|---|
sandbox_id | str | Unique identifier in sbx-* format |
template_id | str | Template used to create the sandbox |
name | str | None | Optional human-readable name |
state | SandboxState | Current state: creating, running, paused, killed |
metadata | dict[str, str] | User-defined key-value labels |
started_at | datetime | When the sandbox started |
end_at | datetime | None | Scheduled termination time |
Inspect a sandbox
info = sbx.get_info()
print(info.state) # SandboxState.running
print(info.timeout) # 300
print(info.started_at) # 2024-01-15T10:00:00Z
print(sbx.is_running()) # True
const info = await sbx.getInfo();
console.log(info.state); // 'running'
console.log(info.timeout); // 300
List sandboxes
from declaw import Sandbox, SandboxQuery, SandboxState
# List all running sandboxes
result = Sandbox.list(
query=SandboxQuery(state=[SandboxState.RUNNING]),
limit=20,
)
for sbx_info in result.get("sandboxes", []):
print(sbx_info.sandbox_id, sbx_info.state)
const { sandboxes } = await Sandbox.list({
query: { state: 'running' },
limit: 20,
});
for (const info of sandboxes) {
console.log(info.sandboxId, info.state);
}
Connect to an existing sandbox
Use connect() to reconnect to a running or paused sandbox from a different process or after a restart.
sbx = Sandbox.connect("sbx-abc123")
result = sbx.commands.run("echo still here")
print(result.stdout)
const sbx = await Sandbox.connect('sbx-abc123');
const result = await sbx.commands.run('echo still here');
Extend timeout
# Extend to 10 minutes from now
sbx.set_timeout(600)
await sbx.setTimeout(600);
Pause and resume
Pausing a sandbox preserves the full memory state and filesystem. No CPU is consumed while paused. The sandbox can be resumed instantly.
sbx.pause()
# Later — resume by connecting
sbx = Sandbox.connect("sbx-abc123")
result = sbx.commands.run("echo resumed")
await sbx.pause();
// Resume by connecting
const resumed = await Sandbox.connect('sbx-abc123');
SandboxMetrics model
metrics_list = sbx.get_metrics()
for m in metrics_list:
print(m.cpu_usage_percent) # 12.4
print(m.memory_usage_mb) # 128.0
print(m.disk_usage_mb) # 45.2
print(m.timestamp) # datetime
const metrics = await sbx.getMetrics();
for (const m of metrics) {
console.log(m.cpuUsagePercent);
console.log(m.memoryUsageMb);
console.log(m.diskUsageMb);
}
| Field | Type | Description |
|---|
timestamp | datetime | When the metrics were sampled |
cpu_usage_percent | float | CPU usage as a percentage of allocated vCPUs |
memory_usage_mb | float | RAM consumed in megabytes |
disk_usage_mb | float | Rootfs space consumed in megabytes |
Resource configuration
sbx = Sandbox.create(
resources={"vcpus": 2, "memory_mb": 1024},
)
const sbx = await Sandbox.create({
resources: { vcpus: 2, memoryMb: 1024 },
});
| Parameter | Default | Range | Description |
|---|
vcpus | 1 | 1–8 | Number of virtual CPUs |
memory_mb | 256 | 128–8192 | RAM in megabytes |
Disk is not configurable per-sandbox. Each sandbox gets its own copy of the base rootfs (up to 20 GB ext4).
Kill a sandbox
# Always clean up in a try/finally block
sbx = Sandbox.create()
try:
result = sbx.commands.run("python3 my_script.py")
print(result.stdout)
finally:
sbx.kill()
const sbx = await Sandbox.create();
try {
const result = await sbx.commands.run('node script.js');
console.log(result.stdout);
} finally {
await sbx.kill();
}
Auto-injected environment variables
Every sandbox receives these environment variables automatically:
| Variable | Value | Description |
|---|
DECLAW_SANDBOX_ID | sbx-abc123 | Unique sandbox identifier |
DECLAW_TEMPLATE_ID | default | Template the sandbox was created from |
DECLAW_SANDBOX | true | Indicates code is running inside Declaw |
DECLAW_SECURITY_POLICY | JSON string | Active security policy (for introspection) |
Lifecycle configuration
from declaw import Sandbox, SandboxLifecycle
sbx = Sandbox.create(
timeout=300,
lifecycle=SandboxLifecycle(
on_timeout="pause", # "kill" (default) or "pause"
auto_resume=True, # resume when SDK activity arrives
),
)
With on_timeout="pause", the sandbox is preserved rather than destroyed when it times out. Combined with auto_resume=True, the next SDK call automatically wakes it up.
Maximum runtime is 24 hours for Pro tier and 1 hour for the Base tier. Pausing resets the runtime window.