Sandboxes & VMs Overview
cersei-vms — sandbox & VM isolation for Cersei coding agents. Runs commands in isolated environments, supports parallel agents in parallel sandboxes, and shares state through host-mediated primitives.
cersei-vms
cersei-vms is the 15th crate in the workspace. It introduces a pluggable sandbox runtime layer so Cersei agents don't have to execute shell commands and edit files directly on the host machine. The same crate provides three cross-sandbox primitives — Volume, Mailbox, KvStore — that let multiple parallel agents communicate and share state safely.
Inspired by E2B. The trait shape (Sandbox / Commands / Filesystem) mirrors E2B's SDK almost 1:1, so existing mental models port directly. Unlike E2B, cersei-vms is first-party Rust, runs locally by default (Docker), and ships cross-sandbox primitives out of the box.
Why a sandbox layer
Without one, Cersei has three structural weaknesses:
- Unsafe for untrusted code. A model that emits shellcode runs it with the user's full privileges.
- No parallel-agent isolation. When
cersei-agent::delegatespawns N parallel sub-agents, they share one filesystem and process namespace — they trample each other on writes,cd, env vars. - No cross-agent comms primitive. There's
send_messagebetween coordinator/worker, but no shared state, no shared volumes, no message bus between independent agents.
cersei-vms fixes all three.
At a glance
Runtimes
SandboxRuntime trait + two backends: LocalProcessRuntime (always-on, no isolation, for tests) and DockerRuntime (real container isolation via the local docker CLI).
Per-sandbox surface
Every Sandbox exposes commands() (run / stream / signal) and filesystem() (read / write / list / stat / mkdir / remove / upload / download).
Cross-sandbox primitives
Volume (host-mounted dirs), Mailbox (broadcast pub/sub), KvStore (versioned CAS) — all host-mediated, so sandboxes don't need direct network links.
Snapshots
First-party Sandbox::snapshot() -> SnapshotId and SandboxRuntime::restore(&id). Docker uses docker commit; local copies the dir. Manifest stored in ~/.cersei/vms/snapshots/.
envd daemon
Tiny Rust JSON-RPC 2.0 daemon meant to live inside container images. Speaks process.*, fs.* over a bind-mounted Unix socket.
Transparent routing
When a Sandbox handle is in ToolContext.extensions, BashTool automatically routes through it. Zero changes to your tool list.
60-second example
use cersei::prelude::*;
use cersei::vms::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Spin up a local-process runtime (use DockerRuntime in prod).
let runtime = LocalProcessRuntime::new()?;
// 2. Allocate a sandbox.
let sb = runtime
.create(SandboxOpts::image("cersei/sandbox-base:latest"))
.await?;
// 3. Run a command inside it.
let out = sb
.commands()
.run(RunRequest::new("echo hello && pwd"))
.await?;
println!("{} (exit {})", out.stdout.trim(), out.exit_code);
// 4. Read/write files inside it.
sb.filesystem().write("/work/note.txt", b"first-party").await?;
let bytes = sb.filesystem().read("/work/note.txt").await?;
assert_eq!(&bytes[..], b"first-party");
// 5. Snapshot mid-run, kill, restore later — state survives.
let snap = sb.snapshot().await?;
sb.kill().await?;
let restored = runtime.restore(&snap).await?;
let again = restored.filesystem().read("/work/note.txt").await?;
assert_eq!(&again[..], b"first-party");
Ok(())
}Architecture
Multiple sandboxes attach to one host broker for Volume / Mailbox / KvStore. Sandbox-to-sandbox messages always go through the host — there is no requirement for sandboxes to network to each other directly, which keeps the security model simple.
Where it sits in the workspace
| Crate | Role |
|---|---|
cersei-types | Foundation types (no change). |
cersei-vms | Sandbox runtimes, traits, primitives, snapshots, envd daemon. New in 0.1.9. |
cersei-tools | Optional vms feature wires BashTool to route through a Sandbox when one is in ToolContext.extensions; ships new agent-facing tools in cersei_tools::vm_tools. |
cersei (facade) | cersei::vms re-export behind a default-on vms feature. |
What ships in 0.1.9 (Phase 1)
SandboxRuntime,Sandbox,Commands,FilesystemtraitsLocalProcessRuntimeandDockerRuntimebackendsVolume,Mailbox,KvStoreprimitives- Snapshot/restore for both backends
cersei-envdbinary + reference Dockerfile forcersei/sandbox-base- Transparent routing in
BashTool+ newvm_toolsmodule cersei::vmsfacade re-export- 9 passing integration tests covering all primitives + snapshots
What's coming in 0.1.10 (Phase 2)
AgentBuilder::with_sandbox(handle)/with_sandbox_allocator(...)— no more manual extension stuffing.cersei-agent::delegateper-task allocator — every parallel worker lands in its own sandbox.abstractCLI:--sandbox <local|docker>flag and/vmslash command.FirecrackerRuntime(Linux microVMs),E2bRuntime(remote E2B),VercelSandboxRuntime.docker pause/unpause, incremental snapshots, snapshot GC.
Reading order
- This page — concepts and architecture.
- VMs API — every public type, method, and option, organised by crate module.
- VMs Cookbook — end-to-end recipes: parallel agents over a shared volume, mailbox-driven coordination, snapshot-driven retries.
Compression Benchmarks
Real-provider token savings for cersei-compression — commands you can run locally plus the numbers we got on OpenAI and Google Gemini.
Sandboxes & VMs — API
Complete reference for cersei-vms — runtimes, sandbox surface, cross-sandbox primitives, snapshots, and the envd daemon protocol.