StackMap
Subscribe
Explore / forkd
deeplethe

forkd

fork() for agent microVMs: children fork copy-on-write from a warm Firecracker parent — 100 KVM-isolated VMs in ~100ms, live-VM branching in ~56ms, portable snapshots from a hub.

2,720 212 Rust Apache-2.0updated 2 days ago
Curator's take

The sandbox primitive agent fan-out actually wants: instead of cold-booting a kernel per child, a parent VM boots once with your runtime warm (deps imported, model loaded, JVM JITed) and children mmap its memory copy-on-write — so spawning 100 isolated environments costs ~100ms, and v0.4 can BRANCH a live running VM. Tree-search agents, parallel experiment runners and RL rollouts are the natural fits. NOT a managed platform: Linux/KVM only, you operate it, and there's no E2B-style API compatibility — this is a runtime primitive you build on, not a sandbox service you call.

Mapped by ShipWithAI editors · links verified
README.md

forkd


CI Release PyPI License 中文 README Stars


Fork 100 microVMs in 101 ms. BRANCH a live VM in 56 ms (v0.4 live mode).

forkd: pull a portable snapshot from the hub, then fork 100 microVMs
Unedited: `forkd pull` a portable snapshot, then fork 100 microVMs — 100/100 alive, ~200 ms wall-clock. asciicast. (First pull also fetches the rootfs sidecar once; cached here.)

A microVM sandbox runtime for AI agent fan-out. Children fork from a warmed parent snapshot, inheriting its address space copy-on-write instead of cold-booting their own kernel.

forkd is built on Firecracker. The parent VM boots once, imports your runtime (Python + your dependencies, a JIT-warmed JVM, an already-loaded ML model) and is paused to disk. Each child is a separate Firecracker process that mmaps the parent's memory image with MAP_PRIVATE; the kernel implements copy-on-write at the page level, so children share the parent's resident memory until they diverge.

The result is two properties at once: per-child KVM isolation, and a spawn cost that's closer to fork(2) than to a cold-boot VM.

forkd also supports BRANCH: pause a running sandbox, snapshot its in-flight state, and resume — all in ~150 ms — so an agent can fork mid-thought, not only at warm-up. v0.3.4 fixed a slow-path regression where repeated BRANCHes on the same parent ballooned from 150 ms to 2.7 s (#146); the chain now stays flat (17.6× faster on the 6th consecutive BRANCH).

v0.4 live BRANCH collapses the source-pause window from ~200 ms (Diff) to 56 ms p50 / 64 ms p90 on a 1.5 GiB source — measured on a real BRANCH workload, bench/live-fork-pause-window/RESULTS-v0.4.md. 3.6× faster pause vs v0.3 Diff at p50, and the gap widens on slower storage because Live's pause is disk-independent (memory copy runs after resume, not during). With wait: false the caller returns in ~70 ms while the background copy completes asynchronously — a 200× RT improvement for fire-and-forget BRANCH from agent code. Pass --live / --no-wait on the CLI, mode: "live" / wait: false on REST, or the same on the Python / TypeScript / MCP SDKs.

from forkd import Controller
c = Controller()
# Source must boot with live_fork=True (memfd-backed RAM, the prereq
# for UFFD_WP to see writes from the running parent).
parent = c.spawn_sandboxes("pyagent", n=1, live_fork=True)[0]
# ... drive parent ... then BRANCH live + fire-and-forget:
branch = c.branch_sandbox(parent["id"], mode="live", wait=False)
# Returns after ~10 ms with status="writing"; poll list_sna

Continue your stack

What teams reach for next — and why each earns a place beside forkd. Ranked by curator confidence.