Custom Agents
Custom agents are specialized AI personas defined as markdown files with YAML frontmatter. Each agent has its own system prompt, tool allowlist, model, permission mode, MCP servers, hooks, persistent memory, and color identity.
.md file in .claude/agents/
and it becomes an immediately available agent. The YAML frontmatter configures everything — tools, model,
memory, hooks, MCP — and the markdown body is the system prompt. No code required.
Agent Definition Types & Priority
4 definition types
| Type | Source | Prompt |
|---|---|---|
| Built-in | builtInAgents.ts | Dynamic (function) |
| Custom | .claude/agents/*.md | Static (markdown body) |
| Plugin | plugin/agents/*.md | Static + variable substitution |
| Flag | --agents CLI flag | JSON (static) |
Discovery priority (higher wins)
A project agent with the same name as a built-in will override it. CLAUDE_CODE_SIMPLE=true skips all custom agents.
Agent File Format
File location: .claude/agents/my-agent.md
---
name: my-agent
description: Use this agent for code reviews.
Checks security, performance, and best practices.
tools:
- Read
- Grep
- Glob
- Bash
disallowedTools:
- Write
- Edit
model: opus
color: red
memory: project
maxTurns: 20
---
You are a specialized code reviewer. Your job is
to review code changes for security vulnerabilities,
performance issues, and best practices.
## Guidelines
1. Always check for OWASP top 10
2. Look for N+1 query patterns
3. Check for proper error handling System prompt construction
Default prompt fallback
If no body is provided, the agent uses DEFAULT_AGENT_PROMPT: a general-purpose task-completion prompt that instructs the agent to use available tools, complete the task fully, and return a concise report.
Complete Frontmatter Schema
Required fields
| Field | Description |
|---|---|
| name | Unique identifier → agentType. Used for subagent_type selection. |
| description | whenToUse text shown to the model. Supports \n for newlines. |
Optional fields
| Field | Default | Values / Notes |
|---|---|---|
| tools | All tools | String or array. []=none, *=all |
| disallowedTools | None | Denylist applied on top of allowlist |
| model | Inherit | sonnet, opus, haiku, inherit, or full model ID |
| effort | Inherit | low, medium, high, max |
| permissionMode | Inherit | default, acceptEdits, bypassPermissions, dontAsk, plan, auto |
| color | None | red, blue, green, yellow, purple, orange, pink, cyan |
| maxTurns | No limit | Positive integer |
| background | false | Always run as background task |
| initialPrompt | None | Prepended to first user turn (main-thread use) |
| memory | None | user, project, local |
| isolation | Same CWD | worktree — isolated git worktree, auto-cleaned |
| hooks | None | Session-scoped, all 27 events supported |
| mcpServers | None | String refs or inline server definitions |
| skills | None | Skill names to preload (content injected before first turn) |
Tool configuration
Resolution flow
tools undefined → all tools (full toolset)tools: [] → no toolstools: ["*"] → all toolsdisallowedTools applied as denylist on top# Read-only agent
tools:
- Read
- Grep
- Glob
disallowedTools:
- Agent
- Write
- Edit
- Bash
# MCP tools (full name required)
tools:
- Bash
- Read
- mcp__github__create_issue
- mcp__slack__search_public MCP Servers & Memory
MCP server configuration
Reference existing servers
mcpServers:
- slack # Uses "slack" from user/project config
- github # Shares connection, NOT cleaned up on finish Inline definition
mcpServers:
- my-api:
type: http
url: https://api.example.com/mcp
headers:
Authorization: Bearer `${API_TOKEN}`
# Newly created for agent, cleaned up when finished Mixed
mcpServers:
- slack # reference
- custom: # inline
command: node
args: ["`${plugin_root}`/server.js"] 3 memory scopes
| Scope | Directory | VCS |
|---|---|---|
| user | ~/.claude/agent-memory/<name>/ | No |
| project | <cwd>/.claude/agent-memory/<name>/ | Yes |
| local | <cwd>/.claude/agent-memory-local/<name>/ | No |
How memory works
loadAgentMemoryPrompt() loads MEMORY.md index → appended to system promptuser)Memory snapshots (VCS distribution)
Stored at <cwd>/.claude/agent-memory-snapshots/<agentType>/. On load: if no local memory but snapshot exists, copies snapshot to local. Teams can commit snapshots to share baseline agent knowledge.
Hooks Per-Agent
Frontmatter hooks example
---
name: formatter
hooks:
PostToolUse:
- matcher: "Write|Edit"
hooks:
- type: command
command: "prettier --write \"$(cat | jq -r '.tool_input.file_path')\""
timeout: 10
statusMessage: "Formatting..."
Stop:
- hooks:
- type: command
command: "npm test"
--- Behavior
Stop hooks auto-converted to SubagentStopstrictPluginOnlyCustomization, only admin-trusted sources can register hooksAll 27 hook events are supported in agent frontmatter.
Agent Invocation
AgentTool input schema
{
description: string // 3-5 words (REQUIRED)
prompt: string // Full task prompt (REQUIRED)
subagent_type?: string // Agent name (default: general-purpose)
model?: 'sonnet'|'opus'|'haiku'
run_in_background?: boolean
name?: string // For multi-agent teams
team_name?: string
mode?: PermissionMode // Override for teammate
isolation?: 'worktree'
cwd?: string // Working dir (KAIROS only)
} Execution flow (10 steps)
Fork vs Fresh agent
| Aspect | Fork (no subagent_type) | Fresh (with subagent_type) |
|---|---|---|
| History | Inherits parent context | Starts empty |
| Tools | Exact parent pool | Agent-defined |
| System prompt | Parent's prompt | Agent's markdown |
| Context window | Shared with parent | Fresh |
| Purpose | Background work without flooding parent | Specialized execution |
Isolation modes
Plugin Agent Restrictions & Built-in Agents
Plugin agent security restrictions
| Field | Status |
|---|---|
| permissionMode | IGNORED — cannot escalate beyond install-time trust |
| hooks | IGNORED — cannot register custom hooks |
| mcpServers | IGNORED — cannot define MCP servers |
| All other fields | Allowed (name, tools, model, color, etc.) |
Plugin agent names are namespaced: pluginName:agentName (e.g., my-plugin:test-runner).
JSON agent definitions (--agents flag)
All frontmatter fields available as JSON object keys. Multiple agents per JSON object.
Agents CANNOT be defined in settings.json — there is no agents key in the settings schema.
Built-in agents (6)
| Agent | Model | Key features |
|---|---|---|
| general-purpose | Inherit | All tools, research & multi-step tasks |
| Explore | Haiku | Read-only, fast codebase search, omits CLAUDE.md |
| Plan | Inherit | Read-only, architecture planning, omits CLAUDE.md |
| claude-code-guide | Haiku | Docs lookup, dontAsk permission mode |
| statusline-setup | Sonnet | Only Read + Edit tools, orange color |
| verification | Inherit | Background, VERDICT output, feature-gated, red |
CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS=true disables all built-in agents (non-interactive only).
Practical Examples
Security reviewer (read-only, opus)
---
name: security-review
description: Use for security reviews of code.
Checks OWASP top 10, injection, auth, data exposure.
tools: [Read, Grep, Glob, Bash]
disallowedTools: [Write, Edit, Agent]
color: red
model: opus
---
You are a security code reviewer... Deploy agent (MCP + maxTurns)
---
name: deployer
description: Use to deploy code to staging or prod.
Requires deploy-server MCP to be connected.
tools: [Bash, Read, Grep]
mcpServers:
- deploy-server
color: orange
permissionMode: default
maxTurns: 20
---
You are a deployment specialist... Learning agent (user memory)
---
name: tutor
description: Use to learn about the codebase.
Remembers what the user has learned.
tools: [Read, Grep, Glob]
memory: user
color: green
effort: high
---
You are a patient coding tutor... Auto-formatter (per-agent hooks)
---
name: formatter
description: Use when writing code that needs
auto-formatting after every file edit.
hooks:
PostToolUse:
- matcher: "Write|Edit"
hooks:
- type: command
command: "prettier --write \"$(cat | jq -r '.tool_input.file_path')\""
timeout: 10
---
You write clean code. Prettier formats automatically. /agents Command
Interactive management UI
Built-in and plugin agents are shown but marked non-editable.
Agent creation wizard (7 steps)
description field is the only signal the model uses to decide
which agent to pick. Write it as "Use this agent when..." followed by specific, concrete scenarios.
Vague descriptions lead to poor agent selection. Supports \n for multi-line formatting
in the agent list shown to the model.