Skip to main content

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

FileURL
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

ServiceBase URLPurpose
Sandbox APIhttps://api.sandbox.stateset.app/api/v1Sandbox management, execution, files
WebSocketwss://api.sandbox.stateset.app/wsReal-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": "[email protected]"
  }'
Response:
{
  "success": true,
  "user": {
    "id": "user_xxx",
    "email": "[email protected]"
  },
  "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

MethodEndpointDescription
POST/api/v1/sandbox/createCreate new sandbox
GET/api/v1/sandbox/:idGet sandbox details
GET/api/v1/sandbox/:id/statusGet sandbox status
GET/api/v1/sandboxesList all sandboxes
POST/api/v1/sandbox/:id/stopStop sandbox
DELETE/api/v1/sandbox/:idDelete sandbox

File Operations

MethodEndpointDescription
POST/api/v1/sandbox/:id/filesWrite 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

MethodEndpointDescription
POST/api/v1/sandbox/:id/executeExecute command
Execute Request:
{
  "command": "npm run build",
  "working_dir": "/workspace",
  "env": {"NODE_ENV": "production"},
  "stream": false,
  "timeout": 30000
}

Checkpoints

MethodEndpointDescription
POST/api/v1/sandbox/:id/checkpointsCreate checkpoint
GET/api/v1/sandbox/:id/checkpointsList checkpoints
POST/api/v1/sandbox/:id/checkpoints/:cpId/restoreRestore checkpoint
POST/api/v1/sandbox/:id/checkpoints/:cpId/cloneClone to new sandbox
DELETE/api/v1/sandbox/:id/checkpoints/:cpIdDelete checkpoint

Artifacts (Cloud Storage)

MethodEndpointDescription
POST/api/v1/sandbox/:id/artifacts/uploadUpload to S3/GCS/Azure
POST/api/v1/sandbox/:id/artifacts/downloadDownload from storage
GET/api/v1/artifactsList artifacts
GET/api/v1/artifacts/:id/urlGet pre-signed URL
DELETE/api/v1/artifacts/:idDelete artifact

MCP Servers

MethodEndpointDescription
POST/api/v1/sandbox/:id/mcp/startStart MCP server
POST/api/v1/sandbox/:id/mcp/stopStop MCP server
GET/api/v1/sandbox/:id/mcp/serversList running servers
GET/api/v1/sandbox/:id/mcp/presetsList available presets

Agent Sessions

MethodEndpointDescription
POST/api/v1/agent-sessionsCreate agent session
GET/api/v1/agent-sessions/:idGet session details
POST/api/v1/agent-sessions/:id/startStart session
POST/api/v1/agent-sessions/:id/execExecute in session
POST/api/v1/agent-sessions/:id/pausePause session
POST/api/v1/agent-sessions/:id/resumeResume session
POST/api/v1/agent-sessions/:id/stopStop session
GET/api/v1/agent-sessions/:id/eventsGet session events

API Keys

MethodEndpointDescription
POST/api/v1/api-keysCreate new API key
GET/api/v1/api-keysList API keys
DELETE/api/v1/api-keys/:idRevoke API key
POST/api/v1/api-keys/:id/rotateRotate API key

Webhooks

MethodEndpointDescription
POST/api/v1/webhooksRegister webhook
GET/api/v1/webhooksList webhooks
PUT/api/v1/webhooks/:idUpdate webhook
DELETE/api/v1/webhooks/:idDelete webhook

Tunnels (Port Forwarding)

MethodEndpointDescription
POST/api/v1/sandbox/:id/tunnelsCreate tunnel
GET/api/v1/sandbox/:id/tunnelsList tunnels
DELETE/api/v1/sandbox/:id/tunnels/:tunnelIdDelete tunnel

Create Sandbox Options

FieldTypeDefaultDescription
cpusstring"2"CPU limit (“1”, “2”, “500m”)
memorystring"2Gi"Memory limit (“1Gi”, “2Gi”, “512Mi”)
timeout_secondsnumber600Sandbox lifetime (60-86400)
envobject{}Environment variables
isolationstring"container"Isolation level: container, gvisor, microvm
gpu.countnumber-GPU count (1-8)
gpu.typestring-GPU type (“nvidia.com/gpu”)
gpu.memory_gbnumber-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

VariableDefaultDescription
SANDBOX_IMAGE-Docker image for sandbox pods
DEFAULT_CPUS"2"Default CPU limit
DEFAULT_MEMORY"2Gi"Default memory limit
DEFAULT_TIMEOUT600Default timeout (seconds)
MAX_SANDBOXES_PER_ORG5Max concurrent sandboxes
WARM_POOL_ENABLEDfalseEnable warm pod pool
WARM_POOL_SIZE5Warm pool size
SANDBOX_EXEC_BACKENDkubectlExec 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

Configure Secrets

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

Preinstalled Tools

Each sandbox includes:
CategoryTools
LanguagesNode.js 20, Python 3.11, Go 1.21, Rust 1.75
Package Managersnpm, yarn, pnpm, pip, cargo
Version Controlgit, gh (GitHub CLI)
Build Toolsmake, cmake, gcc, g++
Utilitiescurl, wget, jq, ripgrep, fd
ContainersDocker 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