Skip to content

Compiling

The spawnfile compile command takes a Spawnfile project and produces runtime-specific output files plus a machine-readable compile report. This guide explains the pipeline, output layout, and report format.

The reference compiler follows this pipeline:

  1. Parse the root Spawnfile.
  2. Validate local schema and file references.
  3. Walk the manifest graph through members[*].ref and subagents[*].ref.
  4. Detect cycles and incompatible duplicate references.
  5. Resolve effective runtime and execution for every graph node.
  6. Resolve agent descriptions and workspace/environment inheritance.
  7. Build a normalized intermediate representation (IR).
  8. Group resolved nodes by runtime.
  9. Invoke runtime adapters.
  10. Resolve representatives, team context files, rosters, and team-network artifacts.
  11. Attach compiler-owned capability outcomes and warnings before policy enforcement.
  12. Emit output directories and spawnfile-report.json.

The compiler operates on resolved IR after the graph phase, not on raw YAML. Adapters receive fully resolved nodes with all inheritance applied.

Validation happens in three layers:

  • YAML validity
  • Required fields (spawnfile_version, kind, name)
  • Path existence for docs, skills, environment inputs, and member/subagent refs
  • Enum checks (transport, isolation, sandbox mode)
  • Duplicate name/id detection
  • Cycle detection across teams and subagents
  • Duplicate node resolution conflicts (same path, different effective config)
  • Runtime resolution (every agent must have an effective runtime)
  • Team representative and team-network member references
  • Skill requires.mcp resolution against visible MCP scope
  • Runtime option validation
  • Runtime-native config constraints
  • Capability preservation checks

You can run validation without compiling using spawnfile validate:

Terminal window
spawnfile validate ./my-agent

This performs static and graph validation without invoking adapters or emitting output.

Use spawnfile view after validation when you want to inspect the resolved graph before compiling:

Terminal window
spawnfile view ./my-agent
spawnfile view ./my-team --mode networks
spawnfile view ./my-team --paths

validate answers whether the project is structurally valid. view shows what Spawnfile resolved from that valid project while staying read-only. compile performs validation, invokes runtime adapters, writes runtime-native output, and emits the compile report.

Graph nodes are keyed by canonical manifest path. One manifest path equals one logical node. If the same path is referenced multiple times, all references must resolve to the same effective runtime and execution. Otherwise the compiler fails.

The compiler tracks two edge kinds:

  • team_member — from a team to one of its members
  • subagent — from a parent agent to one of its subagents

Adapters may treat these edge types very differently.

  • For agents: runtime is declared in the manifest.
  • For subagents: runtime is inherited from the parent. If the subagent declares runtime, it must match the parent.
  • For execution: parent execution is deep-merged with child execution. Objects merge recursively, scalars replace, arrays replace wholesale.
  • For team members: each member declares its own runtime. Teams do not override member runtimes.

Runtime adapters implement two operations:

  • compileAgent (required) — takes a resolved agent node, emits files and capability outcomes.
  • compileTeam (optional) — takes a resolved team node, emits native team artifacts if the runtime supports them.

Each operation returns:

  • files — emitted files relative to the node’s output directory
  • capabilities — per-capability outcomes (supported, degraded, or unsupported)
  • diagnostics — warnings and errors discovered by the adapter

Every agent node is always compilable independently by its runtime adapter. Team compilation is optional and adapter-dependent.

For multi-runtime teams, the compiler compiles each member agent independently and reports any loss of native team semantics.

The compiler does not inject a team router or team-message tool. It emits context files and rosters that describe how agents can coordinate through shared declared surfaces and team networks.

Direct team memberships receive .spawnfile/team-contexts/<team-context-key>/TEAM.md and .spawnfile/rosters/<team-context-key>.yaml. Root TEAM.md and .spawnfile/roster.yaml are emitted only when the agent has exactly one direct team membership.

Selected nested-team representatives also receive parent context files: .spawnfile/team-contexts.yaml, .spawnfile/team-contexts.md, namespaced parent TEAM.md, parent rosters, and referenced team cards.

Rosters carry derivable per-surface addresses, not routed endpoints. Moltnet FQIDs are derivable. Slack, Discord, Telegram, and WhatsApp addresses require optional surfaces.<name>.identity. Portable HTTP addresses are not part of roster v2.

The default output root is ./.spawn. Within that root:

.spawn/
spawnfile-report.json
runtimes/
openclaw/
agents/
analyst/
teams/
research-cell/
picoclaw/
agents/
researcher/

