# Write your own agent

An agent type is one Markdown file: YAML frontmatter on top, system prompt below.

## 1. Pick a location

| Scope   | Directory                                                                                   |
| ------- | ------------------------------------------------------------------------------------------- |
| User    | `<pi-agent-dir>/subagent-manager/agents/` (normally `~/.pi/agent/subagent-manager/agents/`) |
| Project | `<cwd>/.pi/agent/subagent-manager/agents/` — loaded only when pi trusts the project         |

Precedence: **project > user > bundled**. A file with the same `name` as a bundled agent replaces it.

These are the only locations read. Other packages' `~/.pi/agent/agents` or `.pi/agents` are ignored — use [`/agents import`](importing-agents.md) for those.

## 2. Write the file

`~/.pi/agent/subagent-manager/agents/api-scout.md`:

```markdown
---
name: api-scout
description: Investigate APIs and find evidence before implementation
thinkingLevel: high
models:
  - anthropic/claude-sonnet-4-6
  - openai/gpt-5
tools:
  allow: [read, grep, find, ls, agent_update, agent_pause]
---

You are an API scout. Read the relevant source and docs,
report concrete findings with file paths, and do not modify files.
```

## 3. Load it

Run `/agents reload`. Diagnostics show any errors. Or just start a new turn — definitions reload after model turns.

Ask the main model to use it: _"spawn an api-scout at `stripe-webhooks` to check how retries work"_.

## Fields

| Field              | Required | What it does                                                                                                                                                        |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`             | yes      | Type name used in `agent_spawn`                                                                                                                                     |
| `description`      | yes      | Shown to the parent model so it knows when to pick this type                                                                                                        |
| `models`           | no       | Ordered `provider/model-id` preferences. How they're used depends on [Model Picking](settings.md#model-picking-modelselection). Omit to inherit the parent's model. |
| `thinkingLevel`    | no       | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Clamped to what the model supports.                                                                      |
| `tools`            | no       | `allow` / `block` lists of exact tool names. Applied per [Tool Filtering](settings.md#tool-filtering-toolfiltering).                                                |
| `color`            | no       | pi semantic color (`accent`, `success`, `warning`, `error`, `muted`, `dim`) for the type pill and path. Default `accent`.                                           |
| `modelSuggestions` | no       | Plain model names (e.g. `sonnet-5.5`) that rank the model picker's search. **Never** select a model at runtime.                                                     |
| `model`            | no       | Deprecated single-model alias. Still parsed; saved back as `models`.                                                                                                |

The Markdown body is the system prompt.

## Tips

- **Tools default to none.** With default filtering, an empty or missing `allow` list means the agent gets no tools. List what it needs.
- **To delegate**, a type needs `agent_spawn` and `agent_wait` in `allow`.
- **Include `agent_update` / `agent_pause`** so the agent can report progress or hand back early.
- **Model matching is exact.** If no preference is available (or scoped, in scoped mode), spawn fails — no silent fallback.
- **Unknown tool names fail** rather than widening access.
- **Edits affect new threads only.** Running and retained threads keep the definition they started with.

## Editing in the TUI

`/agents types` opens a browser and two-column editor.

| Key      | Action                                         |
| -------- | ---------------------------------------------- |
| ↑↓ / Tab | Select field                                   |
| Enter    | Edit field                                     |
| Ctrl+S   | Save (or apply a multiline field to the draft) |
| Esc      | Discard draft                                  |

The model picker lists selected models first, in fallback order. **Enter** toggles a model, **Ctrl+↑/↓** reorders, typing filters. Unselected models are ranked by fuzzy match against `modelSuggestions`, scoped models first.

**External editor** opens the whole file in `$VISUAL`, `$EDITOR`, or `vi`.

## Errors

- Malformed files and duplicate names in the same scope show diagnostics and disable only the affected type.
- An unavailable tool or model fails the spawn with a clear message.
