Production Guide
Deploy, secure, and operate StateSet Sandbox.
StateSet Sandbox - Production Guide
Overview
StateSet Sandbox is a secure, isolated execution environment for running code on behalf of AI agents. It provides containerized sandboxes with full lifecycle management, checkpointing, artifact storage, and usage tracking.
Architecture
┌─────────────────────────────────────────────────────────────────────────┐
│ DEVELOPER │
└─────────────────────────────────────────────────────────────────────────┘
│ │ │
│ 1. Register │ 2. Use SDK │ 3. Dashboard
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ SANDBOX CONTROLLER │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Registration │ │ Sandbox │ │ Checkpoint │ │ Webhook │ │
│ │ Service │ │ Manager │ │ Manager │ │ Manager │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬──────┘ │
└─────────┼─────────────────┼─────────────────┼─────────────────┼─────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐
│ PostgreSQL │ │ Kubernetes │ │ Cloud │ │ External │
│ (Managed DB) │ │ (Pods) │ │ Storage │ │ Webhooks │
│ │ │ │ │ (GCS/S3) │ │ │
│ • organizations │ │ • sandbox │ │ • artifacts │ │ • your-app.com │
│ • api_keys │ │ pods │ │ • checkpts │ │ │
│ • usage_events │ │ │ │ │ │ │
│ • checkpoints │ │ │ │ │ │ │
└─────────────────┘ └─────────────┘ └─────────────┘ └─────────────────┘Component Details
| Component | Technology | Purpose |
|---|---|---|
| Controller | Node.js + Express | API server, orchestration |
| Database | PostgreSQL (managed) | Persistent storage |
| Sandboxes | Kubernetes Pods | Isolated execution |
| Storage | GCS/S3 | Artifact & checkpoint files |
| Dashboard | Next.js 14 | Web UI for management |
| SDK | TypeScript | Client library |
User Flow
1. Registration
Developer signs up via API or dashboard:
curl -X POST https://api.sandbox.stateset.app/api/v1/register \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ada",
"last_name": "Lovelace",
"email": "dev@company.com",
"organization_name": "Acme Corp",
"use_case": "CI automation"
}'**Response:**
{
"organization": {
"id": "org_abc123",
"name": "Acme Corp",
"slug": "acme-corp",
"plan": "hobby"
},
"user": {
"id": "user_abc123",
"email": "dev@company.com",
"role": "owner"
},
"api_key": {
"key": "sk-sandbox-xxxxxxxxxxxxxxxxxxxx",
"key_prefix": "sk-sandbox-xxxx",
"name": "Default API Key"
}
}2. SDK Installation
Node.js:
npm install @stateset/sandbox-sdkPython:
pip install stateset-sandboxAdditional preview SDKs are available in this repo:
- Rust:
sdk-rust/README.md - Ruby:
sdk-ruby/README.md - Go:
sdk-go/README.md - PHP:
sdk-php/README.md - Java:
sdk-java/README.md - Kotlin:
sdk-kotlin/README.md - Swift:
sdk-swift/README.md
3. Basic Usage
import { StateSetSandbox } from '@stateset/sandbox-sdk';
// Initialize client
const client = new StateSetSandbox({
baseUrl: 'https://api.sandbox.stateset.app',
authToken: 'sk-sandbox-xxxxxxxxxxxx'
});
// Create a sandbox
const sandbox = await client.create({
timeout_seconds: 300, // 5 minutes
cpus: '1', // 1 vCPU
memory: '1Gi', // 1GB RAM
env: {
NODE_ENV: 'production'
}
});
console.log(`Sandbox created: ${sandbox.sandbox_id}`);
console.log(`Expires at: ${sandbox.expires_at}`);
// Execute commands
const result = await client.execute(sandbox.sandbox_id, {
command: ['node', '-e', 'console.log("Hello from sandbox!")']
});
console.log(result.stdout); // "Hello from sandbox!"
console.log(result.exit_code); // 0
// Write files
await client.writeFiles(sandbox.sandbox_id, [
{ path: '/workspace/app.js', content: 'console.log("app");' }
]);
// Read files
const content = await client.readFile(sandbox.sandbox_id, '/workspace/app.js');
// Stop sandbox when done
await client.stop(sandbox.sandbox_id);Advanced endpoints (checkpoints, artifacts, webhooks, templates) are available via StateSetSandboxExtended:
import { StateSetSandboxExtended } from '@stateset/sandbox-sdk';
const client = new StateSetSandboxExtended({
baseUrl: 'https://api.sandbox.stateset.app',
authToken: 'sk-sandbox-xxxxxxxxxxxx'
});4. Advanced: Checkpoints
Save and restore sandbox state:
// Save current state
const checkpoint = await client.createCheckpoint(sandbox.sandbox_id, {
name: 'after-npm-install',
description: 'All dependencies installed'
});
console.log(`Checkpoint created: ${checkpoint.id}`);
// Later: Restore to that state (same sandbox)
await client.restoreCheckpoint(sandbox.sandbox_id, checkpoint.id, {
restore_files: true,
restore_env: true,
overwrite: true
});
// Clone a checkpoint
const cloned = await client.cloneCheckpoint(checkpoint.id, 'feature-branch-base');
// Compare checkpoints
const diff = await client.compareCheckpoints(
checkpoint1.id,
checkpoint2.id
);5. Advanced: Artifacts
Upload and download files:
// Upload file from sandbox to cloud storage
const artifact = await client.uploadArtifact(sandbox.sandbox_id, {
path: '/workspace/output/report.pdf',
remote_path: 'reports/2024/report.pdf', // stored under artifacts/<organization-id>/...
content_type: 'application/pdf',
expires_in: 86400 * 7 // 7 days
});
// Download artifact to sandbox
await client.downloadArtifact(
sandbox.sandbox_id,
artifact.id,
'/workspace/downloads/report.pdf'
);
// Get presigned URL for direct download
const { url } = await client.getArtifactUrl(artifact.id, 3600);
console.log(`Artifact URL: ${url}`);6. Advanced: Webhooks
Get notified of sandbox events:
// Register webhook
const webhook = await client.createWebhook({
url: 'https://your-app.com/webhooks/sandbox',
events: [
'sandbox.created',
'sandbox.ready',
'sandbox.error',
'sandbox.stopped',
'command.completed',
'checkpoint.created'
],
secret: 'whsec_your_secret_key'
});
// Test webhook
const testResult = await client.testWebhook(webhook.id);
console.log(`Test successful: ${testResult.success}`);
// List webhook deliveries
const deliveries = await client.getWebhookDeliveries(webhook.id, 10);**Webhook Payload:**
{
"id": "evt_abc123",
"event": "sandbox.ready",
"timestamp": "2024-01-15T12:00:00Z",
"sandboxId": "sbx_xyz789",
"orgId": "org_abc123",
"data": {
"podIp": "10.0.1.5",
"startupMs": 1234
}
}**Signature Verification:**
import { createHmac } from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string): boolean {
const expected = createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expected}` === signature;
}7. Templates
Create sandboxes from pre-configured templates:
// List available templates
const templates = await client.listTemplates();
// Create from template
const sandbox = await client.createFromTemplate('python-data-science', {
timeout_seconds: 600,
env: {
DATASET_URL: 'https://example.com/data.csv'
}
});**Available Templates:**
| Template | Description | Pre-installed |
|---|---|---|
python-basic | Python 3.11 | pip, venv |
node-basic | Node.js 22 | npm, yarn |
go-basic | Go 1.22 | go mod |
rust-basic | Rust stable | cargo |
python-data-science | Data analysis | pandas, numpy, matplotlib |
node-express-api | Web APIs | express, typescript |
claude-agent | AI agents | claude-code, MCP servers |
API Reference
Authentication
All API requests require authentication via header:
Authorization: ApiKey sk-sandbox-xxxxxxxxxxxxThe organization is inferred from the API key or JWT claims; no org header is required.
Or with JWT:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Endpoints
Registration & API Keys
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/register | Create organization + API key |
| GET | /api/v1/api-keys | List API keys |
| POST | /api/v1/api-keys | Create new API key |
| DELETE | /api/v1/api-keys/:id | Revoke API key |
Sandboxes
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/sandbox/create | Create sandbox |
| GET | /api/v1/sandbox/:id | Get sandbox details |
| GET | /api/v1/sandbox/:id/status | Get sandbox status (lightweight) |
| POST | /api/v1/sandbox/:id/execute | Execute command |
| POST | /api/v1/sandbox/:id/files | Write files |
| GET | /api/v1/sandbox/:id/files?path=... | Read file |
| POST | /api/v1/sandbox/:id/stop | Stop sandbox |
| DELETE | /api/v1/sandbox/:id | Delete sandbox |
| GET | /api/v1/sandboxes | List sandboxes |
Checkpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/checkpoints | List checkpoints |
| GET | /api/v1/checkpoints/:id | Get checkpoint |
| POST | /api/v1/sandbox/:id/checkpoints | Create checkpoint |
| POST | /api/v1/sandbox/:id/checkpoints/restore | Restore checkpoint |
| POST | /api/v1/checkpoints/:id/clone | Clone checkpoint |
| POST | /api/v1/checkpoints/compare | Compare checkpoints |
| DELETE | /api/v1/checkpoints/:id | Delete checkpoint |
Artifacts
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/artifacts | List artifacts |
| GET | /api/v1/artifacts/:id | Get artifact details |
| GET | /api/v1/artifacts/:id/url | Get presigned URL |
| POST | /api/v1/sandbox/:id/artifacts/upload | Upload artifact |
| POST | /api/v1/sandbox/:id/artifacts/download | Download artifact |
| DELETE | /api/v1/artifacts/:id | Delete artifact |
Webhooks
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/webhooks | List webhooks |
| POST | /api/v1/webhooks | Create webhook |
| DELETE | /api/v1/webhooks/:id | Delete webhook |
| POST | /api/v1/webhooks/:id/test | Test webhook |
| GET | /api/v1/webhooks/:id/deliveries | Get delivery history |
Webhook Events
| Event | Description |
|---|---|
sandbox.created | Sandbox pod created |
sandbox.ready | Sandbox is ready for commands |
sandbox.stopped | Sandbox stopped |
sandbox.error | Sandbox encountered error |
sandbox.timeout | Sandbox timed out |
command.started | Command execution started |
command.completed | Command finished successfully |
command.failed | Command failed |
file.written | File written to sandbox |
checkpoint.created | Checkpoint created |
checkpoint.restored | Checkpoint restored |
checkpoint.cloned | Checkpoint cloned |
checkpoint.deleted | Checkpoint deleted |
artifact.uploaded | Artifact uploaded |
artifact.deleted | Artifact deleted |
resource.warning | Resource usage warning |
resource.critical | Resource usage critical |
mcp.started | MCP server started |
mcp.stopped | MCP server stopped |
Pricing
Plans
| Plan | Price | Sandboxes/Month | Concurrent | Max Duration | Storage |
|---|---|---|---|---|---|
| Free | $0 | 50 | 2 | 5 min | 1 GB |
| Pro | $49/mo | 1,000 | 10 | 1 hour | 50 GB |
| Team | $299/mo | 10,000 | 50 | 2 hours | 500 GB |
| Enterprise | Custom | Unlimited | Custom | Custom | Custom |
Usage-Based Pricing
| Resource | Rate |
|---|---|
| CPU | $0.05 / vCPU-hour |
| Memory | $0.02 / GB-hour |
| Network | $0.10 / GB egress |
| Storage | $0.20 / GB-month |
Dashboard
Access at: https://sandbox.stateset.app/dashboard
Pages
| Page | Path | Description |
|---|---|---|
| Overview | /dashboard | Active sandboxes, metrics |
| Sandboxes | /dashboard/sandboxes | List and manage sandboxes |
| API Keys | /dashboard/api-keys | Create/revoke keys |
| Checkpoints | /dashboard/checkpoints | Manage checkpoints |
| Artifacts | /dashboard/artifacts | File storage |
| Webhooks | /dashboard/webhooks | Event notifications |
| Audit Logs | /dashboard/audit-logs | Activity history |
| Usage | /dashboard/usage | Usage and billing |
| Settings | /dashboard/settings | Organization settings |
Security
API Key Security
- Keys are hashed (SHA-256) before storage
- Original key shown only once at creation
- Keys can have scopes and expiration
- Rate limiting per key
Sandbox Isolation
- Each sandbox runs in isolated Kubernetes pod
- Network policies restrict pod communication
- Resource limits enforced (CPU, memory)
- Read-only root filesystem
- Non-root user execution
Data Protection
- All data encrypted in transit (TLS)
- Database encrypted at rest
- Secrets stored encrypted with KMS
- Audit logging for compliance
Logs
# Controller logs
kubectl logs -n your-namespace -l app=sandbox-controller -c controller
# Database proxy logs
kubectl logs -n your-namespace -l app=sandbox-controller -c db-proxy
# Sandbox pod logs
kubectl logs -n your-namespace <sandbox-pod-name>Support
- GitHub Issues: https://github.com/stateset/sandbox/issues
- Documentation: https://docs.stateset.io/sandbox
- Email: support@stateset.io