VM0 is a platform for running AI agent workflows in isolated sandbox environments. The platform consists of three core subsystems:
- Compute: Sandbox execution (E2B or Firecracker microVMs)
- Storage: User data persistence (Cloudflare R2)
- Orchestration: Job queue and runner coordination (PostgreSQL)
Execution Flow:
User CLI/API Request
↓
Web API (Next.js)
↓
Executor Selection (E2B or Runner)
↓
Compute Layer (Sandbox)
↓ (downloads from)
Storage Layer (R2)
↓ (reports via webhooks)
Web API
↓
User receives results
The compute layer executes agent workflows in isolated sandbox environments.
1. E2B (Default)
- Third-party managed sandbox service (e2b.dev)
- Container-based isolation
- Template system for environment configuration
- 2-hour timeout (production), 1-hour (development)
- Fire-and-forget execution with webhook callbacks
2. Firecracker (Experimental)
- Self-hosted microVMs on bare metal Linux
- Hardware-level isolation via KVM
- 3-5 second boot time
- Network namespace isolation per VM
- Requires runner infrastructure
if experimental_runner.group specified:
→ Queue job in runner_job_queue
→ Firecracker runner polls and executes
else:
→ Execute immediately via E2B
The storage layer persists user data (volumes, artifacts, session state) in Cloudflare R2.
Volumes: Read-only data mounted at specified paths
- Examples: Code repositories, dependencies, reference data
- Defined in
vm0.yaml
Artifacts: Read-write working directory
- Agent output, modified files, generated assets
- Versioned after each run
- Used for checkpoints and resume
Upload:
CLI → tar.gz archive → presigned PUT URL → R2
Database records: storage_id, version_id, s3_key
Download:
Server → presigned GET URL (1h expiration)
↓
Storage manifest JSON → Sandbox
↓
Sandbox downloads directly from R2 (no API proxy)
↓
Extracts to mount paths
The orchestration layer coordinates job execution between web API and runners.
Job Notification:
- Push: Ably realtime notifications for instant job pickup (~100-200ms)
- Fallback: Polling every 30s catches missed notifications
Runner Behavior:
- Subscribe to Ably channel
runner-group:{scope}/{name} - Receive job notification:
{ runId } - Claim job atomically via
/api/runners/jobs/{id}/claim(setsclaimed_at) - Execute in Firecracker VM
- Report completion via webhook
- Job deleted from queue
Format: {scope}/{name}
- Official:
vm0/*(e.g.,vm0/production) - VM0-managed runners - User:
{userid}/*(e.g.,user123/private) - Self-hosted runners
Authentication:
- Official runners: HMAC signature using
OFFICIAL_RUNNER_SECRET - User runners: JWT bearer token with userId claim
E2B (e2b.dev) is a third-party managed sandbox service that provides containerized execution environments.
- SDK:
@e2b/code-interpreter - Template: Specified via
agent.imageinvm0.yaml(defaults tovm0/claude-code) - Authentication:
E2B_API_KEY
- Create sandbox with environment variables
- Upload Python/Node.js scripts via tar bundle
- Download storages from R2 via presigned URLs
- Restore session history (for resume)
- Start agent CLI in background (nohup)
- Webhook reports progress and completion
Firecracker is an open-source VMM (Virtual Machine Monitor) developed by AWS that creates lightweight microVMs using Linux KVM.
Hardware:
- Bare metal Linux server
- KVM support:
/dev/kvmdevice - Cannot run on cloud VMs (nested virtualization limitations)
Software:
- Firecracker v1.10.1 binary
- Linux kernel v6.1.102 (for microVM)
- Node.js 24.x, pnpm, pm2
- mitmproxy (network observability)
- Docker (rootfs build only)
Runner Application: Separate Node.js application in turbo/apps/runner/
VM Configuration:
# runner.yaml
firecracker:
binary: /usr/local/bin/firecracker
kernel: /opt/firecracker/vmlinux
rootfs: /opt/firecracker/rootfs.squashfs
sandbox:
vcpu: 2
memory_mb: 2048
max_concurrent: 1Shared Read-Only Base:
- Squashfs rootfs (~500MB-1GB compressed)
- Location:
/opt/firecracker/rootfs.squashfs - Shared across all VMs
- Built from Dockerfile via
build-rootfs.sh
Per-VM Writable Overlay:
- Sparse ext4 (2GB, allocates on write)
- Location:
/tmp/vm0-vm-{vmId}/overlay.ext4 - Combined with base via overlayfs (custom init script)
- Enables instant boot without rootfs copy
Isolation: Each VM in separate network namespace
TAP Device: One per VM
- Name:
vm0tap{vmId}(e.g.,vm0tap12345678) - Layer 2 Ethernet virtualization
- Bridges host and guest
IP Allocation: 172.16.x.x/30 subnets
- Host IP: .1 (e.g., 172.16.161.177)
- Guest IP: .2 (e.g., 172.16.161.178)
- 4 IPs total per VM: network, host, guest, broadcast
Internet Access: NAT via iptables on runner host
HTTP Proxy: mitmproxy at host:8080
- Intercepts all HTTP/HTTPS traffic
- Logs requests/responses
- Firewall enforcement (experimental)
- CA certificate injected into VM trust store
- Runner receives job via Ably push (or 30s polling fallback)
- Creates Firecracker VM (3-5s boot)
- Vsock connection to guest agent
- Upload scripts, configure DNS, install proxy CA
- Preflight check (curl to heartbeat endpoint)
- Download storages from R2
- Start agent CLI in background
- Webhook reports progress
- VM terminated on completion
Cloudflare R2 is S3-compatible object storage with zero egress fees.
- Endpoint:
https://{R2_ACCOUNT_ID}.r2.cloudflarestorage.com - Bucket:
R2_USER_STORAGES_BUCKET_NAME - SDK:
@aws-sdk/client-s3with S3-compatible API - Region: Auto (global)
- Archives: tar.gz compressed
- S3 keys: Content-addressed by SHA-256 hash
- Presigned URLs: 1-hour expiration for GET/PUT
Sandboxes download directly from R2 (no proxy through VM0 API):
- VM0 API generates presigned GET URLs
- Storage manifest JSON uploaded to sandbox
- Sandbox's
download.mjsscript fetches from R2 - Parallel downloads for multiple archives