What is Sandbox?
This is a env where developers/AI agents can create isolated execution environments, execute commands, and connect to them through APIs/WebSockets
Requirements
1. Sandbox configurable with different CPU, memory, disk, network, and
runtime/image; each sandbox must be strongly isolated from other
tenants and the host.
2. Clients can execute commands, stream stdout/stderr, inspect process
status, upload/download files, and maintain interactive terminal
sessions over REST APIs and WebSockets
3. Horizontally scalable sandbox
High Level Design
flowchart LR
Client["Developer / AI Agent"]
GLB["Global LB"]
subgraph Regions["Global Infrastructure"]
RLB["Regional LB - Region 1"]
RLB1["Regional LB - Region 2"]
end
subgraph AWS["AWS Region / Datacenter"]
%% =========================
%% CONTROL PLANE
%% =========================
subgraph CP["CONTROL PLANE (Sandbox creation, billing, auth)"]
direction TB
API["API Gateway
REST + WebSocket"]
Auth["Auth + Rate Limiter"]
SandboxAPI["Sandbox Control Service"]
Queue["Sandbox Job Queue
Kafka/RabitMQ"]
Scheduler["Scheduler
(See Below)"]
DB[("Metadata DB")]
Cache[("Redis / Session Store")]
API --> Auth
Auth --> SandboxAPI
SandboxAPI --> DB
SandboxAPI --> Cache
SandboxAPI --> Queue
Queue --> Scheduler
Scheduler --> DB
end
%% =========================
%% DATA PLANE
%% =========================
subgraph DP["DATA PLANE "]
direction TB
Router["Sandbox / Session Router"]
subgraph Compute["Sandbox Compute Cluster"]
direction LR
Worker1["Worker Node 1
Worker Agent"]
Worker2["Worker Node 2
Worker Agent"]
WorkerN["Worker Node N
Worker Agent"]
Runtime1["Sandbox Runtime 1
Container / MicroVM"]
Runtime2["Sandbox Runtime 2
Container / MicroVM"]
RuntimeN["Sandbox Runtime N
Container / MicroVM"]
Worker1 --> Runtime1
Worker2 --> Runtime2
WorkerN --> RuntimeN
end
ObjectStore[("Object Storage
Files / Artifacts")]
Router --> Worker1
Router --> Worker2
Router --> WorkerN
Runtime1 --> ObjectStore
Runtime2 --> ObjectStore
RuntimeN --> ObjectStore
end
end
%% =========================
%% GLOBAL ROUTING
%% =========================
Client --> GLB
GLB --> RLB
GLB --> RLB1
RLB --> API
%% =========================
%% CONTROL PLANE
%% =========================
Scheduler --> Worker1
Scheduler --> Worker2
Scheduler --> WorkerN
%% =========================
%% DATA PLANE
%% =========================
API -. "WebSocket
terminal / streaming I/O" .-> Router
Router -. "Interactive I/O" .-> Runtime1
Router -. "Interactive I/O" .-> Runtime2
Router -. "Interactive I/O" .-> RuntimeN
| Component | Role |
|---|---|
| Scheduler |
Why not place Worker directly at end of Kafka? Kafka directly gives jobs to workers(consumer groups), does not understand which worker has how much capacity We can assign capacity to workers and scheduler can understand and route accordingly
|
Seqeunce Diagram
Whole architecture is divided into 2 planes
Control plane (Sandbox creation, billing, auth)
Responsible for: create sandbox, delete sandbox, authentication, quotas, scheduling, billing, metadata, lifecycle, worker health
Data Plane (Actual user commands)
Run code, stdin stdout stderr, file operations, terminal sessions, network traffic
sequenceDiagram
autonumber
actor C as Developer / AI Agent
box Control Plane
participant API as API Gateway
participant S as Sandbox Service
participant Q as Sandbox Job Queue
participant SCH as Scheduler
participant DB as Metadata DB
end
box Data Plane
participant W as Worker Agent
participant R as Sandbox Runtime
participant P as User Process
end
box Data Plane Routing
participant SR as Sandbox / Session Router
end
%% =========================================
%% CREATE SANDBOX - CONTROL PLANE
%% =========================================
Note over C: CREATE SANDBOX - Control Plane
C->>API: POST /v1/sandboxes
Note right of C:
{
image: python:3.12,
cpu: 2,
memory_mb: 4096,
disk_gb: 20,
ttl_seconds: 3600}
API->>S: Create sandbox request
S->>DB: Create sandbox record
status = CREATING
S->>Q: Enqueue CREATE_SANDBOX job
Note over Q,SCH: Durable job waiting for capacity
Q->>SCH: Consume sandbox job
SCH->>DB: Find suitable worker
DB-->>SCH: Worker Node 17 available
SCH->>W: Deploy sandbox
sandbox_id + resource requirements
%% =========================================
%% SANDBOX CREATION - DATA PLANE
%% =========================================
Note over W,R: Sandbox creation - Data Plane
W->>R: Create isolated runtime
R->>R: Allocate CPU / RAM / Disk
R->>R: Boot Container / MicroVM
R->>R: Start sandbox-agent
R-->>W: READY
runtime_id + endpoint
W->>S: Sandbox READY
S->>DB: Update status = READY
worker_id + runtime_id
S-->>API: Sandbox details
API-->>C: 201 Created
sandbox_id + status=READY
%% =========================================
%% INTERACTIVE EXECUTION - DATA PLANE
%% =========================================
Note over C,SR: EXECUTION - Data Plane
C->>API: WebSocket /v1/sandboxes/{id}/terminal
API->>SR: Establish session for sandbox_id
SR->>DB: Resolve sandbox → worker/runtime
DB-->>SR: worker-17 / runtime-42
SR->>R: Establish terminal session
R-->>SR: Session established
SR-->>API: WebSocket connected
API-->>C: WebSocket connected
%% =========================================
%% COMMAND / TERMINAL I/O
%% =========================================
C->>API: stdin: "python\n"
API->>SR: Forward stdin
SR->>R: stdin
R->>P: Start Python process
P-->>R: stdout: "Python 3.12..."
R-->>SR: stdout
SR-->>API: stdout
API-->>C: Stream stdout
C->>API: stdin: "print(2 + 3)\n"
API->>SR: Forward stdin
SR->>R: stdin
R->>P: Execute command
P-->>R: stdout: "5\n"
R-->>SR: stdout
SR-->>API: stdout
API-->>C: Stream output
%% =========================================
%% CLOSE SESSION
%% =========================================
C->>API: Close WebSocket
API->>SR: Close terminal session
SR->>R: Close PTY/session
R-->>SR: Session closed
%% =========================================
%% DELETE SANDBOX - CONTROL PLANE
%% =========================================
Note over C,API: DELETE SANDBOX - Control Plane
C->>API: DELETE /v1/sandboxes/{id}
API->>S: Delete sandbox request
S->>DB: status = TERMINATING
S->>Q: Enqueue DELETE_SANDBOX job
Q->>SCH: Consume cleanup job
SCH->>W: Destroy sandbox
%% =========================================
%% DESTROY - DATA PLANE
%% =========================================
W->>R: Destroy runtime
R->>P: Terminate processes
R-->>W: Resources released
W->>S: Sandbox destroyed
S->>DB: status = TERMINATED
S-->>API: Cleanup complete
API-->>C: 204 No Content