Create an agent
A custom agent is one markdown file: YAML frontmatter for the settings, and the body as the system prompt.
---
description: Moves one module to the new API surface, one call site at a time.
mode: primary
model: anthropic/claude-sonnet-5
temperature: 0.1
permission:
bash:
"*": ask
"npm run typecheck": allow
"git diff*": allow
edit:
"*": allow
agent_handoff:
"*": allow
---
You migrate call sites to the new API, one at a time.
For each call site: change it, run the typecheck, and move on only when it is
clean. Never change more than one call site before typechecking. If a call site
needs a decision you can't make from the code, leave it and list it at the end.The filename is the agent id — migrator.md gives you migrator. Ids are global across every source, so pick something unlikely to collide.
You can write the same thing from Settings → Agents → New agent, which saves to the same directory in the same format.
Frontmatter
| Key | Default | Meaning |
|---|---|---|
description | — | One line, shown in the picker and to the task tool. Write it as a selection criterion, not a title. |
mode | subagent | primary, subagent, or all. See modes. |
model | the session's | provider/model, e.g. anthropic/claude-sonnet-5. If it fails to resolve, the agent runs on the current model and logs a warning. |
temperature | the model's | Sampling temperature. |
tools | all tools | Allow-list of tool ids. Read the caveat below before relying on it. |
permission | * → ask | Nested tool → pattern → action. See the gotcha below. |
harness | none | Marks this agent as a stage of one chain. See harness-only agents. |
Everything after the closing --- is the system prompt.
The two things that catch everyone
One more, quieter: a markdown agent with no mode is a subagent, so it won't appear in the picker and can't be a harness stage. Set mode: primary (or all) when you want to select it.
Overriding a built-in
Native agents can't be rewritten, but specific fields can be patched from the config block — no prompt needed:
{
"agent": {
"review": { "model": "anthropic/claude-sonnet-5" },
"test": { "temperature": 0 }
}
}The same block sets harness on a built-in, and "harness": null detaches a shipped harness-only agent so it appears in the picker as an ordinary one.
Deleting
Deleting from Settings → Agents removes the file. It fails with 409 agent_in_use while any harness chain still references the agent — as a stage, an on_failure target, or an acceptance agent. Remove it from the chain first.
Next
- Delegation vs handoff — which mode you need depends on this.
- Build a harness — where custom agents earn their keep.