Custom Agents
A custom agent is a reusable, named agent definition: a markdown file that gives an agent a description, a specialization prompt, and optional limits on its tools, permissions, and model. Once defined, a custom agent can be used two ways:
- As a subagent type: when the agent delegates work, it can pick your custom agent by name and the subagent runs with that definition's prompt and limits.
- As the main session: launch
pw code --agent <name>to run a definition as the agent you talk to directly.
Where Definitions Live
pw code looks for .md definition files in these directories, in order (when the same agent name appears in more than one place, the earlier directory wins):
<workspace>/.agents/agents/: project definitions, checked in with your code~/.config/agents/agents/: your personal definitions (respectsXDG_CONFIG_HOME)
Directories are scanned recursively, so you can organize definitions into subfolders. An agent's identity comes from its name field (or its filename), never its path. The name fork is reserved for conversation forks; a definition named fork is ignored with a warning.
Project definitions require approval
Definition files in the workspace are part of the configuration pw code asks you to approve at launch. See Workspace Trust.
File Format
A definition is YAML frontmatter followed by a markdown body. The body is the agent's specialization prompt. It is appended to the standard system prompt, so the agent keeps all its normal abilities and gains your specialization on top.
| Field | Meaning |
|---|---|
name | The agent's name. Defaults to the filename without .md. |
description | What this agent is for. This is how the main agent decides when to delegate to it. Write it like a job description. |
tools | Comma-separated allowlist of tool names the agent may use (for example ReadFile, GrepSearch, GlobSearch, Bash). Empty means all tools. |
disallowedTools | Comma-separated denylist. Deny always wins over tools. |
model | Model this agent runs on (owner:provider-name/model-name). Empty inherits; see model resolution. |
permissionMode | Requested permission mode: read-only, plan, accept-edits, or bypass-permissions. Can narrow the session's mode, never widen it (see Permission Clamping). |
isolation | worktree runs the agent's delegated tasks in a temporary git worktree, keeping its changes out of your working tree. |
maxTurns | Cap on agentic iterations per delegated task. Unset means unlimited. |
background | true forces this agent's tasks to always run detached, even when an inline result was requested. |
color | Display color for the agent's switcher dot and task blocks: blue, green, yellow, purple, cyan, orange, pink, or red. |
initialPrompt | Auto-submitted as the first message when the definition runs as the main session via --agent. |
Frontmatter values are single-line. isolation, background, and color shape how the agent behaves and displays when it runs as a subagent; they do not apply to a --agent main session.
Example Definition
.agents/agents/reviewer.md:
---
name: reviewer
description: Reviews code changes for correctness, style, and missed edge cases. Use for read-only review passes over a diff or a set of files.
tools: ReadFile, GrepSearch, GlobSearch, Bash
permissionMode: read-only
model: owner:provider-name/model-name
color: purple
maxTurns: 30
---
You are a meticulous code reviewer.
Review the changes you are pointed at for:
- Correctness bugs and unhandled edge cases
- Consistency with the surrounding code's style and conventions
- Missing or misleading tests
Report findings as a prioritized list. Cite file paths and line numbers.
Do not modify any files.Using a Custom Agent for Delegated Work
You do not invoke a custom agent directly. The main agent sees every definition's name and description and picks the right type when it delegates. You can also steer it explicitly: "use the reviewer agent to check this diff."
In the agent switcher, a custom agent's row shows its type name next to its task description, and its task block in the transcript is titled with the type name instead of Task. The definition's color (or an automatically assigned one) marks its dot in both places.
Worktree Isolation
An agent defined with isolation: worktree runs its delegated tasks in a temporary git worktree (a separate checkout of your repository) so its changes never touch your working tree while you and other agents keep working. This requires the workspace to be a git repository with at least one commit; when a worktree cannot be created, the task falls back to sharing the workspace and says so in its task block.
The subagent's report names the worktree path so you (and the main agent) know where its changes live. A worktree with no changes is cleaned up automatically; a worktree holding uncommitted changes or new commits is kept, and resuming the session later puts the revived subagent back inside it.
Running a Definition as the Main Session
Launch a definition as the agent you talk to:
pw code --agent reviewer- The definition's
modelandpermissionModeare used unless you override them on the command line. - Its
tools,disallowedTools, andmaxTurnslimits apply exactly as they would to a subagent. - Its body is appended to the system prompt as the session's specialization.
- Its
initialPrompt, if set, is submitted automatically as the first message; in a one-shot run (-p), it is prepended to your prompt instead.
Naming an agent that does not exist fails with the list of available names.
Ad-Hoc Definitions with --agents
--agents takes JSON definitions keyed by name: the same fields as frontmatter, with tools and disallowedTools as arrays and the specialization body in a prompt field. They merge over the definition files (an ad-hoc definition with the same name wins) and are available both for delegation and for --agent:
pw code --agents '{
"changelog": {
"description": "Drafts changelog entries from recent commits",
"tools": ["ReadFile", "Bash"],
"permissionMode": "read-only",
"prompt": "You draft concise changelog entries. Read git log and summarize user-facing changes."
}
}'Permission Clamping for Definition Authors
A custom agent can restrict what a subagent may do, but it can never grant more than the session it runs in:
- Modes only narrow. Modes rank
read-only<plan<accept-edits<bypass-permissions. If a definition requests a mode above the session's, it is clamped down to the session's mode, and the clamp is noted in the subagent's task block. Aread-onlydefinition stays read-only in any session. The requested mode also acts as a live ceiling: if the session's mode changes while the subagent is running, the subagent follows the change, up to the definition's requested mode and never past the session. - Tool scope only narrows. Allowlists intersect with what the spawning agent may use, and denylists accumulate across every generation, so even with nesting enabled a restricted agent can never spawn a subagent with tools it lacks itself. A definition whose
toolslist has nothing in common with the spawning agent's tools is unusable from that agent, and delegation to it fails with an explanation. - Approvals stay per-agent. When a subagent's command needs approval, the prompt names that agent, and your approval applies to that subagent only.
Write definitions assuming the narrowest session they might run in, and treat permissionMode and tools as guardrails for the agent's role: a reviewer that cannot write files, a researcher that cannot run shell commands. See Permissions for how modes and approvals work.
Related Documentation
- pw code Overview: Feature overview and quick start
- Subagents: Delegation, the agent switcher, follow-ups, and limits
- Permissions: Permission modes and approvals
- Models & Allocations: Model IDs and choosing models
- Settings: Subagent-related settings
- Project Instructions: Per-project guidance for the agent
- Non-Interactive Mode: One-shot runs with -p