Skill、Subagent、ToolSearch 与初始工具
skill 的发现与触发、subagent 的启动与隔离、ToolSearch 的延迟工具加载。初始工具集合以 2.1.233 制品为准。
1. Skill 的发现与触发#
skill 如何被发现
skills/loadSkillsDir.ts 支持多来源:
- managed skills:
<managed>/.claude/skills - user skills:
~/.claude/skills - project skills:从当前目录向上查
.claude/skills --add-dir额外目录中的.claude/skills- legacy
/commands目录中的 markdown/SKILL.md - plugin skills
- bundled skills
- MCP skills:MCP
skill://resource 或 prompt 转换而来
新格式只支持:
.claude/skills/<skill-name>/SKILL.md
frontmatter 解析字段包括:description、when_to_use、allowed-tools、argument-hint / arguments、model、disable-model-invocation、user-invocable、hooks、context: fork、agent、effort、paths、shell。
条件 skill 与动态发现
skill 不是只在启动时加载:
- 带
pathsfrontmatter 的 conditional skills 会先存入conditionalSkills,不立即暴露。 activateConditionalSkillsForPaths(filePaths, cwd)用 gitignore 风格匹配路径,命中后加入 dynamic skills。discoverSkillDirsForPaths()会在文件操作路径向上查嵌套.claude/skills,跳过 gitignored 目录。addSkillDirectories()动态加载后触发skillsLoaded.emit(),其他缓存可清理。
这解释了为什么 Claude Code 会在读/写某些目录后突然知道新的项目局部 skill。
skill 什么时候触发
有三类触发:
- 用户显式 slash command:
/skill-name args经processSlashCommand.tsx展开。若 skill frontmattercontext: fork,会作为 forked slash command 在 subagent 中跑。 - 模型主动调用
Skilltool:tools/SkillTool/SkillTool.ts暴露Skill({ skill, args }),模型根据 tool prompt 中的 skill 名称/描述/when_to_use 判断是否调用。 - agent frontmatter 预加载:agent definition 可写
skills: [...],runAgent.ts启动 subagent 时会把这些 skill 内容作为初始 meta message 注入。
SkillTool 的执行形态
SkillTool 有两种执行:
- inline:把 skill markdown 展开成新的 user/meta messages,返回
Launching skill,后续主 query loop 继续处理。 - fork:如果 command
context === 'fork',通过executeForkedSkill()启动 subagent,执行完返回 result 文本。
权限上:SkillTool.checkPermissions() 先检查 Skill(name) deny/allow 规则;远程 canonical skill 可自动 allow,但 deny 仍优先;如果 skill 只有安全字段,自动 allow,否则默认 ask,并给出 exact/prefix allow suggestion;skill 的 allowed-tools 会在展开后作为 command/session allow rules 加到权限上下文中。
2. Subagent 的触发与逻辑#
触发入口
主要入口是 Agent tool:tools/AgentTool/AgentTool.tsx。输入字段包括:description、prompt、subagent_type、model、run_in_background、team/swarm 字段(name、team_name、mode)、isolation(worktree / ant-only remote)、assistant mode 下的 cwd。如果开启 FORK_SUBAGENT,省略 subagent_type 会走 fork path;否则默认 general-purpose。
agent 如何被发现
tools/AgentTool/loadAgentsDir.ts:
- built-in agents
- plugin agents
- user/project/policy/flag agents,来自
.claude/agentsmarkdown - active agent 采用覆盖顺序:built-in < plugin < user < project < flag < managed(后写覆盖同名)
- 支持 frontmatter:tools/disallowedTools、model、permissionMode、mcpServers、hooks、maxTurns、skills、memory、background、isolation 等。
Agent tool prompt 会把可用 agent 列给模型;启用 shouldInjectAgentListInMessages() 时列表改由 agent_listing_delta attachment 注入,以减少工具 schema cache bust。
正常 subagent 与 fork subagent
正常 subagent:使用选中 agent 自己的 system prompt;默认新上下文,只收到 parent 写进 prompt 的信息;tool pool 由 assembleToolPool() 按 agent permission mode 和 tools/disallowedTools 重新计算;thinking 通常关闭以控成本。
fork subagent:省略 subagent_type 触发;继承父会话完整消息前缀和父 system prompt,目标是 prompt cache 命中;buildForkedMessages() 会复制父 assistant 的所有 tool_use,再补统一 placeholder tool_result,最后追加本 fork directive;所有 fork 强制 async,避免主线程等待;fork child 禁止递归 fork(通过 querySource 和 fork boilerplate message 检测)。
sync、async、background、worktree、remote
AgentTool 会决定 shouldRunAsync:用户 run_in_background、agent definition background: true、coordinator mode、fork subagent gate、assistant/KAIROS/proactive 模式;CLAUDE_CODE_DISABLE_BACKGROUND_TASKS 关闭后台任务。
- sync agent:主线程等待,但注册 foreground task,可被 background。
- async agent:注册
LocalAgentTask,独立 abort controller,完成后 enqueue task notification,父 agent 在后续 turn 接收结果。 - worktree isolation:创建临时 git worktree;完成后若无改动自动删除,有改动保留并通知。
- remote isolation:ant-only,走 CCR/teleport,注册
RemoteAgentTask。
subagent 的权限与状态隔离
utils/forkedAgent.ts 的 createSubagentContext() 是关键:
- 默认 clone
readFileState,新建nestedMemoryAttachmentTriggers、dynamicSkillDirTriggers、discoveredSkillNames。 - 默认子 abort controller 绑定父 abort;async agent 可传独立 controller。
- 默认
setAppStateno-op,避免后台 agent 改主 UI;但 task 相关通过setAppStateForTasks回到 root store。 - 默认设置
shouldAvoidPermissionPrompts,后台不可交互时 ask 会转 deny;bubble/可交互 agent 例外。 - local denial tracking 给 async subagent 单独计数。
3. Tool Search 机制#
为什么需要 ToolSearch
MCP 工具和大型工具 schema 可能非常多、非常长。utils/toolSearch.ts 让工具"先只暴露名字,按需加载完整 schema"。这样减少:初始工具定义 tokens、MCP 连接变化导致的 prompt cache bust、大量 MCP tools 超过 API 工具数量/上下文限制的风险。
哪些工具会 defer
tools/ToolSearchTool/prompt.ts:
alwaysLoad === true永不 defer。MCP 可通过_meta['anthropic/alwaysLoad']设置。- MCP tools 默认 defer。
tool.shouldDefer === true的普通工具 defer。ToolSearch自己永不 defer。- fork subagent 开启时
Agent不 defer,因为第一轮必须可用。 - Brief、SendUserFile 等核心通信工具也避免 defer。
开关与兼容
ENABLE_TOOL_SEARCH 解析:unset 默认 tst(启用);true 启用;false 关闭;auto / auto:N 达到 deferred tool token 阈值才启用(auto:0 永远启用,auto:100 关闭)。还会检查:模型是否支持 tool_reference(默认 haiku 不支持)、CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS 强制关闭、非 first-party proxy 且用户未显式启用时保守关闭、ToolSearchTool 本身被 disallowed 也关闭。
搜索与加载流程
getDeferredToolsDelta()扫描历史 attachment,计算新增/移除 deferred tool 名称,以deferred_tools_deltaattachment 告诉模型。- 模型调用
ToolSearch({ query })。 - query 支持:
select:Read,Edit,Grep精确选择;普通关键词搜索;+slack send表示 slack 必须匹配,其它词排序。 - 搜索会匹配工具名、MCP server/action 名、tool prompt/description、
searchHint。 - 返回结果不是普通文本,而是
tool_referenceblocks;API 会把这些 reference 展开成完整工具 schema。 extractDiscoveredToolNames()从历史 tool_reference 和 compact boundary metadata 中恢复已发现工具集合,compact 后不丢。
4. Claude Code 初始工具有哪些#
getAllBaseTools() 是全集。下表是 2.1.233 外部常见会看见的核心工具(还要过 isEnabled / 权限 / 模型门控):
| 工具 | 作用 | 备注 |
|---|---|---|
Agent | 启动 subagent / fork / background agent | legacy alias Task |
TaskOutput | 读取后台 task 输出 | 用于 async agent/shell 等 |
Bash | shell 命令 | 权限与 sandbox 最复杂 |
Glob | 文件 glob 搜索 | 如果构建内置 bfs/ugrep,可能不出现 |
Grep | 内容搜索 | 同上 |
ExitPlanMode | 退出 plan mode | V2 tool |
Read | 读文件/图片/PDF | 文件内容进入上下文 |
Edit | 精确编辑文件 | 旧模型必须先 Read;2.1.208 起新模型可跳过 |
Write | 创建/覆盖文件 | 2.1.228 起新模型对齐 Edit;旧模型既有文件仍须先 Read |
NotebookEdit | 编辑 notebook | notebook 专用 |
WebFetch | 抓取 URL | domain 权限 |
TodoWrite | 写任务清单 | v1;默认关,ENABLE_TASKS=0 回退。见 Todo 门控 |
WebSearch | Web 搜索 | provider/gate 影响 |
TaskStop | 停止任务 | 后台任务控制 |
AskUserQuestion | 向用户提问/结构化问题 | bypass 下仍要人;auto 默认交给分类器 |
Skill | 模型调用 skill | skill 发现后由模型触发 |
EnterPlanMode | 进入 plan mode | 权限模式相关 |
SendMessage | 给 agent/team 发送消息 | 通过 lazy require 加入 |
Brief | assistant/KAIROS 通信简报工具 | 是否启用看 feature |
ListMcpResources | 列 MCP resources | 基础 MCP resource 工具 |
ReadMcpResource | 读 MCP resource | 基础 MCP resource 工具 |
ToolSearch | 按需加载 deferred tools | 默认可能启用,受模型/provider/env 影响 |
memory_list / read / write | 项目记忆存取 | 连上的 project memory store,不是 auto-memory 那条 Write 路径 |
Workflow | 工作流 | 2.1.233 工具表 |
Monitor | 监视 | 2.1.233 工具表 |
PowerShell | Windows shell | 没 Git Bash 默认开 |
条件/内部/实验工具还包括:REPL、LSP、worktree 的 EnterWorktree/ExitWorktree、Workflow、Cron 三件套、Monitor、PushNotification 等。Tungsten / WebBrowser 不在 2.1.233 工具表。PowerShell:Windows 没 Git Bash 默认开,有则看 tengu_cobalt_ridge。Todo v2 四件套默认给未门控模型;2.1.233 起 Opus 4.8 / Sonnet 5 等需 CLAUDE_CODE_ENABLE_TODO_TOOLS=1。TeamCreate/TeamDelete 已在 2.1.178 移除。Config 不在 2.1.233 工具表里。
注意:真正发给模型的工具列表还会被 isEnabled()、permission blanket deny、allowed/disallowed tools、agent 工具限制、ToolSearch defer、MCP 连接状态共同过滤。因此 getAllBaseTools() 是全集,单次请求里的工具子集会更小。