FluxVM for AI agents
Give an agent a disposable, hardware-isolated machine it can break, with a handle to checkpoint it, roll it back,
see what it changed and read what it did. FluxVM runs the machine (Apple Virtualization.framework on a Mac; KVM,
Firecracker, Cloud Hypervisor and QEMU on Linux) and an agent session wraps it with a workspace, a network policy
and a ledger. On a Mac, --host-gpu / runtime.host_gpu exposes the host Metal/MLX OpenAI endpoint inside an offline
guest (host-inference.md).
Agent (Claude Code, Codex, Gemini CLI, OpenCode, your own)
โ MCP ยท REST ยท Go ยท Python ยท fluxctl
โผ
Agent session โโ workspace ยท policy ยท checkpoints ยท ledger
โ
โผ
Sandbox โโ snapshot ยท restore ยท fork (KVM) ยท speculate โ changeset โ approve/apply
โ
โผ
vz ยท KVM ยท Firecracker ยท Cloud Hypervisor ยท QEMU
Honest status. On an Apple M4 the session layer was run live for create, exec, memory checkpoint and restore, fork into diverging children, workspace diff and delete. It is not sub-second (create is seconds), and a session on the Mac's NAT cannot fork (offline or allow-listed sessions can). Since then the layer gained filesystem confinement (Landlock + seccomp, Linux guests), scoped session tokens, a guest job supervisor, per-action approvals, per-session HTTP method/path rules, budgets, resumable file transfer and fork-evaluate-promote. Those are implemented and unit/router tested, not yet field-tested on a live guest; the practical guide ends with the exact list. Start with agent-sessions-guide.md. The table at the end lists every claim and how it was checked. Compared with microsandbox: vs-microsandbox.md.
Installโ
macOS (Apple silicon, macOS 14 or newer) and Linux (x86_64):
curl -fsSL https://zyvorai.github.io/zyvor-fluxvm/install.sh | bash # download, verify, install
curl -fsSL https://zyvorai.github.io/zyvor-fluxvm/install.sh | bash -s -- --service --client claude-code
fluxctl --version && curl -s http://127.0.0.1:7788/healthz # {"ok":true} once the daemon runs
The installer needs no sudo or Homebrew, verifies the package's SHA-256, and is reversible (--uninstall); the options and
what it changes are in install.md. Homebrew (brew install zyvorai/tap/fluxvm) is the alternative on
a Mac.
Sessions ship in 0.4.8+; current is 0.4.18. fluxctl agent --help should list verbs. On a Mac, add --host-gpu
(or runtime.host_gpu) so an offline guest can call the host Metal/MLX OpenAI endpoint (host-inference.md).
If agent is missing, upgrade (curl โฆ \| bash or brew upgrade zyvorai/tap/fluxvm) or build from source
(install.md).
Linux hosts use the same installer when the release has a linux-x86_64 asset (check the release page: the package is
built in ubuntu:22.04, and not every release has had one attached); otherwise cargo build --release -p fluxctl. Full macOS notes: install-macos.md.
60 secondsโ
# a session: a sandbox, a network policy, a workspace directory
fluxctl agent run claude-code --policy developer-safe --ttl-seconds 3600 # prints the session, note its id
fluxctl agent exec <id> -- 'uname -a && mkdir -p /workspace/demo && echo hi > /workspace/demo/a.txt'
fluxctl agent checkpoint <id> --tag before-change
fluxctl agent exec <id> -- 'echo changed > /workspace/demo/a.txt'
fluxctl agent artifacts <id> # what changed in /workspace since the session started
fluxctl agent restore <id> before-change # memory, disk: back to the checkpoint
fluxctl agent timeline <id> # what was done, in order
fluxctl agent rm <id>
Measured on an M4 mini (debug build, 5 runs): create 4.6-6.8 s, exec 0.1-0.4 s, checkpoint 0.7 s, restore 4 s, fork into 2 running children 2.5 s. Details and caveats: benchmarks/agent-session.md.
Wire it to your agent (MCP)โ
fluxctl mcp install claude-code --allow-write # also: codex, gemini, cursor, vscode, ... see `fluxctl mcp --help`
fluxctl mcp status
The agent then has the session_* tools (create, exec, jobs, files, git, checkpoint, restore, fork, rollout, evaluate,
promote, grants, tokens, approvals, probe, events, artifacts, delete) and the review loop tools sandbox_speculate,
sandbox_changesets, sandbox_changeset_decide. Write tools exist only with --allow-write. For an agent you do not
fully trust, give the MCP server a scoped session token, not the admin one. The full table is in
mcp.md.
From codeโ
from fluxvm import FluxVM
fx = FluxVM("http://127.0.0.1:7788")
with fx.create_session("codex", policy="developer-safe", ttl_seconds=900) as s:
r = s.exec("python3 -c 'print(6 * 7)'")
print(r.exit_code, r.stdout)
s.checkpoint("clean")
s.exec("rm -rf /workspace/*")
s.restore("clean")
print(s.artifacts()["changes"])
c := fluxvm.NewClient("http://127.0.0.1:7788")
s, err := c.CreateSession(ctx, fluxvm.CreateSessionRequest{Agent: "codex", Policy: &fluxvm.SessionPolicyRequest{Preset: "offline"}})
defer s.Delete(ctx)
res, _ := s.Exec(ctx, "uname -a", 30)
Try several fixes, keep the one that passesโ
Two ways, depending on the backend:
- Any backend, one sandbox:
sandbox_speculateruns a command in an isolated copy and returns a changeset (added/modified/deleted files with contents). Review it, thensandbox_changeset_decidewithapproveandapply. Apply refuses with a conflict if the files changed since. - A forkable session (offline or allow-listed on a Mac, or in-tree KVM on Linux):
fluxctl agent fork <id> --count 4creates children that start from the parent's exact state and diverge; run a candidate in each, keep the winner, delete the rest. examples/agent-sandbox-demo does this at the sandbox level (4 copies in about 4 s on an M4 mini). A session on the Mac's NAT answers409with the reason and creates nothing.fluxctl agent evaluateforks one child per candidate, tests and ranks them and keeps the winner;fluxctl agent promote <child> --dry-runthen shows a three-way merge of its workspace changes into the parent, which you apply with theplan_id.
Policyโ
fluxctl agent run codex --policy offline # no network card at all
fluxctl agent run codex --policy developer-safe # GitHub, crates.io, PyPI, npm, Go proxy
fluxctl agent run codex --allow api.example.com --allow '*.example.com'
Host allow-lists are enforced by the host (a proxy on ports 80/443; the guest has no other route). Beyond that:
- Method and path rules (
{host, methods, paths}entries) are enforced per session by the host's egress proxy where the sandbox's traffic reaches it (QEMU/KVM with the proxy enabled); a session that cannot be filtered is refused at create unless you choosebest-effort. Not onvz. - Filesystem rules are enforced inside Linux guests with Landlock + seccomp (
--confine,--fs-read,--fs-write). - Process rules (
allow,deny,ask) are a guardrail on the command string, not a security boundary;askholds a command for an operator's approval.
How to choose and verify each: agent-sessions-guide.md. Reference: agent-sessions.md.
What was checked, and howโ
| Claim | Status |
|---|---|
create / exec / delete on vz | Run live (M4, macOS 27.2, stock debian-13) |
| memory checkpoint, restore reverts a file | Run live |
| disk-only restore | Run: it cold-boots, and exec returned 255 until the guest had finished booting; do not rely on it for quick rollback |
| workspace baseline and artifacts diff | Run live (an added file reported) |
| git clone into the workspace | Run: failed as designed on the stock image (no git, reported in workspace.note); success path not run |
| network allow-list | Run live through a session (--allow example.com): that host answered 200 over the proxy, example.org was refused, a direct connection to an IP had no route |
| tenant isolation (404 across tenants) | router tests, not a multi-tenant daemon |
| fork | Run live on vz: an offline session into 2 children, which inherited the parent's state and diverged; 409 for a NAT session. The in-tree KVM fork is Not run on hardware |
| MCP tools, Go and Python SDKs | mock-server tests; the CLI path is the one run live |
| sub-second start | Not met (see the benchmark); a goal |
Where to go nextโ
- agent-sessions.md: the API, backends, policy compiler, roadmap.
- macos-sandboxes.md, agent-density.md: sandboxes on a Mac, warm pool, density.
- credential-broker.md, http-acl.md, procbox.md: secrets, egress rules, rootless sandbox.
- vs-microsandbox.md: how this compares, including where FluxVM is behind.