Files
cs-note/claude-code-best/docs/tools/what-are-tools.md
T
2026-06-08 23:26:18 +08:00

8.4 KiB
Raw Blame History

title, description, keywords
title description keywords
工具系统设计 - AI 如何从说到做 深入理解 Claude Code 的 Tool 抽象设计:从类型定义、注册机制、调用链路到渲染系统,揭示 50+ 内置工具如何通过统一的 Tool 接口协同工作。
工具系统
Tool 抽象
AI 工具
function calling
buildTool
getTools

{/* 本章目标:基于 src/Tool.ts 和 src/tools.ts 揭示工具系统的完整架构 */}

AI 为什么需要工具

大语言模型本质上只能做一件事:根据输入文本,生成输出文本。

它不能读文件、不能执行命令、不能搜索代码。要让 AI 真正"动手",需要一个桥梁——这就是 Tool(工具)。

工具是 AI 的双手。AI 说"我想读这个文件",工具系统替它真正去读;AI 说"我想执行这条命令",工具系统替它真正去跑。

Tool 类型:35 个字段的统一接口

所有工具都实现 src/Tool.ts:368 的 Tool<Input, Output, Progress> 类型。这不是一个 class,而是一个包含 35+ 字段的结构化类型(structural typing),任何满足该接口的对象就是一个工具:

核心四要素

字段 类型 说明
name string 唯一标识(如 Read、Bash、Agent)
description() (input) => Promise<string> 动态描述——根据输入参数返回不同描述(如 Execute skill: ${skill})
inputSchema z.ZodType Zod schema,定义参数类型和校验规则
call() (args, context, canUseTool, parentMessage, onProgress?) => Promise<ToolResult<Output>> 执行函数

注册与发现

字段 说明
aliases 别名数组(向后兼容重命名)
searchHint 3-10 词的短语,供 ToolSearch 关键词匹配(如 "jupyter" for NotebookEdit)
shouldDefer 是否延迟加载(配合 ToolSearch 按需加载)
alwaysLoad 永不延迟加载(如 SkillTool 必须在 turn 1 可见)
isEnabled() 运行时开关(如 PowerShellTool 检查平台)

安全与权限

字段 说明
validateInput() 输入校验(在权限检查之前),返回 ValidationResult
checkPermissions() 权限检查(在校验之后),返回 PermissionResult
isReadOnly() 是否只读操作(影响权限模式)
isDestructive() 是否不可逆操作(删除、覆盖、发送)
isConcurrencySafe() 相同输入是否可以并行执行
preparePermissionMatcher() 为 Hook 的 if 条件准备模式匹配器
interruptBehavior() 用户中断时的行为:'cancel' 或 'block'

输出与渲染

字段 说明
maxResultSizeChars 结果字符上限(超出则持久化到磁盘,如 100_000)
mapToolResultToToolResultBlockParam() 将 Output 映射为 API 格式的 ToolResultBlockParam
renderToolResultMessage() React 组件渲染工具结果到终端
renderToolUseMessage() React 组件渲染工具调用过程
backfillObservableInput() 在不破坏 prompt cache 的前提下回填可观察字段

上下文与 Prompt

字段 说明
prompt() 返回该工具的详细使用说明,注入到 System Prompt
outputSchema 输出 Zod schema(用于类型安全的结果处理)
getPath() 提取操作的文件路径(用于权限匹配和 UI 显示)

工具注册:getTools() 的分层组装

src/tools.ts 的 getAllBaseTools()(第 195 行)是工具注册的核心:

固定工具(始终可用):
  AgentTool, BashTool, FileReadTool, FileEditTool, FileWriteTool,
  NotebookEditTool, WebFetchTool, WebSearchTool, TodoWriteTool,
  AskUserQuestionTool, SkillTool, EnterPlanModeTool, ExitPlanModeV2Tool,
  TaskOutputTool, BriefTool, ListMcpResourcesTool, ReadMcpResourceTool

条件工具(运行时检查):
  ← hasEmbeddedSearchTools()  ? []       : [GlobTool, GrepTool]
  ← isTodoV2Enabled()         ? V2 Tasks  : []
  ← isWorktreeModeEnabled()   ? Worktree  : []
  ← isAgentSwarmsEnabled()    ? Teams     : []
  ← isToolSearchEnabled()     ? ToolSearch: []
  ← isPowerShellToolEnabled() ? PowerShell: []

