void-box logoVoid-Box
Architecture

Agent(Skills) + Isolation Boundary

void-box is a composable agent runtime where each agent runs in a hardware-isolated micro-VM. On Linux this uses KVM; on macOS (Apple Silicon) it uses Virtualization.framework (VZ). The core equation is:

VoidBox = Agent(Skills) + Isolation

A VoidBox binds declared skills (MCP servers, CLI tools, procedural knowledge files, reasoning engines) to an isolated execution environment. Boxes compose into pipelines where output flows between stages, each in a fresh VM.

Component Diagram

┌──────────────────────────────────────────────────────────────────┐
│ User / Daemon / CLI                                              │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐    │
│  │ VoidBox (agent_box.rs)                                   │    │
│  │  name: "analyst"                                         │    │
│  │  prompt: "Analyze AAPL..."                               │    │
│  │  skills: [claude-code, financial-data.md, market-mcp]    │    │
│  │  config: memory=1024MB, vcpus=1, network=true            │    │
│  └─────────────────────┬────────────────────────────────────┘    │
│                        │ resolve_guest_image() → .build() → .run()
│  ┌─────────────────────▼───────────────────────────────────┐     │
│  │ OCI Client (voidbox-oci/)                               │     │
│  │  guest image → kernel + initramfs  (auto-pull, cached)  │     │
│  │  base image  → rootfs              (pivot_root)         │     │
│  │  OCI skills  → read-only mounts    (/skills/...)        │     │
│  │  cache: ~/.voidbox/oci/{blobs,rootfs,guest}/            │     │
│  └─────────────────────┬───────────────────────────────────┘     │
│                        │                                         │
│  ┌─────────────────────▼───────────────────────────────────┐     │
│  │ Sandbox (sandbox/)                                      │     │
│  │  ┌─────────────┐  ┌──────────────┐                      │     │
│  │  │ MockSandbox │  │ LocalSandbox │                      │     │
│  │  │ (testing)   │  │ (KVM / VZ)   │                      │     │
│  │  └─────────────┘  └──────┬───────┘                      │     │
│  └──────────────────────────┼──────────────────────────────┘     │
│                             │                                    │
│  ┌──────────────────────────▼──────────────────────────────┐     │
│  │ MicroVm (vmm/)                                          │     │
│  │  ┌────────┐ ┌────────┐ ┌─────────────┐ ┌──────────────┐ │     │
│  │  │ KVM VM │ │ vCPU   │ │ VsockDevice │ │ VirtioNet    │ │     │
│  │  │        │ │ thread │ │ (AF_VSOCK)  │ │ (SLIRP)      │ │     │
│  │  └────────┘ └────────┘ └───────┬─────┘ └───────┬──────┘ │     │
│  │  Linux/KVM: virtio-blk (OCI rootfs)            │        │     │
│  │  9p/virtiofs: skills + host mounts             │        │     │
│  │  Seccomp-BPF on VMM thread    │               │        │     │
│  └────────────────────────────────┼───────────────┼────────┘     │
│                                   │               │              │
└═══════════════════════════════════╪═══════════════╪══════════════┘
              Hardware Isolation    │               │
                                    │ vsock:1234    │ SLIRP NAT
