Files

213 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [自定义Agent, Agent定义, Markdown, Agent配置, 角色定制]
create time: 2026-06-09 22:30
---
# 自定义 Agent - 从 Markdown 到运行时的完整链路
## 概述
揭秘 Claude Code 自定义 Agent 完整链路:Agent 定义的 Markdown 数据模型、三种加载来源、工具过滤策略和与 AgentTool 的联动机制。
## 正文
### Agent 定义的三种来源
Claude Code 的 Agent 不仅仅来自用户自定义——系统有三类来源,按优先级合并:
| 来源 | 位置 | 优先级 |
|------|------|--------|
| **Built-in** | `packages/builtin-tools/src/tools/AgentTool/built-in/` 硬编码 | 最低(可被覆盖) |
| **Plugin** | 通过插件系统注册 | 中 |
| **User/Project/Policy** | `.claude/agents/*.md` 或 settings.json | 最高 |
合并逻辑在 `getActiveAgentsFromList()` 中:按 `agentType` 去重,后者覆盖前者。这意味着你可以在 `.claude/agents/` 中放一个 `Explore.md` 来完全替换内置的 Explore Agent。
### Markdown Agent 文件的完整格式
```markdown
---
# === 必需字段 ===
name: "reviewer" # Agent 标识(agentType)
description: "Code review specialist, read-only analysis"
# === 工具控制 ===
tools: "Read,Glob,Grep,Bash" # 允许的工具列表(逗号分隔)
disallowedTools: "Write,Edit" # 显式禁止的工具
# === 模型配置 ===
model: "haiku" # 指定模型(或 "inherit" 继承主线程)
effort: "high" # 推理努力程度:low/medium/high 或整数
# === 行为控制 ===
maxTurns: 10 # 最大 agentic 轮次
permissionMode: "plan" # 权限模式:plan/bypassPermissions 等
background: true # 始终作为后台任务运行
initialPrompt: "/search TODO" # 首轮用户消息前缀(支持斜杠命令)
# === 隔离与持久化 ===
isolation: "worktree" # 在独立 git worktree 中运行
memory: "project" # 持久记忆范围:user/project/local
# === MCP 服务器 ===
mcpServers:
- "slack" # 引用已配置的 MCP 服务器
- database: # 内联定义
command: "npx"
args: ["mcp-db"]
# === Hooks ===
hooks:
PreToolUse:
- command: "audit-log.sh"
timeout: 5000
# === Skills ===
skills: "code-review,security-review" # 预加载的 skills(逗号分隔)
# === 显示 ===
color: "blue" # 终端中的 Agent 颜色标识
---
你是代码审查专家。你的职责是...
(正文内容 = system prompt)
```
#### 字段解析细节
- **`tools`**:通过 `parseAgentToolsFromFrontmatter()` 解析,支持逗号分隔字符串或数组
- **`model: "inherit"`**:使用主线程的模型(区分大小写,只有小写 "inherit" 有效)
- **`memory`**:启用后自动注入 `Write`/`Edit`/`Read` 工具(即使 `tools` 未包含),并在 system prompt 末尾追加 memory 指令
- **`isolation: "remote"`**:仅在 Anthropic 内部可用(`USER_TYPE === 'ant'`),外部构建只支持 `worktree`
- **`background`**:`true` 使 Agent 始终在后台运行,主线程不等待结果
### 加载与发现机制
`getAgentDefinitionsWithOverrides()`(被 `memoize` 缓存)执行完整的发现流程:
```mermaid
flowchart TD
A["1. 加载 Markdown 文件"] --> B["loadMarkdownFilesForSubdir('agents', cwd)"]
B --> C["~/.claude/agents/*.md 用户级 source='userSettings'"]
B --> D[".claude/agents/*.md 项目级 source='projectSettings'"]
B --> E["managed/policy sources 策略级 source='policySettings'"]
A --> F["每个 .md 文件"]
F --> G["解析 YAML frontmatter"]
F --> H["正文作为 system prompt"]
F --> I["校验必需字段 name/description"]
F --> J["静默跳过无 frontmatter 的 .md 文件"]
F --> K["解析失败 -> 记录到 failedFiles,不阻塞其他 Agent"]
A --> L["2. 并行加载 Plugin Agents"]
L --> M["loadPluginAgents() memoized"]
A --> N["3. 初始化 Memory Snapshots"]
N --> O["initializeAgentMemorySnapshots()"]
A --> P["4. 合并 Built-in + Plugin + Custom"]
P --> Q["getActiveAgentsFromList() 按 agentType 去重,后者覆盖前者"]
Q --> R["5. 分配颜色"]
R --> S["setAgentColor(agentType, color)"]
```
### 工具过滤的实现
当 Agent 被派生时,`AgentTool` 根据定义中的 `tools` / `disallowedTools` 过滤可用工具列表:
```mermaid
flowchart TD
A["全部工具"] --> B["disallowedTools 移除"]
B --> C{"tools 指定?"}
C -->|"是"| D["tools 白名单过滤"]
C -->|"否"| E["全部保留"]
D --> F["可用工具"]
E --> F
```
- **`tools` 未指定**:Agent 可以使用所有工具(默认全能)
- **`tools` 指定**:只能使用列出的工具
- **`disallowedTools`**:即使 `tools` 未指定,这些工具也被禁止
- **自动注入**:`memory` 启用时自动添加 `Write`/`Edit`/`Read`
以内置 Explore Agent 为例:
```typescript
// packages/builtin-tools/src/tools/AgentTool/built-in/exploreAgent.ts
disallowedTools: [
'Agent', // 不能嵌套调用 Agent
'ExitPlanMode', // 不需要 plan mode
'FileEdit', // 只读
'FileWrite', // 只读
'NotebookEdit', // 只读
]
```
### System Prompt 的注入方式
Agent 的 system prompt 通过 `getSystemPrompt()` 闭包延迟生成:
```typescript
// Markdown Agent
getSystemPrompt: () => {
if (isAutoMemoryEnabled() && memory) {
return systemPrompt + '\n\n' + loadAgentMemoryPrompt(agentType, memory)
}
return systemPrompt
}
```
这意味着:
1. **Markdown 正文 = 完整的 system prompt**——不是追加,而是替换默认 prompt
2. **Memory 指令**在 memory 启用时自动追加到末尾
3. **闭包延迟计算**——memory 状态可能在文件加载后才变化
对于 Built-in Agent,`getSystemPrompt` 接受 `toolUseContext` 参数,可以根据运行时状态(如是否使用嵌入式搜索工具)动态调整 prompt 内容。
### 与 AgentTool 的联动
当主 Agent 需要派生子 Agent 时:
```mermaid
flowchart TD
A["AgentTool.call({ subagent_type: 'reviewer', ... })"] --> B["从 agentDefinitions.activeAgents 查找 agentType === 'reviewer'"]
B --> C["检查 requiredMcpServers"]
C --> D["过滤工具列表 tools/disallowedTools"]
D --> E{"解析模型"}
E -->|"'inherit'"| F["使用主线程模型"]
E -->|"具体模型名"| G["直接使用"]
E -->|"未指定"| F
E --> H["解析权限模式 permissionMode"]
H --> I["构建隔离环境 isolation === 'worktree'"]
I --> J["注入 system prompt getSystemPrompt()"]
J --> K["注入 initialPrompt 如果定义了"]
K --> L["启动子 Agent 循环 forkSubagent/runAgent"]
```
### 内置 Agent 参考
| Agent | agentType | 角色 | 工具限制 | 模型 |
|-------|-----------|------|---------|------|
| **General Purpose** | `general-purpose` | 默认子 Agent | 全部工具 | 主线程模型 |
| **Explore** | `Explore` | 代码搜索专家 | 只读(无 Write/Edit) | haiku(外部) |
| **Plan** | `Plan` | 规划专家 | 只读 + ExitPlanMode | inherit |
| **Verification** | `verification` | 结果验证 | 由 feature flag 控制 | — |
| **Code Guide** | `claude-code-guide` | Claude Code 使用指南 | 只读 | — |
| **Statusline Setup** | `statusline-setup` | 终端状态栏配置 | 有限 | — |
> [!tip]
> SDK 入口(`sdk-ts`/`sdk-py`/`sdk-cli`)不加载 Code Guide Agent。环境变量 `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` 可以完全禁用内置 Agent,给 SDK 用户提供空白画布。
### Agent Memory:持久化的 Agent 状态
当 `memory` 字段启用时,Agent 获得跨会话的持久记忆:
- **`local`**:当前项目、当前用户有效
- **`project`**:当前项目所有用户共享
- **`user`**:所有项目共享
Memory 通过 `loadAgentMemoryPrompt()` 注入到 system prompt 末尾,包含读写记忆的指令。Agent Memory Snapshot 机制在项目间同步 `user` 级记忆。
## 关联笔记
- [[claude-code-best/docs/features/extensibility/hooks]]
- [[claude-code-best/docs/features/extensibility/skills]]
- [[claude-code-best/docs/features/fork-subagent]]