# Agent-definition schema

[Documentation index](../README.md)

This page is the canonical public schema for Markdown agent definitions.

## File format

A definition requires frontmatter beginning on the first line and a closing
frontmatter delimiter:

```markdown
---
name: scout
thinking: medium
tools: ["read", "bash"]
---

Prompt body.
```

Known string arrays use inline JSON arrays. YAML block sequences are not
supported.

Unknown frontmatter fields fail validation.

Malformed files fail discovery; Pi Herd does not silently drop one invalid
definition and return a partial roster.

## Sources and precedence

Bundled definitions:

```text
dist/agent-definitions/
```

Global definitions by default:

```text
~/.pi/agent/agents/
```

A matching global name overlays the bundled definition.

An unmatched global definition is standalone.

All effective definitions are sorted and validated together, including every
`subagents` reference.

`enabled` controls definition availability. A disabled definition remains in the
root roster so it can be enabled again, but parent-visible definition lists omit
it. Fresh assignments and non-live historical-session restores reject a disabled
definition. An already-live worker keeps its launch-time configuration and
remains controllable and reusable.

## Fields

| Field                   | Accepted value                                                        | Omitted/default behavior                                          | Runtime/composition behavior                                                                           |
| ----------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `name`                  | non-empty string                                                      | required                                                          | Effective definition identity.                                                                         |
| `enabled`               | boolean                                                               | `true`                                                            | `false` makes fresh assignment and non-live restore unavailable; it does not mutate a live worker.     |
| `description`           | string                                                                | absent                                                            | Display/selection description.                                                                         |
| `model`                 | non-empty string                                                      | Pi default/current launch behavior                                | Passed as Pi model selection.                                                                          |
| `thinking`              | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`, or `false` | Pi default/current launch behavior                                | `false` launches as `off`.                                                                             |
| `systemPromptMode`      | `append` or `replace`                                                 | `append` only for definition name `delegate`; otherwise `replace` | Controls effective body versus Pi base system prompt.                                                  |
| `bodyMode`              | `append` or `replace`                                                 | `replace` for non-empty matching override body                    | Valid only in a global file matching a bundled definition; consumed during body composition.           |
| `noTools`               | boolean                                                               | Pi normal tool policy                                             | `true` emits `--no-tools`; managed `ask_owner` remains infrastructure.                                 |
| `noBuiltinTools`        | boolean                                                               | Pi normal built-in tool policy                                    | `true` emits `--no-builtin-tools`.                                                                     |
| `tools`                 | inline array of non-empty strings                                     | no explicit allowlist                                             | Passed as tool allowlist; matching override replaces whole array.                                      |
| `excludeTools`          | inline array of non-empty strings                                     | no explicit exclusions                                            | Passed as exclusions; matching override replaces whole array.                                          |
| `noSkills`              | boolean                                                               | skills disabled unless `inheritSkills: true`                      | Controls Pi native skill discovery; explicit `skills` values are still passed separately.              |
| `inheritSkills`         | boolean                                                               | does not enable by itself unless `true`                           | `true` changes omitted `noSkills` default so native skills remain available. Explicit `noSkills` wins. |
| `skills`                | inline array of non-empty strings                                     | no explicit skill arguments                                       | Each value is passed unchanged as a Pi skill path/resource.                                            |
| `noExtensions`          | boolean                                                               | Pi normal extension policy                                        | `true` emits `--no-extensions`. Required Herdr worker infrastructure remains injected by the launcher. |
| `extensions`            | inline array of non-empty strings                                     | no extra extension arguments                                      | Each value is passed unchanged to Pi.                                                                  |
| `subagents`             | inline array of unique non-empty definition names                     | no direct children                                                | Names direct definitions this worker may assign; every name must exist.                                |
| `inheritProjectContext` | boolean                                                               | `true` only for definition name `delegate`; otherwise `false`     | Controls project context-file inheritance.                                                             |
| `inheritGlobalContext`  | boolean                                                               | follows effective `inheritProjectContext`                         | Controls global context-file inheritance.                                                              |

Arrays supplied by an override replace the complete inherited array, including
an explicit `[]`.

When a parent declares a child in `subagents`, that child must be enabled. A
parent referencing a disabled child can remain discoverable, but is rejected
during assignment or fresh worker startup with an explicit disabled-child error
rather than being silently removed from the parent definition.

Skill and extension paths are passed to Pi unchanged. Herdr does not resolve
them relative to the definition file.

## Tool inference for `subagents`

A non-empty `subagents` list declares potential child definitions; effective
delegation also requires permitted `subagent` capability and a controller depth
that allows delegation.

This capability is projected by controller depth. Root-launched definitions
retain their declared child allowlist and effective `subagent` tool. A
parent-launched child receives no child allowlist and no effective `subagent`,
even when its definition is delegation-enabled at the root. Explicit tool
allowlists, empty arrays, `noTools`, and exclusions remain fail-closed.

When it has an explicit non-empty `tools` allowlist and does not already contain
`subagent`, Pi Herd appends `subagent` to the effective allowlist unless denied.

Rules:

| Configuration                                      | Effective inference                                                         |
| -------------------------------------------------- | --------------------------------------------------------------------------- |
| `subagents` omitted or `[]`                        | no inferred `subagent`                                                      |
| non-empty `subagents`, `tools` omitted             | keep Pi default tool policy; do not materialize a `subagent`-only allowlist |
| non-empty `subagents`, explicit non-empty `tools`  | append `subagent`                                                           |
| `excludeTools` contains `subagent`                 | explicit denial wins                                                        |
| `noTools: true`, no explicit `subagent` in `tools` | no inferred `subagent`                                                      |
| `noTools: true`, explicit `tools: ["subagent"]`    | explicit allow is preserved                                                 |
| explicit allow plus explicit exclusion             | exclusion wins                                                              |

`ask_owner` is separate mandatory managed-worker infrastructure and is not this
inference rule.

## Body composition

The body is text after the closing `---`, trimmed at its outer boundaries.

For a matching global override:

```text
empty override body
    → bundled body