┌───────────────────────────────────▼───────────────▼───────────────┐
│ Guest VM (Linux kernel)                                           │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────────┐ │
│  │ guest-agent (PID 1)                                          │ │
│  │  - Authenticates via session secret (kernel cmdline)         │ │
│  │  - Reads /etc/voidbox/allowed_commands.json                  │ │
│  │  - Reads /etc/voidbox/resource_limits.json                   │ │
│  │  - Applies setrlimit + command allowlist                     │ │
│  │  - Drops privileges to uid:1000                              │ │
│  │  - Listens on vsock port 1234                                │ │
│  │  - pivot_root to OCI rootfs (if sandbox.image set)           │ │
│  └────────────────────────┬─────────────────────────────────────┘ │
│                           │ fork+exec                             │
│  ┌────────────────────────▼─────────────────────────────────────┐ │
│  │ claude-code (or claudio mock)                                │ │
│  │  --output-format stream-json                                 │ │
│  │  --dangerously-skip-permissions                              │ │
│  │  Skills: ~/.claude/skills/*.md                               │ │
│  │  MCP:    ~/.claude/mcp.json                                  │ │
│  │  OCI skills: /skills/{python,go,...} (read-only mounts)      │ │
│  │  LLM:    Claude API / Ollama (via SLIRP → host:11434)        │ │
│  └──────────────────────────────────────────────────────────────┘ │
│                                                                   │
│  eth0: 10.0.2.15/24  gw: 10.0.2.2  dns: 10.0.2.3                  │
└───────────────────────────────────────────────────────────────────┘

Data Flow

Single VoidBox Execution

1. VoidBox::new("name")           User declares skills, prompt, config
       │
2. resolve_guest_image()          Resolve kernel + initramfs (5-step chain)
       │                          Pulls from GHCR if no local paths found
       │
3. .build()                       Creates Sandbox (mock or local VM backend: KVM/VZ)
       │                          Mounts OCI rootfs + skill images if configured
       │
4. .run(input)                    Execution begins
       │
   ├─ provision_security()        Write resource limits + allowlist to /etc/voidbox/
   ├─ provision_skills()          Write SKILL.md files to ~/.claude/skills/
   │                              Write mcp.json to ~/.claude/
   ├─ write input                 Write /workspace/input.json (if piped from previous stage)
   │
   ├─ sandbox.exec_claude()       Send ExecRequest over vsock
   │       │
   │   [vsock port 1234]
   │       │
   │   guest-agent receives       Validates session secret
   │       │                      Checks command allowlist
   │       │                      Applies resource limits (setrlimit)
   │       │                      Drops privileges (uid:1000)
   │       │
   │   fork+exec claude-code      Runs with --output-format stream-json
   │       │
   │   claude-code executes       Reads skills, calls LLM, uses tools
   │       │
   │   ExecResponse sent          stdout/stderr/exit_code over vsock
   │       │
   ├─ parse stream-json           Extract ClaudeExecResult (tokens, cost, tools)
   ├─ read output file            /workspace/output.json
   │
5. StageResult                    box_name, claude_result, file_output

Pipeline Execution

Pipeline::named("analysis", box1)
    .pipe(box2)                    Sequential: box1.output → box2.input
    .fan_out(vec![box3, box4])     Parallel: both receive box2.output
    .pipe(box5)                    Sequential: merged [box3, box4] → box5.input
    .run()

Stage flow:
  box1.run(None)          → carry_data = output bytes
  box2.run(carry_data)    → carry_data = output bytes
  [box3, box4].run(carry) → carry_data = JSON array merge
  box5.run(carry_data)    → PipelineResult

For parallel stages (fan_out), each box runs in a separate tokio::task::JoinSet. Their outputs are merged as a JSON array for the next stage.

Network Layout (SLIRP)

void-box uses smoltcp-based usermode networking (SLIRP) -- no root, no TAP devices, no bridge configuration.

Guest VM                                    Host
┌─────────────────────┐                    ┌──────────────────┐
│ eth0: 10.0.2.15/24  │                    │                  │
│ gw:   10.0.2.2      │── virtio-net ──────│ SLIRP stack      │
│ dns:  10.0.2.3      │   (MMIO)           │ (smoltcp)        │
└─────────────────────┘                    │                  │
                                           │ 10.0.2.2 → NAT   │
                                           │   → 127.0.0.1    │
                                           └──────────────────┘
  • Guest IP: 10.0.2.15/24
  • Gateway: 10.0.2.2 (mapped to host 127.0.0.1)
  • DNS: 10.0.2.3 (forwarded to host resolver)
  • Outbound TCP/UDP is NATed through the host
  • The guest reaches host services (Ollama on :11434) via 10.0.2.2

Key Layers

Host Layer

CLI/daemon orchestrates runs, provisions skills/config, manages KVM VM lifecycle, and records run events.

Guest Layer

guest-agent authenticates host requests, enforces command allowlist + rlimits, drops privilege, then executes claude-code.

Communication

vsock protocol frames requests/responses and supports streaming chunks plus telemetry. See the Wire Protocol page for frame format details.

Security Model

KVM isolation + seccomp + session auth + policy controls + controlled networking. See the Security page for defense-in-depth details.