vault backup: 2026-06-09 23:15:17

This commit is contained in:
2026-06-09 23:15:17 +08:00
parent 31fd89aafe
commit e92c0327d9
111 changed files with 7276 additions and 8846 deletions
@@ -1,12 +1,17 @@
---
title: "自定义 Agent - 从 Markdown 到运行时的完整链路"
description: "揭秘 Claude Code 自定义 Agent 完整链路:Agent 定义的 Markdown 数据模型、三种加载来源、工具过滤策略和与 AgentTool 的联动机制。"
keywords: ["自定义 Agent", "Agent 定义", "Markdown Agent", "Agent 配置", "角色定制"]
tags: [自定义-Agent, Agent-定义, Markdown-Agent, 角色定制, Claude-Code]
create time: 2026-06-09 22:30
---
{/* 本章目标:揭示 Agent 定义的完整数据模型、加载发现机制、工具过滤和与 AgentTool 的联动 */}
# 自定义 Agent - 从 Markdown 到运行时的完整链路
## Agent 定义的三种来源
## 概述
Claude Code 的 Agent 系统支持三种来源(Built-in、Plugin、User/Project/Policy),通过 Markdown 文件定义 Agent 的完整行为——包括工具控制、模型配置、权限模式、隔离策略和 Hooks。本文揭示从 Agent 定义的 Markdown 数据模型到运行时子 Agent 启动的完整链路。
## 正文
### Agent 定义的三种来源
Claude Code 的 Agent 不仅仅来自用户自定义——系统有三类来源,按优先级合并:
@@ -18,7 +23,7 @@ Claude Code 的 Agent 不仅仅来自用户自定义——系统有三类来源
合并逻辑在 `getActiveAgentsFromList()` 中:按 `agentType` 去重,后者覆盖前者。这意味着你可以在 `.claude/agents/` 中放一个 `Explore.md` 来完全替换内置的 Explore Agent。
## Markdown Agent 文件的完整格式
### Markdown Agent 文件的完整格式
```markdown
---
@@ -69,7 +74,7 @@ color: "blue" # 终端中的 Agent 颜色标识
(正文内容 = system prompt)
```
### 字段解析细节
#### 字段解析细节
- **`tools`**:通过 `parseAgentToolsFromFrontmatter()` 解析,支持逗号分隔字符串或数组
- **`model: "inherit"`**:使用主线程的模型(区分大小写,只有小写 "inherit" 有效)
@@ -77,42 +82,34 @@ color: "blue" # 终端中的 Agent 颜色标识
- **`isolation: "remote"`**:仅在 Anthropic 内部可用(`USER_TYPE === 'ant'`),外部构建只支持 `worktree`
- **`background`**:`true` 使 Agent 始终在后台运行,主线程不等待结果
## 加载与发现机制
### 加载与发现机制
`getAgentDefinitionsWithOverrides()`(被 `memoize` 缓存)执行完整的发现流程:
```
1. 加载 Markdown 文件
├── loadMarkdownFilesForSubdir('agents', cwd)
│ ├── ~/.claude/agents/*.md (用户级,source = 'userSettings')
│ ├── .claude/agents/*.md (项目级,source = 'projectSettings')
│ └── managed/policy sources (策略级,source = 'policySettings')
│
└── 每个 .md 文件:
├── 解析 YAML frontmatter
├── 正文作为 system prompt
├── 校验必需字段(name, description)
├── 静默跳过无 frontmatter 的 .md 文件(可能是参考文档)
└── 解析失败 → 记录到 failedFiles,不阻塞其他 Agent
2. 并行加载 Plugin Agents
└── loadPluginAgents() → memoized
3. 初始化 Memory Snapshots(如果 AGENT_MEMORY_SNAPSHOT 启用)
└── initializeAgentMemorySnapshots()
4. 合并 Built-in + Plugin + Custom
└── getActiveAgentsFromList() → 按 agentType 去重,后者覆盖前者
5. 分配颜色
└── setAgentColor(agentType, color) → 终端 UI 中区分不同 Agent
```mermaid
flowchart TD
A["加载 Markdown 文件"] --> B["解析 YAML frontmatter\n正文作为 system prompt"]
B --> C["校验必需字段\nname, description"]
C --> D["并行加载 Plugin Agents"]
D --> E["初始化 Memory Snapshots"]
E --> F["合并 Built-in + Plugin + Custom\n按 agentType 去重, 后者覆盖前者"]
F --> G["分配颜色\nsetAgentColor()"]
```
## 工具过滤的实现
Markdown 文件的加载路径:
- `~/.claude/agents/*.md`(用户级,source = `'userSettings'`)
- `.claude/agents/*.md`(项目级,source = `'projectSettings'`)
- `managed/policy sources`(策略级,source = `'policySettings'`)
> [!tip] 容错处理
> 静默跳过无 frontmatter 的 .md 文件(可能是参考文档),解析失败记录到 failedFiles 不阻塞其他 Agent。
### 工具过滤的实现
当 Agent 被派生时,`AgentTool` 根据定义中的 `tools` / `disallowedTools` 过滤可用工具列表:
```
```text
全部工具
↓ disallowedTools 移除
↓ tools 白名单过滤(如果指定)
@@ -137,7 +134,7 @@ disallowedTools: [
]
```
## System Prompt 的注入方式
### System Prompt 的注入方式
Agent 的 system prompt 通过 `getSystemPrompt()` 闭包延迟生成:
@@ -158,36 +155,24 @@ getSystemPrompt: () => {
对于 Built-in Agent,`getSystemPrompt` 接受 `toolUseContext` 参数,可以根据运行时状态(如是否使用嵌入式搜索工具)动态调整 prompt 内容。
## 与 AgentTool 的联动
### 与 AgentTool 的联动
当主 Agent 需要派生子 Agent 时:
```
AgentTool.call({ subagent_type: "reviewer", ... })
↓
1. 从 agentDefinitions.activeAgents 查找 agentType === "reviewer"
↓
2. 检查 requiredMcpServers(如果 Agent 要求特定 MCP 服务器)
↓
3. 过滤工具列表(tools / disallowedTools)
↓
4. 解析模型:
- "inherit" → 使用主线程模型
- 具体模型名 → 直接使用
- 未指定 → 主线程模型
↓
5. 解析权限模式(permissionMode)
↓
6. 构建隔离环境(如果 isolation === "worktree")
↓
7. 注入 system prompt(getSystemPrompt())
↓
8. 注入 initialPrompt(如果定义了)
↓
9. 启动子 Agent 循环(forkSubagent / runAgent)
```mermaid
flowchart TD
A["AgentTool.call(subagent_type: reviewer)"] --> B["从 agentDefinitions.activeAgents 查找"]
B --> C["检查 requiredMcpServers"]
C --> D["过滤工具列表\ntools / disallowedTools"]
D --> E["解析模型\ninherit / 具体模型名 / 未指定"]
E --> F["解析权限模式 permissionMode"]
F --> G["构建隔离环境\n如果 isolation === worktree"]
G --> H["注入 system prompt"]
H --> I["注入 initialPrompt"]
I --> J["启动子 Agent 循环\nforkSubagent / runAgent"]
```
## 内置 Agent 参考
### 内置 Agent 参考
| Agent | agentType | 角色 | 工具限制 | 模型 |
|-------|-----------|------|---------|------|
@@ -198,14 +183,23 @@ AgentTool.call({ subagent_type: "reviewer", ... })
| **Code Guide** | `claude-code-guide` | Claude Code 使用指南 | 只读 | — |
| **Statusline Setup** | `statusline-setup` | 终端状态栏配置 | 有限 | — |
SDK 入口(`sdk-ts`/`sdk-py`/`sdk-cli`)不加载 Code Guide Agent。环境变量 `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` 可以完全禁用内置 Agent,给 SDK 用户提供空白画布。
> [!info] SDK 限制
> SDK 入口(`sdk-ts`/`sdk-py`/`sdk-cli`)不加载 Code Guide Agent。环境变量 `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` 可以完全禁用内置 Agent,给 SDK 用户提供空白画布。
## Agent Memory:持久化的 Agent 状态
### Agent Memory:持久化的 Agent 状态
当 `memory` 字段启用时,Agent 获得跨会话的持久记忆:
- **`local`**:当前项目、当前用户有效
- **`project`**:当前项目所有用户共享
- **`user`**:所有项目共享
| 范围 | 说明 |
|------|------|
| `local` | 当前项目、当前用户有效 |
| `project` | 当前项目所有用户共享 |
| `user` | 所有项目共享 |
Memory 通过 `loadAgentMemoryPrompt()` 注入到 system prompt 末尾,包含读写记忆的指令。Agent Memory Snapshot 机制在项目间同步 `user` 级记忆。
## 关联笔记
- [[skills|Skills 技能系统]]
- [[hooks|Hooks 生命周期钩子]]
- [[mcp-configuration|MCP 配置]]