non-empty override body, bodyMode omitted/replace
    → override body

non-empty override body, bodyMode append
    → bundled body + "\n\n" + override body
```

Standalone definitions cannot declare `bodyMode`.

## Body file references

A body line is a reference only when the complete trimmed line matches:

```text
@./relative/path
@../relative/path
@/absolute/path
```

Before bundled/global body composition, relative references are resolved from
the definition file that declared them.

When a new worker generation is constructed:

1. references are processed in body order;
2. targets are canonicalized with `realpath`;
3. each canonical file is included once;
4. a caller `assign.files` canonical overlap wins and removes the body copy;
5. each accepted source must be a bounded readable regular UTF-8 file without
   NUL bytes;
6. included text replaces that reference line;
7. included text is not recursively expanded.

A live reusable worker keeps its launched prompt and does not re-expand body
files for every later assignment.

## Runtime prompt order

For a newly constructed managed worker, the effective launch composition is:

```text
Pi base system prompt
    ↓ effective body via systemPromptMode
selected project/global context-file additions
    ↓
shared Herdr worker guidance
```

The final effective body and shared guidance are delivered through private
temporary prompt snapshots.

## Complete override example

```markdown
---
name: reviewer
description: Review implementation changes
model: openai-codex/gpt-5.6-luna
thinking: high
bodyMode: append
systemPromptMode: replace
noTools: false
noBuiltinTools: false
tools: ["read", "bash"]
excludeTools: []
noSkills: false
inheritSkills: true
skills: ["/absolute/path/to/code-review/SKILL.md"]
noExtensions: false
extensions: ["/absolute/path/to/local-extension.ts"]
subagents: ["scout"]
inheritProjectContext: true
inheritGlobalContext: false
---

Additional local review instructions.

@./prompts/review-policy.md
```

Because `subagents` is non-empty and the explicit `tools` list does not deny it,
the effective tools include `subagent`.

To disable a bundled role without copying its definition, use a minimal global
override:

```markdown
---
name: reviewer
enabled: false
---
```

The `/subagents overrides` menu exposes the same enable and disable operations.
Removing the `enabled` line inherits the bundled value; when no source declares
the field, the effective value is `true`.

## See also

- [Customizing bundled agents](../guides/customizing-agents.md)
- [Handoffs and files](../guides/handoffs.md)
- [Delegation](../concepts/delegation.md)
