Integration shims that let existing orchestrators run void-box (microVM-isolated agent runtimes) as a first-class workload.
shim-k8s: Kubernetes — auto-selects betweenbatch/v1 Job(one-shot) andagents.x-k8s.io/v1alpha1 Sandbox(long-running services) based on the spec.shim-containerd: containerd runtime v2 shim (stub).shim-libvirt: libvirt domain adapter (stub).
- Run any void-box
RunSpecon Kubernetes with the same YAML schema you use locally. - Microvm (KVM) isolation for each agent — stronger than gVisor / Kata; smaller than full VMs.
- Native k8s lifecycle for long-running agents via the
kubernetes-sigs/agent-sandboxCRD: stable identity, headlessService,suspend/resumeviakubectl scale,shutdownTimeauto-expiration. - Per-agent credential isolation:
ANTHROPIC_API_KEY(orOPENAI_API_KEYfor codex) is read from the operator's env at render time, stored in a per-SandboxSecret, mounted into the pod, propagated into the guest VM. - Built-in observability: per-second host telemetry + structured run events
(
RunStarted,SpecLoaded,RunCompleted, …) over the daemon's HTTP API. - Cost tracking: tokens-in / tokens-out / USD reported per run.
# Build
cargo build --workspace --release
# Render a Job manifest (no cluster needed)
./target/release/void-shim-k8s render --file ./examples/run.yaml > /tmp/job.yaml
# Apply against a cluster
./target/release/void-shim-k8s run --file ./examples/run.yaml
# → default/void-run-smoke-test-abc12345
# Lifecycle
./target/release/void-shim-k8s status default/void-run-smoke-test-abc12345
./target/release/void-shim-k8s logs default/void-run-smoke-test-abc12345 --follow
./target/release/void-shim-k8s rm default/void-run-smoke-test-abc12345The shim auto-detects which k8s primitive fits the spec:
| Spec | Backend | When |
|---|---|---|
kind: agent, mode: task (default) |
batch/v1 Job |
One-shot prompt → exit |
kind: workflow |
batch/v1 Job |
Multi-stage pipeline → exit |
kind: pipeline |
batch/v1 Job |
Multi-box pipeline → exit |
kind: agent, mode: service |
agents.x-k8s.io/v1alpha1 Sandbox |
Long-running addressable agent |
Override with --backend job|sandbox|auto (default auto).
For kind: agent, mode: service, the shim renders a Sandbox CR plus three
auxiliary Secrets:
<name>-token— bearer token for the daemon's TCP listener<name>-spec— the RunSpec YAML, mounted at/spec/run.yaml<name>-llm-creds—ANTHROPIC_API_KEY(or other LLM creds) when applicable
-
agent-sandboxcontroller installed in the cluster:kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v0.4.6/manifest.yaml kubectl wait --for=condition=Established crd/sandboxes.agents.x-k8s.io --timeout=60s kubectl wait --for=condition=Available deploy --all -n agent-sandbox-system --timeout=180s
-
A container image with
voidbox0.2.x + entrypoint dispatcher baked in. Build locally:./crates/shim-k8s/dockerfile/build.sh /path/to/voidbox # → image void-box:smoke -
For real microVMs (
sandbox.mode: kvm): kernel + initramfs baked into the image AND the cluster's nodes must expose/dev/kvm. The bundleddockerfile/build.shships only the voidbox binary; for KVM mode you need a Dockerfile that also COPYs the kernel (e.g.target/vmlinux-slim-x86_64) and an agent-enabled initramfs (e.g.target/void-box-claude.cpio.gz) and setsENV VOID_BOX_KERNEL=… VOID_BOX_INITRAMFS=…. Seedocs/superpowers/specs/2026-05-27-mode-service-sandbox-backend-design.mdfor the full pattern.
# Operator-side env is auto-propagated into the per-Sandbox Secret
export ANTHROPIC_API_KEY=sk-ant-...
REF=$(./target/release/void-shim-k8s run --file examples/run-service.yaml)
# → default/smoke-svc-abc12345
# Inspect state
./target/release/void-shim-k8s telemetry $REF
./target/release/void-shim-k8s status $REF
# Conversation (caveat below)
./target/release/void-shim-k8s send $REF --message "hello"
# Lifecycle
./target/release/void-shim-k8s suspend $REF # kubectl scale --replicas=0
./target/release/void-shim-k8s resume $REF # kubectl scale --replicas=1
./target/release/void-shim-k8s cancel $REF # POST /v1/runs/<id>/cancel
./target/release/void-shim-k8s rm $REF # delete Sandbox CR (cascades)
# Raw connection info (URL + bearer token) for curl / SDK integration
./target/release/void-shim-k8s endpoint $REFEndpoint mode: out-of-cluster clients use kubectl port-forward
(spawned + reaped by the shim transparently). In-cluster callers use the
DNS <sandbox>.<ns>.svc.cluster.local:43100. Override with
--endpoint-mode auto|in-cluster|port-forward.
End-to-end against a local kind cluster:
# Prereqs: docker running, kind + kubectl on PATH
./scripts/kind_smoke.sh # Job-path only (mock sandbox, fast)
./scripts/kind_smoke.sh --keep-cluster # keep cluster alive for debugging
# With API key, exercises Sandbox path + real LLM round-trip too
export ANTHROPIC_API_KEY=sk-ant-...
./scripts/kind_smoke.shFor real KVM (sandbox.mode: kvm), kind needs the host's /dev/kvm exposed
to the node container:
# /tmp/kind-kvm-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- hostPath: /dev/kvm
containerPath: /dev/kvmkind create cluster --name void-shims-smoke --config=/tmp/kind-kvm-config.yamlFull chain proven against a real Anthropic API call:
| Step | Result |
|---|---|
| Shim renders Sandbox CR + 4 Secrets | ✅ |
| agent-sandbox controller creates pod | ✅ |
| Pod Ready (exec readiness probe with bearer auth) | ✅ 4 s |
voidbox serve accepts spec via POST /v1/runs |
✅ |
MicroVM boots with /dev/kvm + claude rootfs |
✅ telemetry CID assigned |
Claude Code CLI inside VM reads ANTHROPIC_API_KEY |
✅ |
| Real Anthropic API call | ✅ 7in / 148out tokens, $0.0303 |
Agent writes /workspace/output.json → published as run output |
✅ 4 bytes ("pong") |
| Telemetry stream | ✅ 21 samples |
Clean exit (RunCompleted event) |
✅ |
void-shim-k8s rm cascades cleanup |
✅ |
spec/shim-v0.2.md— shim contract (CLI, runtime model, target requirements)docs/superpowers/specs/— design docs (schema migration, Service-mode Sandbox backend)docs/superpowers/plans/— implementation plansexamples/run.yaml— task-mode agent (Job backend)examples/run-service.yaml— service-mode agent (Sandbox backend)
cargo build --workspace
cargo test --workspace # 44 tests (3 shim-core, 41 shim-k8s)
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all -- --checkCI (.github/workflows/ci.yml) runs all four on every push / PR.
Pre-commit hooks (.pre-commit-config.yaml) optionally run the same locally.
-
send/telemetry/canceloverkubectl port-forwardfails withreqwest. The HTTP request errors with "error sending request" though a directcurlagainst the same port-forward returns 200. Likely an HTTP/1.1 vs HTTP/2 / connection-pool interaction. Workaround:void-shim-k8s endpoint $REFto print URL+token, thencurldirectly. The full end-to-end execution path (apply → pod Ready → daemon serving → real LLM call) is unaffected — only the shim's outbound HTTP from the operator's machine. In-cluster callers (--endpoint-mode in-cluster) bypass port-forward entirely. -
Suspend / resume is not state-preserving. void-box 0.2.x cannot snapshot a running KVM VM (only Apple VZ on macOS has that API).
suspendscales the Sandbox to 0 replicas;resumestarts a fresh pod. The Sandbox CR identity persists; conversational / VM state does not. -
kindclusters don't expose/dev/kvmby default. For real microVMs in kind, use theextraMountsconfig above. Without it, onlysandbox.mode: mockworks (the mock path stubs the agent execution — no real LLM call). -
The released
agent-sandboxmanifest (v0.4.6) shipsv1alpha1only. The void-box source hasv1beta1types but they're not yet in a release. The shim rendersv1alpha1; whenv1beta1ships, a single-line bump is needed. -
Path dependency on
void-box.crates/shim-core/Cargo.tomlreferences../../../agent-infra/void-boxdirectly. Cloningvoid-shimsrequires cloningvoid-boxat the same relative path. Tracked as follow-up.
- Shims are integrations, not a replacement for
void-control. - Each
voidbox runinvocation already executes one microVM per RunSpec; the shim does not enforce an additional isolation profile.
- Debug
reqwest+kubectl port-forwardHTTP path — most likely fix: swap toureqor shell out tocurl. - Persistence across suspend/resume — needs upstream void-box snapshot/restore for in-flight KVM VMs.
kind: agent, mode: interactiveandkind: sandbox(bare VM) — same Sandbox backend, slightly different render shape.- Ingress / TLS for external clients.
--image-pull-secretfor private GHCR images.- GitHub Actions job running
scripts/kind_smoke.sh(withANTHROPIC_API_KEYas a repo secret) for regression coverage of the LLM round-trip. - Factor
void-box::specinto a sub-crate soshim-corecan switch frompathtogitdependency. - Migrate to
agents.x-k8s.io/v1beta1Sandbox when released.