The packaged capability map takes in 0.7.9's changes, and its header marker moves to capability-delta-v0.7.9. Two lines 0.7.9 made stale are corrected: an emit now opens or notes an intake row for queue.worker, and any registered person can settle an ask asked of someone else, recorded as themselves. It also covers indeterminate receipts, --closure-required-at, guidance placement for fresh Pi and Codex 0.164.0+ seats with the cases that still use the repository's AGENTS.md, what rig down takes back and keeps, the rebuild for wrapper and symlink Claude launches, and the daemon HTTP client reference. rig-spec's managed_blocks and guidance_merge rows and agent-spec's target row say where guidance normally goes. Help text: rig stream emit names the intake row and how to keep emits passive, rig send --verify says exit 1 can mean unconfirmed, and rig down says what it takes back and what it keeps. Docs and help text only.
27 KiB
AgentSpec Reference
Version: 1.0
Last validated against code: 2026-10-07, at the 0.6.6 cut 2620dea8 (whole document at fcaf1f8e; changes to its sources and the shipped agent specs since then checked)
Source of truth: packages/daemon/src/domain/agent-manifest.ts, packages/daemon/src/domain/types.ts, packages/daemon/src/domain/agent-resolver.ts, packages/daemon/src/domain/profile-resolver.ts, packages/daemon/src/domain/skill-catalog.ts
This is the canonical reference for the AgentSpec YAML format (agent.yaml). Every field, validation rule, and default documented here was traced from the actual parser and validator code.
Minimal Valid Example
name: my-agent
version: "1.0"
profiles:
default:
uses:
skills: []
guidance: []
subagents: []
plugins: []
runtime_resources: []
resources: {}
startup:
files: []
actions: []
Practical Example (implementer agent)
name: implementer
version: "1.0"
description: Implementation agent — implements and verifies coherent changes
defaults:
runtime: claude-code
imports:
- ref: local:../../shared
profiles:
default:
uses:
skills: [development-team, systematic-debugging, verification-before-completion]
guidance: []
subagents: []
plugins: [shared:openrig-core]
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config, shared:claude-activity-hooks]
resources:
guidance:
- id: role
path: guidance/role.md
startup:
files:
- path: guidance/role.md
delivery_hint: send_text
required: true
actions: []
Complete Example (all features)
name: vault-specialist
version: "1.0"
description: Vault specialist agent — manages HashiCorp Vault for this managed app
defaults:
runtime: claude-code
model: claude-opus-4-6
effort: high
lifecycle:
execution_mode: interactive_resident
compaction_strategy: default-compaction
restore_policy: resume_if_possible
imports:
- ref: local:../../shared
- ref: local:../common-tools
version: "2.0"
profiles:
default:
summary: Standard Vault operations profile
preferences:
runtime: claude-code
uses:
skills: [systematic-debugging, vault-user]
guidance: []
subagents: []
plugins: [shared:openrig-core, vault-tools]
runtime_resources: [claude-settings]
startup:
files:
- path: guidance/profile-specific.md
delivery_hint: send_text
actions: []
lifecycle:
restore_policy: resume_if_possible
resources:
skills:
- id: vault-user
path: skills/vault-user
guidance:
- id: role
path: guidance/role.md
plugins:
- id: vault-tools
source:
kind: local
path: plugins/vault-tools
runtime_resources:
- id: claude-settings
path: runtime/claude-settings.fragment.json
runtime: claude-code
type: claude_settings_fragment
startup:
files:
- path: guidance/role.md
delivery_hint: send_text
required: true
- path: startup/context.md
delivery_hint: send_text
required: true
- path: guidance/optional-tips.md
delivery_hint: guidance_merge
required: false
applies_on: [fresh_start]
actions:
- type: send_text
value: "Load vault-user skill and verify Vault health."
phase: after_ready
idempotent: true
Top-Level Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | yes | — | Agent name. Used in spec library identification and validation messages. |
version |
string | yes | — | Spec version. Quote it ("1.0"): an unquoted number fails as a non-string. An importing spec that pins imports[].version must match it exactly. |
description |
string | no | — | Human-readable description. Shown in spec library and review surfaces. |
defaults |
Defaults | no | — | Default runtime, model, and lifecycle settings. Applied when not overridden by the rig spec or profile. |
imports |
Import[] | no | [] |
Other AgentSpecs to import. Resources from imported specs become available for profile uses references. |
profiles |
map<string, Profile> | no | {} |
Named profiles. Each profile selects resources and can override startup/lifecycle. The rig spec member's profile field selects which profile to use. |
resources |
Resources | no | all empty | Declared resources (skills, guidance, subagents, plugins, runtime resources). These are the available pool that profiles select from via uses. |
startup |
StartupBlock | no | { files: [], actions: [] } |
Agent-level startup files and actions. Applied to all profiles via the startup layering model. |
Defaults
defaults:
runtime: claude-code
model: claude-opus-4-6
effort: high
lifecycle:
execution_mode: interactive_resident
compaction_strategy: default-compaction
restore_policy: resume_if_possible
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
runtime |
string | no | — | Default runtime for this agent. Precedence: the rig spec member's runtime, then the profile's preferences.runtime, then this, then claude-code. |
model |
string | no | — | Default model, with the same precedence. |
effort |
string | no | — | Default reasoning effort, with the same precedence. Claude gets --effort, Codex -c model_reasoning_effort=…, Pi --thinking <level> (Pi's levels: off, minimal, low, medium, high, xhigh, max; passed as written). A blank or non-string value is ignored with an advisory. |
advisor |
string | no | — | Default Claude Advisor model, with the same precedence. Passed as the session-scoped --advisor flag, independently of the primary model; never written to shared Claude settings. Blank or non-string values are ignored with an advisory. Other runtimes ignore it. |
lifecycle |
Lifecycle | no | see below | Lifecycle behavior defaults. |
Lifecycle Defaults
| Field | Type | Default | Allowed Values |
|---|---|---|---|
execution_mode |
string | interactive_resident |
interactive_resident (only value in v1; wake_on_demand is explicitly rejected) |
compaction_strategy |
string | default-compaction |
default-compaction, managed-compaction, handover, apprentice-handover; deprecated aliases accepted with a validation advisory: harness_native → default-compaction, pod_continuity → handover (custom_prompt is explicitly rejected in v1). managed-compaction and apprentice-handover create their jobs only for claude-code seats; see Codex compaction and sizing |
restore_policy |
string | resume_if_possible |
resume_if_possible, relaunch_fresh, checkpoint_only |
mechanic |
string | — | A canonical seat@rig session address; needed by apprentice-handover |
Imports
imports:
- ref: local:../../shared
- ref: local:../common-tools
version: "2.0"
| Field | Type | Required | Description |
|---|---|---|---|
ref |
string | yes | Reference to another AgentSpec directory. Must start with local: (relative) or path: (absolute). The referenced directory must contain an agent.yaml. |
version |
string | no | Optional version constraint. Must be an exact version — no ranges (~, ^, >=, etc.). When set, the imported spec's version must equal it, or resolution fails with version_mismatch. |
Import Resolution
local:paths resolve relative to the importing spec's directorypath:paths are absolute filesystem paths- Imported resources become available for
usesreferences in profiles - A qualified reference
namespace:id(e.g.,shared:openrig-core) names the imported spec by itsnamefield - An unqualified reference (just
id) resolves against the spec's own resources first, then against the one import that declares it. If two imports declare it, the reference is ambiguous and fails: qualify it - An imported spec may not have imports of its own, and its
namemay not contain:. Two imports that resolve to the same spec name are refused, and import cycles are detected
The Shared Import Pattern
Most built-in agents import the shared builtin spec:
imports:
- ref: local:../../shared
This gives access to the shared pool: skills such as systematic-debugging, verification-before-completion,
development-team and test-driven-development; the openrig-core plugin, which carries openrig-user and OpenRig's
other skills; and runtime resources such as claude-default-settings, claude-default-mcp, codex-default-config and
claude-activity-hooks. Agents select the ones they need via profile uses, for example
plugins: [shared:openrig-core]. That selection projects the plugin's skills into the seat. For a Claude seat it also loads
the plugin's hooks, through a CLAUDE_CODE_PLUGIN_DIRS the daemon sets for a seat that selected openrig-core (see
refocus-channel.md); a seat that didn't select it gets neither.
Profiles
profiles:
default:
summary: Standard operations profile
preferences:
runtime: claude-code
model: claude-opus-4-6
uses:
skills: [systematic-debugging, vault-user]
guidance: [role]
subagents: []
plugins: [shared:openrig-core]
runtime_resources: []
startup:
files: []
actions: []
lifecycle:
restore_policy: resume_if_possible
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
summary |
string | no | — | Profile description. Spec review surfaces read a profile description instead. |
preferences |
object | no | — | Runtime/model/effort/Advisor preferences for this profile. |
preferences.runtime |
string | no | — | Preferred runtime. |
preferences.model |
string | no | — | Preferred model. |
preferences.effort |
string | no | — | Preferred reasoning effort. |
preferences.advisor |
string | no | — | Preferred Claude Advisor model; overrides defaults.advisor and can be overridden by the member. |
uses |
Uses | no | all empty | Selects which declared resources are active for this profile. |
startup |
StartupBlock | no | — | Profile-level startup files and actions. Merged with agent-level startup via layering. |
lifecycle |
Lifecycle | no | — | Profile-level lifecycle overrides. restore_policy can only narrow (resume_if_possible → relaunch_fresh → checkpoint_only); compaction_strategy and mechanic take the most specific value (defaults, then profile, then member). |
Uses
The uses block selects which resources from the resources pool (including imported resources) are active for this profile.
uses:
skills: [systematic-debugging, vault-user]
guidance: [role]
subagents: []
plugins: [shared:openrig-core]
runtime_resources: [claude-settings]
Each array contains resource IDs. These can be:
- Unqualified (
vault-user) — resolves against the spec's ownresourcesfirst, then imported specs - Qualified (
shared:systematic-debugging) — resolves against a specific imported spec's resources
The uses categories are: skills, guidance, subagents, plugins, runtime_resources. A uses.hooks key, even an
empty list, is refused: hooks ship inside plugins.
Skills resolve more widely than other resources. For Claude Code and Codex seats, a skill ID that no declared
resource provides is looked up at launch in the project's runtime skill folder in the seat's cwd (<cwd>/.claude/skills or
<cwd>/.agents/skills), then the skills/ folder beside the RigSpec, then the home skill folder, then the managed
skills root. Pi looks only in the skills/ folder beside the RigSpec. OMP does no filesystem discovery, so its
uses.skills references need declared resources. A discovered skill's ID is its SKILL.md frontmatter name, and a declared resource wins over a discovered skill with the
same ID. When a profile selects a skill from inside the spec's own folder and the managed catalog holds a different
copy, the spec's copy is used and launch warns skill_bundle_precedence. Any other differing copy fails launch with
skill_identity_conflict.
Resources
resources:
skills:
- id: vault-user
path: skills/vault-user
guidance:
- id: role
path: guidance/role.md
subagents:
- id: helper
path: subagents/helper
plugins:
- id: vault-tools
source:
kind: local
path: plugins/vault-tools
plugin_type: auto
runtime_resources:
- id: claude-settings
path: runtime/claude-settings.fragment.json
runtime: claude-code
type: claude_settings_fragment
Resources are the available pool. They are NOT automatically delivered to agents — profiles select them via uses.
The only declared resources delivered are those that the active profile's uses block references. Two sources add
skills outside uses: the managed skill catalog's system selection and a project's install.skills.
resources.hooks is refused at validation: hooks now ship inside plugins, declared under resources.plugins.
Plugin paths
A local plugin's source.path supports these forms:
| Form | Resolution |
|---|---|
/absolute/plugin |
The exact absolute path. |
~/plugins/example or ~ |
The operating-system user home. |
openrig-home:plugins/openrig-core |
Relative to the daemon's configured OpenRig home, including a non-default OPENRIG_HOME. |
plugins/example or ./plugins/example |
Relative to the agent spec directory. |
For a plugin seeded by OpenRig, use the home-relative form so the spec selects that daemon's copy:
resources:
plugins:
- id: openrig-core
source:
kind: local
path: "openrig-home:plugins/openrig-core"
profiles:
default:
uses:
plugins: [openrig-core]
openrig-home: is resolved by the daemon from its configured state root. It is
not shell interpolation and does not consult a seat's shell startup files. Its
suffix must be relative. Existing absolute, tilde and spec-relative paths keep
their meaning; ~user is still a literal relative segment, not a user lookup.
This form needs OpenRig 0.6.5 or later; keep bundles using it pinned to such a
version.
Resource Categories
| Category | Fields | Description |
|---|---|---|
skills |
id, path |
Skill directories containing a SKILL.md. Projected by the runtime adapter. Claude and Codex seats get them in the seat's own storage, <OpenRig home>/state/seats/<rig id>/<logical seat>/<runtime>/, outside the project: Claude to plugin/skills/<id> in the seat's generated plugin, where they show as openrig:<id>, and Codex to skills/<id> beside the seat's skill catalog. A Claude or Codex seat without that storage gets <cwd>/.claude/skills/<id> or <cwd>/.agents/skills/<id>. Pi and OMP project to the seat's own agent directory under OpenRig's state. |
guidance |
id, path, target, merge |
Guidance files, merged as a managed block (see "Guidance Resources"). |
subagents |
id, path |
Subagent definitions. Claude copies them to <cwd>/.claude/agents/, Codex to <cwd>/.agents/; Pi and OMP don't project them. |
plugins |
id, source, plugin_type* |
Local plugin directories; selected with uses.plugins. source.kind must be local. plugin_type is claude, codex or auto (default): Claude projects a plugin to <cwd>/.claude/plugins/<id> when it is claude, or auto with a .claude-plugin/plugin.json; Codex projects to <cwd>/.codex/plugins/<id> when it is codex, or auto with a .codex-plugin/plugin.json. Pi and OMP don't project plugins. Neither Claude Code nor Codex reads skills from that plugin folder, so when a seat is instantiated a selected plugin's skills are also projected into the seat's skill folder under their plain names: the seat's own storage (see skills), or .claude/skills/<name> or .agents/skills/<name> for a seat without it. A folder already there with the same name, ignoring letter case, that OpenRig doesn't own is left alone; unless it already holds the same bytes, launch warns plugin_skill_kept. A skill the seat already selects by that name (from its profile, the System World or the project) keeps that source, an edited OpenRig-owned copy is kept with plugin_skill_kept, a retained plugin copy whose remembered source can no longer be projected is also kept with plugin_skill_kept (a seat selecting that plugin refreshes it at its next launch), and if the plugin skills can't be projected the seat launches without them and warns plugin_skills_not_projected. Hooks ship inside plugins. |
runtime_resources |
id, path, runtime, type |
Runtime-specific resources. runtime and type are required. An entry whose runtime isn't the seat's runtime is skipped. Pi and OMP project none. |
*Fields marked with * are optional.
Recognized runtime resource types:
claude_settings_fragment— merge a JSON object into<cwd>/.claude/settings.local.json.claude_mcp_fragment— merge a JSON object into<cwd>/.mcp.json.claude_activity_hooks— reconcile OpenRig's activity hooks into<cwd>/.claude/settings.local.json.codex_config_fragment— upsert a TOML fragment into$CODEX_HOME/config.toml(default~/.codex/config.toml) inside an OpenRig-managed block.
Unknown runtime resource types are still copied to the Claude or Codex runtime extension directory for agent-visible context.
Writing a codex_config_fragment
Begin the fragment with a table header. A fragment must be a valid TOML document on its own, and every key it sets must sit under a table it declares. A fragment that puts keys ahead of its first table header is refused at projection time, and nothing is written.
The reason is TOML's grammar rather than a policy choice. The managed block is
appended to the end of the user's config.toml, and TOML has no syntax for
returning to document root once a table has been opened. So if the user's file
ends inside any table, an appended root-level key does not land at root — it
silently becomes a member of their table. Refusal is deterministic and never
inspects the user's file: a fragment author cannot see user state, and a rule
that passed or failed depending on it would be impossible to reproduce.
# refused — `model` would bind into whatever table the user's file ends inside
model = "gpt-5"
[mcp_servers.exa]
url = "https://mcp.exa.ai/mcp"
# accepted — every key sits under a table this fragment declares
[mcp_servers.exa]
url = "https://mcp.exa.ai/mcp"
Where a fragment's table is one the user already declares, the user's table wins: the managed table is dropped, their values are never merged, rewritten or overwritten, and the rest of the fragment still applies.
Resource Path Rules
- All resource paths must be safe relative paths (no
..traversal, no absolute paths), except a plugin'ssource.path, which takes the forms under "Plugin paths" - Paths resolve relative to the agent spec's directory
- Resource IDs must be unique within their category
- Resource IDs are the identifiers used in
usesreferences
Guidance Resources
guidance:
- id: role
path: guidance/role.md
merge: managed_block # optional — the only strategy applied
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id |
string | yes | — | Resource identifier. A rig-role guidance resource is never merged; deliver a role with a send_text startup file. |
path |
string | yes | — | Relative path to the guidance file. |
target |
string | no | — | Parsed but not used: the runtime decides the file. Claude merges into the rig's managed_blocks file (CLAUDE.md by default, or CLAUDE.local.md); Codex, Pi and OMP merge into <cwd>/AGENTS.md, except that a fresh Pi seat normally uses its own agent folder's AGENTS.md and a fresh Codex 0.164.0+ seat normally gets launch developer instructions; the conditions are in Codex guidance at launch and Runtime Differences. |
merge |
string | no | managed_block |
Only managed_block is applied. Any other value, such as append, merges nothing. |
Startup Block
The startup block follows the same format as in the RigSpec (see docs/reference/rig-spec.md for full details on files and actions).
Agent-level startup is applied to all profiles. Profile-level startup is applied only when that profile is active. Both merge additively via the startup layering model.
An additional orientation challenge requires an explicit startup_proof action
with value: authenticated and idempotent: true. Omission adds no exercise;
a later applicable value: none overrides an earlier selection. See
startup proof selection for precedence,
restore behavior, and the distinction between readiness and verified proof.
Delivery Hint Quick Reference
| Hint | When Delivered | Mechanism |
|---|---|---|
auto |
Depends on the file | A seat's own role (a file marked orientation: role, or at a guidance/role.md path) is send_text, so pod-mates never overwrite each other's role in the shared file. A seat launched before this rule keeps the hint saved at its launch, which restore (rig up <rig>), rig seat launch --fresh and handover replay, until the rig is instantiated from its spec again: rig down <rig>, then rig up <spec file>, which starts a new generation with fresh conversations. Otherwise a path ending in SKILL.md, or content beginning with # SKILL, is skill_install; a .md file is guidance_merge; and any other file is send_text |
guidance_merge |
Before harness boot | Merged into CLAUDE.md/AGENTS.md as managed block |
skill_install |
Before harness boot | Installed to runtime skill directory |
send_text |
After harness is ready | Sent as text to agent terminal via tmux |
Validation Rules Summary
nameandversionare required non-empty strings.importsmust be an array of objects withreffield.- Import
refmust start withlocal:(relative) orpath:(absolute). - Import
versionmust be an exact version (no ranges). profilesmust be a map (object), not an array.- Profile
usesreferences other than skills must resolve to declared resources (local or imported). Skill references are checked at launch, not at validation (see "Uses"). - Unqualified
usesreferences that don't resolve to local resources require imports to be present. - Qualified
usesreferences must be innamespace:idformat. - All resource paths must be safe relative paths (a plugin's
source.pathexcepted). - Resource IDs must be unique within their category, and each
resources.<category>must be an array. runtime_resourcesentries requireruntimeandtypefields. 12a.resources.hooksandprofiles.<name>.uses.hooksare refused: "removed in plugin-primitive (Phase 3a)". Declare a plugin instead. 12b. A plugin needs a unique non-emptyid, asourceobject withkind: localand a non-emptypath, and aplugin_typeofclaude,codexorautowhen given. 12c. Lifecyclemechanicmust be a canonicalseat@rigsession address.- Lifecycle
execution_modemust beinteractive_resident. - Lifecycle
compaction_strategymust be one ofdefault-compaction,managed-compaction,handover,apprentice-handover— or a deprecated alias (harness_native,pod_continuity), which validates with a deprecation advisory and normalizes to its canonical value (OPR.0.5.6.20). - Lifecycle
restore_policymust beresume_if_possible,relaunch_fresh, orcheckpoint_only. - Startup files and actions follow the same validation rules as in RigSpec.
Unknown keys are ignored, not refused. rig agent validate <path> [--json] runs these syntax checks through the running
daemon; it doesn't resolve imports, find skills or check that files exist, so a missing skill shows up only at launch.
File System Layout
An agent spec directory follows this conventional layout:
my-agent/
agent.yaml # required — the AgentSpec
guidance/
role.md # role definition
startup/
context.md # boot-time grounding
skills/
my-skill/
SKILL.md # skill content
plugins/
my-plugin/ # plugin (skills, hooks) with .claude-plugin/ and/or .codex-plugin/
runtime/
claude-settings.fragment.json # runtime-specific resource
The only required file is agent.yaml. Everything else is referenced by paths in the spec and must exist at those relative paths.
Shipped Examples
Every agent below except shared imports shared and selects plugins: [shared:openrig-core], which carries
openrig-user. Paths are under packages/daemon/specs/agents/; the kernel's own agents are under
packages/daemon/specs/rigs/launch/kernel/agents/.
| Agent | Location | Default runtime | Profile skills | Purpose |
|---|---|---|---|---|
shared |
shared/ |
— | — (resource pool only) | Shared skills, the openrig-core plugin and runtime resources |
implementer |
development/implementer/ |
claude-code | development-team, systematic-debugging, verification-before-completion | Implementation agent |
qa |
development/qa/ |
codex | development-team, systematic-debugging, verification-before-completion, agent-browser, dogfood | Quality assurance agent |
orchestrator |
orchestration/orchestrator/ |
claude-code | orchestration-team, systematic-debugging, verification-before-completion | Rig orchestration lead |
independent-reviewer |
review/independent-reviewer/ |
claude-code | review-team, systematic-debugging, verification-before-completion | Independent code reviewer |
vault-specialist |
apps/vault-specialist/ |
claude-code | systematic-debugging, verification-before-completion, vault-user | Vault domain specialist |
product-designer |
design/product-designer/ |
claude-code | development-team, frontend-design, verification-before-completion | Product designer |
pm |
product-management/pm/ |
claude-code | office-hours, context-builder, requirements-writer, ui-mockup, plan-review, exec-summary, backlog-capture; advisor profile: orchestration-team |
Product manager; its advisor profile is the factory's advisor |
analyst, synthesizer |
research/analyst/, research/synthesizer/ |
claude-code, codex | — | Research team |
conveyor-lead, -planner, -builder, -reviewer |
conveyor/ |
claude-code, codex, claude-code, codex | per role | Kept for the factory-rsi world bundle (its planner); no built-in team uses them |
factory-rsi-release-manager, factory-rsi-dogfood |
factory-rsi/ |
claude-code | per role | Used by the factory-rsi world bundle (not a built-in team) |