- Boot the scenario once — bring up your cluster (or adopt a running one that k7d already hosts) and wait until it is in the state you want every rollout to start from.
- Root a tree at that checkpoint.
- For each GRPO group (or tree-search step):
tree_fork_batch(N)→ run your N policies against the N copies → score →tree_protectthe winners,tree_prunethe losers → let the daemontree_auto_evictunder your RAM/disk budget. - Roll forward from a protected winner when you want the next generation to start from a better state, or
tree_rollbackto an earlier node when you don’t.
Why byte-identical starts matter for GRPO
GRPO (and most group-relative methods) compare rewards within a group. If member A starts from a colder cache, a different etcd revision, or a half-ready Deployment than member B, the reward gap is noise, not signal. A k7d fork is a copy of the live machine — same memory, same disk, same in-cluster TLS sessions, same kube-apiserver state. Every member of the group begins from a byte-identical world, then diverges only because of what your policy did. That is the difference between “we reset the env” and “we cloned the universe.”How your agent talks to the tree
The agent talks JSON-lines over a Unix socket (/run/k7d/k7d.sock). The verbs you actually need:
Full request/response shapes: Daemon API. Budget semantics and LRU eviction: Snapshot tree.
Three reference clients
All three live in the repo’sexamples/ and talk to the daemon over the socket. None is a finished SDK; each is the template for one way of driving the tree.
cluster-tree-search/ — the trainer loop
A thin Python client that covers exactly the loop above:
--keep (leave the tree around for tree_nodes inspection), --tree-id NAME (stable tree id), K7D_SOCKET (override the control socket).
k7d-mcp/ — a frontier agent with a fork button
A stdio MCP server that wraps the tree for Cursor CLI / Claude Code / Codex-style agents. The agent gets tree_status, fork_batch(node_id, n), branch_exec(node_id, member, cmd), tetragon_diff(node_id), and protect / prune / rollback — every call appends one JSONL line (tool, args, latency, tree usage).
The shipped scenario plants a self-healing miner in a live Ubuntu Cilium + Tetragon cluster. The agent does not touch production first: it forks the cluster three ways, tries delete / scale-to-zero / watch on the copies, learns the miner respawns, forks again from the copy that already knows that, and replays only the winning pair of moves on the source. One lab is left broken on purpose; no rollback needed. Video · how it works · JSONL.
k7view/ — the observer
A read-only dashboard: one SSE stream over tree_list / tree_nodes / tree_watch, a vsock probe thread that pings live agents for real RTT and /proc/loadavg, click-to-protect / evict. Fork latency chips are the daemon’s latency_ns; the UI never invents a number or a parent edge. The incident seen from the tree · a ×8 dilated tree recorded in real time.
Sizing the loop
- A single 3-VM cluster fork is ~105 ms on the minimal CI guest under API churn and ~1.1 s on Ubuntu k3s + Cilium + Tetragon; a shared-pause batch of 50 CI-guest clusters is ~3.85 s (~77 ms/cluster). See Benchmarks.
- Forks share memory until they diverge — RAM cost per group member is the dirty pages of its own rollout, not full guest RAM. Three idle k3s nodes dirty ~20% of guest RAM in 30 s (page-cache churn), so plan for that floor.
- Forking from a child costs a keyframe first: O(divergence), ~0.8 s idle / ~1.1 s under Kafka-style churn for 3 × 2 GiB. Fork from the root or from protected checkpoints when you can;
tree_prepare_fork_sourcelets you pay it at a moment of your choosing. - Set the tree budget to your box:
max_live_vms,max_live_ram_bytes,max_disk_bytes. The daemon proactively suspends least-recently-active unprotected nodes at 85% of the RAM budget, so a long training run doesn’t OOM the host.tree_nodesandtree_listreport liveusageagainst thebudget. - If an episode is mostly waiting, run the tree with
auto_warpjump(zero fidelity cost, 1.83× on a probe-heavy episode) or fork children atdilation: 8(8× on the same episode, bounded fidelity cost). Time warp has the trade-off table.