Feature-flag 工具:
  ← feature('COORDINATOR_MODE') ? [coordinatorMode tools]
  ← feature('KAIROS')           ? [SleepTool, SendUserFileTool, ...]
  ← feature('WEB_BROWSER_TOOL') ? [WebBrowserTool]
  ← feature('HISTORY_SNIP')     ? [SnipTool]

Ant-only 工具:
  ← process.env.USER_TYPE === 'ant' ? [REPLTool, ConfigTool, TungstenTool]

getTools()(第 274 行)在 getAllBaseTools() 基础上应用权限过滤:

export const getTools = (permissionContext): Tools => {
  const base = getAllBaseTools()
  // 过滤 blanket deny 规则命中的工具
  return filterToolsByDenyRules(base, permissionContext)
}

关键设计:工具列表在每次 API 调用时组装(而非全局缓存),因为 isEnabled() 的结果可能随运行时状态变化。

buildTool() 工厂函数

大多数工具通过 buildTool() 创建(src/Tool.ts:789),它是一个类型安全的构造器:

export const BashTool: Tool<...> = buildTool({
  name: 'Bash',
  inputSchema: lazySchema(() => z.object({command: z.string(), ...})),
  // ...其他字段
}) satisfies ToolDef<Input, Output, Progress>

satisfies ToolDef 确保编译时类型检查,lazySchema 延迟 Zod schema 解析(避免循环依赖)。

工具调用的完整链路

从 AI 发出 tool_use 到结果回传,经过以下步骤:

1. API 返回 tool_use block(包含 name + input)
   ↓
2. StreamingToolExecutor.addTool() / runTools()
   ↓
3. findToolByName() 查找工具
   ↓
4. validateInput() — 输入校验
   ↓ 失败 → 返回错误 tool_result
5. canUseTool() — 权限 UI(Ask 模式下弹确认)
   ↓ 拒绝 → 返回拒绝 tool_result
6. checkPermissions() — 规则匹配
   ↓
7. call() — 执行实际操作
   ↓ onProgress() 回调实时更新 UI
8. 返回 ToolResult<Output>
   ↓
9. mapToolResultToToolResultBlockParam() — 转为 API 格式
   ↓
10. 新消息追加到对话 → 进入下一轮迭代

工具结果的预算控制

每个工具通过 maxResultSizeChars 声明输出上限:

  • BashTool:30_000(命令输出)
  • SkillTool:100_000(技能执行结果)
  • FileReadTool:Infinity(文件内容不走持久化,避免 Read→file→Read 循环)

超出上限的结果被 applyToolResultBudget()(src/utils/toolResultStorage.ts)持久化到磁盘,AI 只收到预览 + 文件路径。

MCP 工具的扩展

MCP Server 提供的工具通过 mcpInfo 字段标记来源:

mcpInfo?: { serverName: string; toolName: string }

MCP 工具的 inputJSONSchema 直接使用 JSON Schema(而非 Zod),因为 schema 来自远程协议。它们通过 filterToolsByDenyRules() 支持 mcp__server 前缀的 blanket deny 规则。

50+ 内置工具全景

Read / Write / Edit / Glob / Grep / NotebookEdit Bash / PowerShell Agent / SendMessage / AskUserQuestion TaskCreate / TaskUpdate / TaskList / TaskGet / TaskOutput / TaskStop WebFetch / WebSearch / WebBrowser EnterPlanMode / ExitPlanMode / Worktree / TodoWrite / ToolSearch

工具的可视化渲染

工具不仅能"做事",还能"展示"。每个工具通过 React 组件定义 UI 渲染:

  • FileEdit → renderToolResultMessage 展示语法高亮的 diff 视图
  • Bash → 实时显示命令输出(通过 onProgress 回调),带进度指示
  • Grep → 高亮匹配结果,显示文件路径和行号链接
  • Agent → 显示子 Agent 的进度条和状态
  • SkillTool → 渲染技能执行进度

isSearchOrReadCommand() 允许工具声明自己是搜索/读取操作,触发 UI 的折叠显示模式(避免大量搜索结果占满屏幕)。

getActivityDescription() 为 spinner 提供活动描述(如 "Reading src/foo.ts"、"Running bun test"),替代默认的工具名显示。