Documentation Index
Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
Use this file to discover all available pages before exploring further.
StateSet Sandbox
Self-hosted Kubernetes sandbox infrastructure for running AI agents and code execution workloads in isolated containers. REST and WebSocket APIs for creating sandboxes, streaming command output, and managing files.
Skill Files
| File | URL |
|---|
| SKILL.md (this file) | https://doc.stateset.com/stateset-sandbox-skill.md |
Check for updates: Re-fetch these files anytime to see new features!
API Base URL
| Service | Base URL | Purpose |
|---|
| Sandbox API | https://api.sandbox.stateset.app/api/v1 | Sandbox management, execution, files |
| WebSocket | wss://api.sandbox.stateset.app/ws | Real-time streaming |
Environment Variables:
export STATESET_SANDBOX_API_KEY=sk_sandbox_xxx
export STATESET_SANDBOX_URL=https://api.sandbox.stateset.app
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Your App / Agent │
└─────────────────────┬───────────────────────────────────────┘
│ HTTP / WebSocket
▼
┌─────────────────────────────────────────────────────────────┐
│ Sandbox Controller │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ REST API │ │ WebSocket │ │ Warm Pod Pool │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────┬───────────────────────────────────────┘
│ Kubernetes API
▼
┌─────────────────────────────────────────────────────────────┐
│ Sandbox Pods │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ /workspace/ - Your code and files │ │
│ │ Node.js, Python, Go, Rust, Git, Docker CLI │ │
│ │ Isolated network, resource limits, timeouts │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Key Capabilities:
- Isolated execution per sandbox pod with resource limits
- REST and WebSocket APIs for command execution and streaming
- File read/write APIs for workspace workflows
- Prebuilt runtime with Node.js, Python, Go, Rust, and CLI tools
- Automatic cleanup with per-sandbox timeouts
- Warm pool support for sub-100ms startup
Agent Registration
AI agents must register to receive an API key for authentication.
Register a New Agent
curl -X POST https://api.sandbox.stateset.app/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"first_name": "Commerce",
"last_name": "Agent",
"organization_name": "My AI Company",
"email": "agent@example.com"
}'
Response:
{
"success": true,
"user": {
"id": "user_xxx",
"email": "agent@example.com"
},
"organization": {
"id": "org_xxx",
"name": "My AI Company"
},
"api_key": "sk_sandbox_xxx_xxxxxxxxxxxxxxxxxxxxxxxx",
"message": "Registration successful. Store your API key securely."
}
Important: Store the api_key securely. It is only returned once.
Authentication
All API requests require authentication:
curl https://api.sandbox.stateset.app/api/v1/sandboxes \
-H "Authorization: ApiKey YOUR_API_KEY"
Or with Bearer token (JWT):
curl https://api.sandbox.stateset.app/api/v1/sandboxes \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Quick Start
1. Create a Sandbox
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/create \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"cpus": "2",
"memory": "2Gi",
"timeout_seconds": 300
}'
Response:
{
"sandbox_id": "sandbox-a1b2c3d4",
"org_id": "org_xxx",
"status": "running",
"pod_ip": "10.0.1.42",
"created_at": "2026-01-30T10:00:00Z",
"expires_at": "2026-01-30T10:05:00Z",
"startup_metrics": {
"total_ms": 87,
"pod_creation_ms": 12,
"pod_ready_ms": 75
}
}
2. Write Files
# Base64 encode your content
CONTENT=$(echo 'console.log("Hello from sandbox!");' | base64)
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/SANDBOX_ID/files \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"files\": [{
\"path\": \"/workspace/hello.js\",
\"content\": \"$CONTENT\"
}]
}"
3. Execute Commands
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/SANDBOX_ID/execute \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"command": "node /workspace/hello.js"}'
Response:
{
"exit_code": 0,
"stdout": "Hello from sandbox!\n",
"stderr": ""
}
4. Read Files
curl "https://api.sandbox.stateset.app/api/v1/sandbox/SANDBOX_ID/files?path=/workspace/output.txt" \
-H "Authorization: ApiKey YOUR_API_KEY"
Response:
{
"path": "/workspace/output.txt",
"content": "SGVsbG8gV29ybGQh",
"size": 12
}
5. Stop Sandbox
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/SANDBOX_ID/stop \
-H "Authorization: ApiKey YOUR_API_KEY"
TypeScript SDK
Installation
npm install @stateset/sandbox-sdk
Basic Usage
import { StateSetSandbox } from "@stateset/sandbox-sdk";
const sandbox = new StateSetSandbox({
baseUrl: "https://api.sandbox.stateset.app",
authToken: "sk_sandbox_xxx",
timeout: 120000,
});
// Create sandbox
const instance = await sandbox.create({
cpus: "2",
memory: "4Gi",
timeout_seconds: 600,
});
// Write file
await sandbox.writeFile(
instance.sandbox_id,
"/workspace/app.py",
'print("Hello from Python!")'
);
// Execute command
const result = await sandbox.execute(instance.sandbox_id, {
command: "python3 /workspace/app.py",
});
console.log(result.stdout); // "Hello from Python!"
// Cleanup
await sandbox.stop(instance.sandbox_id);
Streaming Execution
await sandbox.executeStream(
instance.sandbox_id,
{ command: "npm install", stream: true },
{
onStdout: (data) => console.log("stdout:", data),
onStderr: (data) => console.error("stderr:", data),
onExit: (code) => console.log("exit code:", code),
}
);
Extended SDK (Advanced Features)
import { StateSetSandboxExtended } from "@stateset/sandbox-sdk";
const sdk = new StateSetSandboxExtended({
baseUrl: "https://api.sandbox.stateset.app",
authToken: "sk_sandbox_xxx",
});
// Create checkpoint
const checkpoint = await sdk.checkpoints.create(sandboxId, {
name: "baseline",
include_paths: ["/workspace"],
include_env: true,
});
// Restore from checkpoint
await sdk.checkpoints.restore(sandboxId, checkpoint.id);
// Upload artifact to cloud storage
const artifact = await sdk.artifacts.upload(sandboxId, {
path: "/workspace/report.pdf",
remote_path: "reports/2026/report.pdf",
});
// Start MCP server
const mcpServer = await sdk.startMCPServer(sandboxId, {
name: "postgres",
command: "npx",
args: ["@modelcontextprotocol/server-postgres"],
env: { DATABASE_URL: "postgresql://..." },
});
Python SDK
Installation
pip install stateset-sandbox
Basic Usage
from stateset_sandbox import StateSetSandbox
client = StateSetSandbox(
base_url="https://api.sandbox.stateset.app",
auth_token="sk_sandbox_xxx",
timeout=30000
)
# Context manager for automatic cleanup
with client.create(cpus="2", memory="4Gi") as sandbox:
# Write file
client.write_file(
sandbox.sandbox_id,
"/workspace/script.py",
"print('Hello from Python!')"
)
# Execute
result = client.execute(sandbox.sandbox_id, "python3 /workspace/script.py")
print(result.stdout)
# Sandbox automatically stopped on exit
Running Claude Code Agent
sandbox = client.create(cpus="4", memory="8Gi", timeout_seconds=1800)
result = client.execute(sandbox.sandbox_id, command=[
"claude",
"-p", "Create a REST API with Express.js that has CRUD endpoints for users",
"--allowedTools", "Write,Bash,Read,Edit"
])
print(result.stdout)
client.stop(sandbox.sandbox_id)
WebSocket API
Connect for real-time streaming:
const ws = new WebSocket('wss://api.sandbox.stateset.app/ws?token=YOUR_JWT');
// Execute with streaming
ws.send(JSON.stringify({
type: 'execute',
sandboxId: 'sandbox-xxx',
command: 'npm run build',
stream: true
}));
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'stdout': console.log(msg.data); break;
case 'stderr': console.error(msg.data); break;
case 'exit': console.log('Exit code:', msg.code); break;
case 'done': console.log('Complete'); break;
}
};
API Reference
Sandbox Lifecycle
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/create | Create new sandbox |
| GET | /api/v1/sandbox/:id | Get sandbox details |
| GET | /api/v1/sandbox/:id/status | Get sandbox status |
| GET | /api/v1/sandboxes | List all sandboxes |
| POST | /api/v1/sandbox/:id/stop | Stop sandbox |
| DELETE | /api/v1/sandbox/:id | Delete sandbox |
File Operations
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/files | Write files (base64) |
| GET | /api/v1/sandbox/:id/files?path=... | Read file (base64) |
| GET | /api/v1/sandbox/:id/files/download?path=... | Download file (binary) |
Command Execution
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/execute | Execute command |
Execute Request:
{
"command": "npm run build",
"working_dir": "/workspace",
"env": {"NODE_ENV": "production"},
"stream": false,
"timeout": 30000
}
Checkpoints
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/checkpoints | Create checkpoint |
| GET | /api/v1/sandbox/:id/checkpoints | List checkpoints |
| POST | /api/v1/sandbox/:id/checkpoints/:cpId/restore | Restore checkpoint |
| POST | /api/v1/sandbox/:id/checkpoints/:cpId/clone | Clone to new sandbox |
| DELETE | /api/v1/sandbox/:id/checkpoints/:cpId | Delete checkpoint |
Artifacts (Cloud Storage)
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/artifacts/upload | Upload to S3/GCS/Azure |
| POST | /api/v1/sandbox/:id/artifacts/download | Download from storage |
| GET | /api/v1/artifacts | List artifacts |
| GET | /api/v1/artifacts/:id/url | Get pre-signed URL |
| DELETE | /api/v1/artifacts/:id | Delete artifact |
MCP Servers
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/mcp/start | Start MCP server |
| POST | /api/v1/sandbox/:id/mcp/stop | Stop MCP server |
| GET | /api/v1/sandbox/:id/mcp/servers | List running servers |
| GET | /api/v1/sandbox/:id/mcp/presets | List available presets |
Agent Sessions
| Method | Endpoint | Description |
|---|
| POST | /api/v1/agent-sessions | Create agent session |
| GET | /api/v1/agent-sessions/:id | Get session details |
| POST | /api/v1/agent-sessions/:id/start | Start session |
| POST | /api/v1/agent-sessions/:id/exec | Execute in session |
| POST | /api/v1/agent-sessions/:id/pause | Pause session |
| POST | /api/v1/agent-sessions/:id/resume | Resume session |
| POST | /api/v1/agent-sessions/:id/stop | Stop session |
| GET | /api/v1/agent-sessions/:id/events | Get session events |
API Keys
| Method | Endpoint | Description |
|---|
| POST | /api/v1/api-keys | Create new API key |
| GET | /api/v1/api-keys | List API keys |
| DELETE | /api/v1/api-keys/:id | Revoke API key |
| POST | /api/v1/api-keys/:id/rotate | Rotate API key |
Webhooks
| Method | Endpoint | Description |
|---|
| POST | /api/v1/webhooks | Register webhook |
| GET | /api/v1/webhooks | List webhooks |
| PUT | /api/v1/webhooks/:id | Update webhook |
| DELETE | /api/v1/webhooks/:id | Delete webhook |
Tunnels (Port Forwarding)
| Method | Endpoint | Description |
|---|
| POST | /api/v1/sandbox/:id/tunnels | Create tunnel |
| GET | /api/v1/sandbox/:id/tunnels | List tunnels |
| DELETE | /api/v1/sandbox/:id/tunnels/:tunnelId | Delete tunnel |
Create Sandbox Options
| Field | Type | Default | Description |
|---|
cpus | string | "2" | CPU limit (“1”, “2”, “500m”) |
memory | string | "2Gi" | Memory limit (“1Gi”, “2Gi”, “512Mi”) |
timeout_seconds | number | 600 | Sandbox lifetime (60-86400) |
env | object | {} | Environment variables |
isolation | string | "container" | Isolation level: container, gvisor, microvm |
gpu.count | number | - | GPU count (1-8) |
gpu.type | string | - | GPU type (“nvidia.com/gpu”) |
gpu.memory_gb | number | - | GPU memory (1-256) |
Agent Sessions
Long-running agent sessions with automatic sandbox rotation:
// Create session with budget controls
const session = await sdk.sessions.create({
name: "code-review-agent",
budget: {
cost_cap_cents: 1000,
iteration_limit: 50,
duration_limit_seconds: 3600,
},
sandbox: {
cpus: "4",
memory: "8Gi",
timeout_seconds: 600,
},
rotation: {
pre_rotate_buffer_seconds: 60,
include_process_state: true,
},
});
// Start session
await sdk.sessions.start(session.id);
// Execute commands (auto-rotates sandbox as needed)
const result = await sdk.sessions.exec(session.id, {
command: "claude -p 'Review the codebase' --allowedTools Write,Bash,Read",
});
// Get session events
const events = await sdk.sessions.getEvents(session.id);
// Stop when done
await sdk.sessions.stop(session.id);
Session States:
pending - Created, not started
running - Active execution
rotating - Sandbox rotation in progress
paused - Temporarily suspended
completed - Successfully finished
failed - Error occurred
cancelled - Manually stopped
MCP Server Integration
Start Model Context Protocol servers inside sandboxes:
// Start filesystem MCP server
await sdk.startMCPServer(sandboxId, {
name: "filesystem",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
port: 3000,
});
// Start PostgreSQL MCP server
await sdk.startMCPServer(sandboxId, {
name: "postgres",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-postgres"],
env: {
DATABASE_URL: "postgresql://user:pass@host/db",
},
port: 3001,
});
// List running servers
const servers = await sdk.listMCPServers(sandboxId);
// Stop server
await sdk.stopMCPServer(sandboxId, "postgres");
Built-in MCP Presets:
filesystem - File operations
github - GitHub repository access
postgres - PostgreSQL queries
slack - Slack messaging
brave-search - Web search
puppeteer - Browser automation
Checkpoints
Save and restore sandbox state:
// Create checkpoint
const checkpoint = await sdk.checkpoints.create(sandboxId, {
name: "after-setup",
description: "Initial project setup complete",
include_paths: ["/workspace"],
exclude_paths: ["/workspace/node_modules"],
include_env: true,
});
// List checkpoints
const checkpoints = await sdk.checkpoints.list(sandboxId);
// Restore to checkpoint
await sdk.checkpoints.restore(sandboxId, checkpointId);
// Clone checkpoint to new sandbox
const newSandbox = await sdk.checkpoints.clone(sandboxId, checkpointId);
// Compare two checkpoints
const diff = await sdk.checkpoints.compare(sandboxId, checkpointId1, checkpointId2);
Webhooks
Subscribe to sandbox events:
const webhook = await sdk.webhooks.create({
url: "https://your-app.com/webhooks/sandbox",
events: [
"sandbox.created",
"sandbox.ready",
"sandbox.stopped",
"command.completed",
"checkpoint.created",
],
secret: "whsec_your_webhook_secret",
});
Webhook Events:
sandbox.created, sandbox.ready, sandbox.stopped, sandbox.error, sandbox.timeout
command.started, command.completed, command.failed
file.written, artifact.uploaded, artifact.deleted
checkpoint.created, checkpoint.restored, checkpoint.deleted
mcp.started, mcp.stopped
resource.warning, resource.critical
security.alert
Configuration
Environment Variables
| Variable | Default | Description |
|---|
SANDBOX_IMAGE | - | Docker image for sandbox pods |
DEFAULT_CPUS | "2" | Default CPU limit |
DEFAULT_MEMORY | "2Gi" | Default memory limit |
DEFAULT_TIMEOUT | 600 | Default timeout (seconds) |
MAX_SANDBOXES_PER_ORG | 5 | Max concurrent sandboxes |
WARM_POOL_ENABLED | false | Enable warm pod pool |
WARM_POOL_SIZE | 5 | Warm pool size |
SANDBOX_EXEC_BACKEND | kubectl | Exec backend: kubectl or k8s |
Self-Hosted Deployment
Prerequisites
- Kubernetes cluster (1.24+)
- kubectl configured
- PostgreSQL database
- Redis (optional, for warm pools)
Deploy
# Clone repository
git clone https://github.com/stateset/stateset-sandbox
cd stateset-sandbox
# Apply Kubernetes manifests
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/rbac.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/deployment.yaml
# Verify deployment
kubectl get pods -n stateset-sandbox
kubectl create secret generic sandbox-secrets -n stateset-sandbox \
--from-literal=JWT_SECRET=your-jwt-secret \
--from-literal=DATABASE_URL=postgresql://user:pass@host/db \
--from-literal=REDIS_URL=redis://host:6379
Security
Container Isolation
- Non-root user: Runs as UID 1001
- Dropped capabilities: ALL capabilities dropped
- Seccomp profile: Enabled by default
- Read-only filesystem: Only /workspace is writable
- Resource limits: CPU, memory, ephemeral storage enforced
Network Isolation
- Egress allowed: HTTPS (443), DNS (53)
- Private ranges blocked: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
- Network policies: Restrictive by default
Authentication
- API Keys: Revocable, organization-scoped
- JWTs: Signed with secret, expiring tokens
- Rate limiting: Per-organization limits
Each sandbox includes:
| Category | Tools |
|---|
| Languages | Node.js 20, Python 3.11, Go 1.21, Rust 1.75 |
| Package Managers | npm, yarn, pnpm, pip, cargo |
| Version Control | git, gh (GitHub CLI) |
| Build Tools | make, cmake, gcc, g++ |
| Utilities | curl, wget, jq, ripgrep, fd |
| Containers | Docker CLI (socket mount optional) |
Quick Reference
CLI Commands (curl)
# Register
curl -X POST https://api.sandbox.stateset.app/api/v1/register \
-H "Content-Type: application/json" \
-d '{"first_name":"...", "last_name":"...", "organization_name":"...", "email":"..."}'
# Create sandbox
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/create \
-H "Authorization: ApiKey KEY" \
-H "Content-Type: application/json" \
-d '{"timeout_seconds": 300}'
# Execute command
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/ID/execute \
-H "Authorization: ApiKey KEY" \
-H "Content-Type: application/json" \
-d '{"command": "echo hello"}'
# Write file
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/ID/files \
-H "Authorization: ApiKey KEY" \
-H "Content-Type: application/json" \
-d '{"files": [{"path": "/workspace/file.txt", "content": "BASE64_CONTENT"}]}'
# Read file
curl "https://api.sandbox.stateset.app/api/v1/sandbox/ID/files?path=/workspace/file.txt" \
-H "Authorization: ApiKey KEY"
# Stop sandbox
curl -X POST https://api.sandbox.stateset.app/api/v1/sandbox/ID/stop \
-H "Authorization: ApiKey KEY"
# List sandboxes
curl https://api.sandbox.stateset.app/api/v1/sandboxes \
-H "Authorization: ApiKey KEY"
SDK Quick Reference
// TypeScript
const sandbox = new StateSetSandbox({ baseUrl, authToken });
await sandbox.create({ cpus, memory, timeout_seconds });
await sandbox.writeFile(id, path, content);
await sandbox.execute(id, { command });
await sandbox.readFile(id, path);
await sandbox.stop(id);
# Python
client = StateSetSandbox(base_url, auth_token)
sandbox = client.create(cpus="2", memory="4Gi")
client.write_file(sandbox.sandbox_id, path, content)
result = client.execute(sandbox.sandbox_id, command)
content = client.read_file(sandbox.sandbox_id, path)
client.stop(sandbox.sandbox_id)
Ideas to Try
- Register and create your first sandbox
- Run a Claude Code agent to generate and test code
- Set up checkpoints to save and restore work
- Use MCP servers for database or GitHub integration
- Create agent sessions for long-running tasks
- Set up webhooks for real-time notifications
- Deploy self-hosted with warm pools for fast startup
- Use GPU sandboxes for ML workloads
StateSet Sandbox v0.4.0
January 2026