Rules:

  • One directory per runtime
  • One stable directory per compiled node
  • Agent and team outputs are separated
  • The report file is always at the root

Use --out to change the output directory:

Terminal window
spawnfile compile ./my-agent --out ./build

The compiler emits a JSON report at spawnfile-report.json in the output root.

{
"spawnfile_version": "0.1",
"root": "/abs/path/to/Spawnfile",
"nodes": [],
"diagnostics": []
}

Each compiled graph node gets an entry:

{
"id": "agent:analyst",
"kind": "agent",
"source": "/abs/path/to/Spawnfile",
"runtime": "openclaw",
"output_dir": "runtimes/openclaw/agents/analyst",
"capabilities": [],
"diagnostics": []
}

For every declared capability, the compiler reports one of:

OutcomeMeaning
supportedFully preserved in the target with equivalent intent
degradedPartially mapped; runtime behavior may differ
unsupportedCannot be expressed in the target

Example:

{
"key": "execution.model",
"outcome": "supported",
"message": ""
}

The compiler reports on these keys:

  • workspace.docs.identity, workspace.docs.soul, workspace.docs.system, workspace.docs.memory, workspace.docs.heartbeat, workspace.docs.extras.<name>
  • workspace.skills.<name-or-ref>
  • mcp.<name>
  • execution.model, execution.sandbox, workspace.docs, workspace.resources, workspace.skills, environment
  • agent.subagents
  • team.members, team.mode, team.lead, team.external, team.shared, team.shared.workspace, team.shared.environment, team.nested
  • team.roster, team.context_orientation, team.representatives, team.networks, team.networks.<provider>, team.networks.<provider>.<network-id-key>
  • surfaces.<name>.identity

Adapters may add runtime-specific keys under runtime.options.* and runtime.native.*.

The compile report is always emitted regardless of policy. When policy is omitted, Spawnfile uses mode: warn and on_degrade: warn. What changes is whether degradation stops the build:

  • policy.mode: permissive — continues, records outcomes

  • policy.mode: warn — continues with warnings

  • policy.mode: strict — fails on any unverifiable capability

  • policy.on_degrade: allow — degradations are silent

  • policy.on_degrade: warn — degradations produce warnings

  • policy.on_degrade: error — degradations fail the build

Terminal window
# Scaffold a new agent project (defaults to openclaw)
spawnfile init
# Scaffold for a specific runtime
spawnfile init --runtime tinyclaw
# Scaffold a new team project
spawnfile init --team
# Add a member agent to a team
spawnfile add agent writer ./my-team --runtime tinyclaw
# Add a subagent to an agent
spawnfile add subagent critic ./my-agent
# Add a nested team to a team
spawnfile add team platform ./my-team

spawnfile init generates runtime-specific markdown docs (SOUL.md, IDENTITY.md, AGENTS.md) tailored to each runtime’s personality and capabilities. Each runtime adapter provides its own scaffold templates.

spawnfile add grows an existing manifest graph in place. It creates the child directory, scaffolds a Spawnfile, and appends the reference to the parent manifest. The CLI enforces parent kind rules: add agent and add team only work on team projects, and add subagent only works on agent projects.

Terminal window
# Set the primary model
spawnfile model set anthropic claude-opus-4-6 --auth claude-code
# Set a model with custom endpoint
spawnfile model set local qwen2.5:14b --auth none \
--compat openai --base-url http://host.docker.internal:11434/v1
# Add a fallback model
spawnfile model add-fallback openai gpt-4o-mini --auth codex
# Remove all fallback models
spawnfile model clear-fallbacks
# Update all agents in a team recursively
spawnfile model set anthropic claude-opus-4-6 ./my-team --auth claude-code --recursive

spawnfile model edits model intent in place and rewrites touched manifests to the canonical inline shape. When targeting a team project, --recursive is required and only descendant agent manifests are updated — the team manifest itself is left unchanged (teams do not declare execution).

Terminal window
# Validate without compiling
spawnfile validate ./fixtures/single-agent
# Inspect the resolved graph without compiling
spawnfile view ./fixtures/single-agent
# Inspect concrete team-network membership
spawnfile view ./fixtures/e2e/moltnet-team-chat --mode networks
# Compile the project in the current directory
spawnfile compile
# Compile a specific project
spawnfile compile ./fixtures/single-agent
# Compile with custom output directory
spawnfile compile ./fixtures/single-agent --out ./build