This is a real run, replayed from its recording in your browser. Every box is a VM; the console inside each is its real serial console. It plays as it happened, with slow motion at the fork, and starts over when it ends. Click a box to enlarge its console and scroll its history.
This is the system prompt the agent in the first VM woke up with, placeholders filled as they were for this run (2 rounds, 25 s per maze, 3 solvers per fork), followed by the only message a human sent. Everything after it, the strategies, the forks, the verdict, the victory lap, was the agent's own doing. The model was DeepSeek V4 Flash through an Anthropic-compatible endpoint.
You are an autonomous agent running INSIDE a Firecracker microVM on zeo5, a platform where a live VM can fork itself: a fork is a snapshot of this VM -- memory, disk, and this very conversation -- woken as new VMs in about 40 ms each. You are the parent. Your goal: get an agent through a MAZE to the exit, in at most 2 round(s) of 25 seconds each.
THE PROBLEM. Solve a maze. It is a perfect maze (exactly one path between any two cells), 37 x 10 cells, given as a list of 21 strings of 75 characters: '#' is wall, ' ' is open. Coordinates are (x, y) with maze[y][x]. Start is (1, 1), the exit is (73, 19). The agent must WALK: one adjacent open cell per move, and it may walk back over cells it has visited. Every move costs the same fixed time, so the strategy that reaches the exit with the fewest wasted moves wins the race.
THE SOLVER CONTRACT. Each strategy is a Python 3 module (standard library only) defining
def solve(maze, start, goal, step, rng):
- maze: the list of strings; start, goal: (x, y) tuples.
- step(cell): moves the agent to an ADJACENT open cell (|dx|+|dy| == 1, not a wall) and returns True when that cell is the goal, False otherwise. It raises ValueError on an illegal move. You MUST move through step() one cell at a time, including when backtracking; keep calling it until it returns True, then return.
- rng: a seeded random.Random for tie-breaks -- use it for every random choice, so the same strategy explores differently in each VM.
- VISITED_BEFORE: a module-level frozenset of (x, y) cells an earlier attempt already explored (empty on a fresh maze). When continuing a maze, `start` is where that attempt stopped.
Any exploration order is allowed (depth-first, breadth-first over a mental map, wall-following, heuristics toward the exit, random restarts...). You may plan on the maze string freely, but the agent only advances by calling step(). No printing, no input, no threads. Under 70 lines each -- terse, no comments.
YOUR TOOLS.
- fork_solvers(strategies): give 3 strategies (the limit -- field all of them, a race of one is not a race), each with a name (short slug), an idea (one sentence) and the complete module code. This VM forks ONCE and the snapshot is woken once per strategy, in parallel; each child VM runs its own strategy with its own random seed. HARD LIMIT: 3 strategies per fork -- more is refused. Make them materially different (different exploration orders or heuristics); identical code only differs by seed.
- race_results(): waits until every child has reported and returns their results: solved or not, seconds, steps, cells explored. The host relays them; children cannot reach you directly.
- declare_winner(instance_id, reason): if a child REACHED THE EXIT, the FIRST one to do so (smallest seconds) wins -- the tool refuses any other choice: it is checkpointed as a named state, the others are discarded, and the game is over -- do NOT fork again, call finish. The champion gets a victory lap: the winner's VM is forked one last time, and that fork lives on as the champion's VM, showing a big trophy on its console. If NOBODY reached the exit, pick the child that got furthest (most cells explored, or closest to the exit): the others are discarded and that child TAKES OVER -- this conversation continues inside its VM, which still holds its half-explored maze, and its own children will CONTINUE THE SAME MAZE from where it stopped, its earlier trail shown in a different colour. After a take-over this VM steps aside: do not call more tools. If EVERY child failed outright (crashed at once, explored nothing), declare_winner with instance_id "none": they are all discarded and you fork again from this VM with fixed code.
- finish(summary): end the game with a short summary.
HOW A ROUND GOES: think briefly about which strategies to field (learn from the results so far), call fork_solvers with exactly 3 strategies, call race_results, call declare_winner. Never call fork_solvers while a round is unjudged. Keep prose short; the code matters. When you continue a maze, prefer strategies that exploit what is already explored (the harness tells the solver which cells were visited before).
Round 1 of 2. The maze race begins. Go.
A 1 GiB VM wakes from a snapshot in about 20 ms. A live VM forks itself in one snapshot and the copies are ready 50–100 ms later, three at a time. Each branch holds only what it changed, and the whole lineage is a tree you can wake, diff, compact or throw away. Below, an AI agent uses it to solve a maze by forking into three solvers and letting the first to the exit win.
All figures were measured on one 8-vCPU host in September 2026. They are host-dependent, and they are honest: nothing here is a projection.
A root set holds a full memory image, root filesystem and VM state. A derived set holds a sparse memory diff, a disk diff and a pointer to its parent. Lineage is a tree, not a line: one set can have many divergent children, and every fork advances the parent so the next fork layers on it.
snapshots/ tour/ mem · rootfs.ext4 · vmstate tour-s0e33f1/ mem.diff · disk.diff · parent → tour maze-r1-bfs-path/ the checkpointed winner maze-r1-bfs-path-champion/ its victory lap
The guest talks to the daemon over a vsock control channel. A fork snapshots the parent, seals a diff and wakes it as new VMs; the parent resumes about 10 ms after the pause. The children resume inside the same call, so identity, not the reply, decides the role.
fork(count=3) parent: whoami → same id, last_children=[…] child: whoami → new id, fork_index=0|1|2 one snapshot, three wakes, 50–100 ms in all
The pool keeps the VMM running per slot, so a wake is a restore, not a boot. A userfaultfd handler serves pages on first touch, prefaulting the profiled working set, so a 1 GiB VM costs tens of megabytes at rest.
rootfs 0.1 ms link the layers backend 2.5 ms handler + working set load 8–13 ms restore the VM state awake 17 ms guest announces itself ready 17–25 ms service port answers
Durable execution engines already think in steps, retries, journals and branches. zeo5 gives each step a machine that can be checkpointed, resumed and forked in tens of milliseconds, so the machine state becomes as durable as the workflow history.
Run an activity or a handler inside a VM and checkpoint it when the step completes. The checkpoint is the durable result: memory, disk and open state included, not just the return value. A retry resumes the exact machine at the failed step in about 20 ms instead of re-running everything before it.
activity(step 3) fails at 14:02 wake checkpoint-after-step-2 22 ms retry step 3 from there, nothing re-executed
Speculative or competing paths, fan-out over inputs, "try three approaches and keep the best": fork the step's VM once and wake it N times. Each branch holds only what it changed. The losers are discarded; the winner's checkpoint continues the workflow. The demo above is exactly this, driven by an agent.
fork(count=3) one snapshot, three branches branches ready in 50–100 ms keep one, discard two, continue
A workflow that waits — on a timer, a signal, a human — parks its VM as a snapshot. A parked snapshot occupies disk, not RAM or CPU; a warm slot that will wake it costs 3.4 MB. When the signal arrives, the machine is back in about 20 ms with its uptime continuing from the pause. Long-lived workflows stop being long-lived processes.
await signal VM parked, 0 CPU signal at +6h wake 22 ms uptime continues from the pause
Nothing here requires a change to the engine: a worker that calls zeo5's daemon to wake, checkpoint, fork and release is an ordinary activity implementation. The snapshot tree is the workflow's history, written in machine state.
Working today, measured, demonstrated above:
The recording above is one run. A live session shows the fork burst on your own prompt, a VM woken from a checkpoint to answer a shell command in 25 ms, and the state tree growing as it goes. Twenty minutes, a screen share, and your questions.
Tell me what you would run on it — agents, CI, sandboxes, anything that wants many short-lived copies of one prepared machine — and I will set up a session.
request a demo