Declarative YAML Specs

Instead of writing Rust code, you can define runs as YAML files and execute them with voidbox run --file <path>. The parser requires api_version: v1; other values are rejected.

Kinds

Four top-level spec kinds are supported:

  • agent — a single agent run inside one isolated VM.
  • pipeline — multiple agent boxes composed into explicit stages.
  • workflow — command-oriented steps executed in a shared sandbox.
  • sandbox — a bare VM definition used for interactive or shell-oriented flows.

Every spec shares the same top-level envelope: api_version, kind, name, an optional sandbox: block, an optional llm: block, and an optional observe: block for OTLP config. The rest of the structure is kind-specific.

Agent

A single agent spec declares the sandbox, LLM provider, prompt, and skills:

api_version: v1
kind: agent
name: hn_researcher

sandbox:
  mode: auto
  memory_mb: 1024
  vcpus: 1
  network: true

llm:
  provider: claude

agent:
  prompt: >
    Analyze current HackerNews top stories and produce
    a tactical briefing for AI engineering teams.
  skills:
    - 'file:examples/hackernews/skills/hackernews-api.md'
  timeout_secs: 600

Pipeline

A pipeline spec chains boxes with explicit stage ordering. Stages can be sequential (type: box) or parallel (type: fan_out):

api_version: v1
kind: pipeline
name: research

sandbox:
  mode: auto
  memory_mb: 512
  network: true

pipeline:
  boxes:
    - name: researcher
      prompt: Find 3 recent HN posts about Rust.
      skills: ['agent:claude-code']
      timeout_secs: 300

    - name: analyst
      prompt: Extract key technical facts.
      skills: ['agent:claude-code']

    - name: writer
      prompt: Turn facts into an executive summary.
      skills: ['agent:claude-code']

  stages:
    - type: box
      name: researcher
    - type: fan_out
      boxes: [analyst, writer]

Fan-out outputs are merged into a JSON array written to the next stage’s /workspace/input.json (see Pipeline Composition).

Per-box sandbox overrides (memory_mb, vcpus, network, env, mounts, snapshot) can be placed inside each PipelineBoxSpec under sandbox: to override the top-level defaults for that box only.

Workflow

A workflow is a shell-style DAG of commands sharing a single sandbox. No LLM required.

api_version: v1
kind: workflow
name: quick-workflow

sandbox:
  mode: mock
  memory_mb: 256
  network: false

workflow:
  steps:
    - name: fetch
      run:
        program: echo
        args: ['hello from workflow']

    - name: transform
      depends_on: [fetch]
      run:
        program: tr
        args: ['a-z', 'A-Z']
        stdin_from: fetch

  output_step: transform

Sandbox

A bare VM that boots and waits for interactive attach (voidbox shell). No agent loop runs.

api_version: v1
kind: sandbox
name: claude-sandbox

sandbox:
  memory_mb: 2048
  network: true

llm:
  provider: claude-personal

Running with the CLI

voidbox run --file examples/hackernews/hackernews_agent.yaml
voidbox run --file examples/specs/pipeline.yaml

The subcommand is run, the flag is --file (no short alias, no positional). For interactive agent or sandbox specs, use voidbox shell --file <path> instead.

Field reference

sandbox:

FieldValues / defaultNotes
modeauto (default), mock, localSelects the backend. No kvm / vz strings — the backend is picked by host OS.
memory_mbintegerGuest memory.
vcpusintegerGuest vCPUs.
networkboolEnables the NAT’d guest network.
envmap of string→stringGuest environment variables.
mountslist of { host, guest, mode: ro|rw }Host directory mounts.
kernelpathExplicit kernel image.
initramfspathExplicit initramfs image.
imageOCI refBase image used as the guest rootfs (e.g. python:3.12).
guest_imageOCI ref, or "" to disable auto-pullKernel + initramfs OCI bundle.
snapshotpath or hash prefixRestore from a snapshot instead of cold-booting.

llm:

FieldValues / defaultNotes
providerclaude, claude-personal, codex, ollama, customUnknown values fall back to claude. lm-studio is Rust-API-only today; not addressable from YAML.
modelstringProvider-dependent. Ollama defaults to qwen3-coder:7b if unset.
base_urlURLFor ollama and custom. custom defaults to http://<guest-host-gateway>:11434.
api_key_envenv var nameFor custom: the host-side env var the CLI reads to inject the API key into the guest.

agent:

FieldValues / defaultNotes
promptstring (required)Agent prompt.
skillslist of skill entriesSee “Skills” below.
timeout_secsintegerPer-box timeout.
output_fileguest pathAgent’s structured output destination inside the guest.
modetask (default), service, interactiveservice runs as a long-lived box; interactive waits for PTY attach.
messaging{ enabled, provider_bridge }Opt-in cross-box messaging.

Skills

Each entry in skills: is either a <type>:<value> string or an OCI image object:

FormExample
agent:<runtime>agent:claude-code
file:<host-path>file:skills/research-method.md
remote:<url>remote:https://example.com/skill.md
cli:<binary>cli:jq
mcp:<server-name>mcp:filesystem
OCI object{ image: ghcr.io/voidbox/skill-jq, mount: /skills/jq }

Inline and programmatic MCP skills exist in the Rust API but are not expressible from YAML.

Stage types

FormMeaning
{ type: box, name: <box> }Run <box> sequentially.
{ type: fan_out, boxes: [...] }Run listed boxes in parallel.

Environment overrides

Override LLM settings at runtime without editing the spec. Env vars take precedence over spec-level llm.* values.

Env varOverrides
VOIDBOX_LLM_PROVIDERllm.provider
VOIDBOX_LLM_MODELllm.model
VOIDBOX_LLM_BASE_URLllm.base_url
VOIDBOX_LLM_API_KEY_ENVllm.api_key_env
VOIDBOX_LLM_PROVIDER=ollama VOIDBOX_LLM_MODEL=phi4-mini \
  voidbox run --file examples/specs/pipeline.yaml

Next

Learn how to compose pipelines in Rust, or set up local LLMs with Ollama.