Skip to content

来源:Claude Code 技术文档 - v2.1.88 源码分析

工具系统 ​

3.1 Tool 接口定义 ​

Tool<Input, Output, P> 是所有工具的核心合约。它是一个泛型接口,参数化了输入 Schema、输出类型和进度数据类型。

3.1.1 完整接口签名 ​

type Tool<
  Input extends z.ZodType,
  Output,
  P extends ToolProgressData = ToolProgressData
> = {
  // ──── 标识 ────
  readonly name: string                    // 唯一工具名称
  aliases?: string[]                       // 别名列表
  searchHint?: string                      // 搜索提示文本
  readonly strict?: boolean                // 严格模式
  isMcp?: boolean                          // 是否 MCP 工具
  isLsp?: boolean                          // 是否 LSP 工具
  shouldDefer?: boolean                    // 是否延迟加载
  alwaysLoad?: boolean                     // 是否始终加载
  mcpInfo?: {                              // MCP 元信息
    serverName: string
    toolName: string
  }
  
  // ──── Schema ────
  readonly inputSchema: Input              // Zod 输入验证 Schema
  readonly inputJSONSchema?: ToolInputJSONSchema  // JSON Schema 表示
  outputSchema?: z.ZodType<unknown>        // 输出验证 Schema
  
  // ──── 能力标志 ────
  isEnabled(): boolean                     // 工具是否启用
  isReadOnly(input): boolean               // 是否只读操作
  isDestructive?(input): boolean           // 是否破坏性操作
  isConcurrencySafe(input): boolean        // 是否并发安全
  isSearchOrReadCommand?(input): {         // 搜索/读取分类
    isSearch: boolean
    isRead: boolean
    isList?: boolean
  }
  isOpenWorld?(input): boolean             // 是否开放世界操作
  requiresUserInteraction?(): boolean      // 是否需要用户交互
  interruptBehavior?(): 'cancel' | 'block' // 中断行为
  
  // ──── 核心执行 ────
  call(
    args: z.infer<Input>,
    context: ToolUseContext,
    canUseTool: CanUseToolFn,
    parentMessage: AssistantMessage,
    onProgress?: ToolCallProgress<P>
  ): Promise<ToolResult<Output>>
  
  // ──── 权限 ────
  checkPermissions(
    input: z.infer<Input>,
    context: ToolUseContext
  ): Promise<PermissionResult>
  validateInput?(
    input: z.infer<Input>,
    context: ToolUseContext
  ): Promise<ValidationResult>
  getPath?(input): string
  preparePermissionMatcher?(input): Promise<(pattern: string) => boolean>
  
  // ──── 描述与提示 ────
  description(
    input: z.infer<Input>,
    options: {
      isNonInteractiveSession: boolean
      toolPermissionContext: ToolPermissionContext
      tools: Tools
    }
  ): Promise<string>
  prompt(options: {
    getToolPermissionContext: () => Promise<ToolPermissionContext>
    tools: Tools
    agents: AgentDefinition[]
    allowedAgentTypes?: string[]
  }): Promise<string>
  
  // ──── UI 渲染 ────
  userFacingName(input): string
  userFacingNameBackgroundColor?(input): keyof Theme | undefined
  getToolUseSummary?(input): string | null
  getActivityDescription?(input): string | null
  renderToolUseMessage(input, options): React.ReactNode
  renderToolResultMessage?(content, progressMessages, options): React.ReactNode
  renderToolUseProgressMessage?(progressMessages, options): React.ReactNode
  renderToolUseQueuedMessage?(): React.ReactNode
  renderToolUseRejectedMessage?(input, options): React.ReactNode
  renderToolUseErrorMessage?(result, options): React.ReactNode
  renderToolUseTag?(input): React.ReactNode
  renderGroupedToolUse?(toolUses, options): React.ReactNode | null
  
  // ──── 序列化 ────
  toAutoClassifierInput(input): unknown
  mapToolResultToToolResultBlockParam(content, toolUseID): ToolResultBlockParam
  backfillObservableInput?(input): void
  inputsEquivalent?(a, b): boolean
  extractSearchText?(output): string
  isResultTruncated?(output): boolean
  maxResultSizeChars: number
  isTransparentWrapper?(): boolean
}

3.1.2 ToolUseContext(执行上下文) ​

每次工具调用都会收到完整的执行上下文:

type ToolUseContext = {
  options: {
    commands: Command[]              // 可用命令列表
    debug: boolean                   // 调试模式
    mainLoopModel: string            // 当前模型名称
    tools: Tools                     // 可用工具集
    verbose: boolean                 // 详细输出
    thinkingConfig: ThinkingConfig   // 思考配置
    mcpClients: MCPServerConnection[]// MCP 连接
    mcpResources: Record<string, ServerResource[]>
    isNonInteractiveSession: boolean // 是否非交互式
    agentDefinitions: AgentDefinitionsResult
    maxBudgetUsd?: number            // 预算限额
    customSystemPrompt?: string      // 自定义系统提示
    appendSystemPrompt?: string      // 追加系统提示
    querySource?: QuerySource        // 查询来源
    refreshTools?: () => Tools       // 工具刷新回调
  }
  
  abortController: AbortController   // 中断控制器
  readFileState: FileStateCache      // 文件状态缓存
  
  // 状态管理
  getAppState(): AppState
  setAppState(f: (prev: AppState) => AppState): void
  setAppStateForTasks?: (f: (prev: AppState) => AppState) => void
  
  // UI 交互
  setToolJSX?: SetToolJSXFn          // 设置工具 JSX 渲染
  addNotification?: (notif) => void
  appendSystemMessage?: (msg) => void
  sendOSNotification?: (opts) => void
  
  // MCP 交互
  handleElicitation?: (
    serverName: string,
    params: ElicitRequestURLParams,
    signal: AbortSignal
  ) => Promise<ElicitResult>
  
  // 动态触发器
  nestedMemoryAttachmentTriggers?: ...
  dynamicSkillDirTriggers?: ...
  // ... 20+ 更多字段
}

3.1.3 ToolResult(返回值) ​

type ToolResult<T> = {
  data: T                            // 工具输出数据
  newMessages?: (                    // 可选的新增消息
    UserMessage | AssistantMessage |
    AttachmentMessage | SystemMessage
  )[]
  contextModifier?: (               // 可选的上下文修改器
    context: ToolUseContext
  ) => ToolUseContext
  mcpMeta?: {                       // MCP 元数据
    _meta?: Record<string, unknown>
    structuredContent?: Record<string, unknown>
  }
}

3.2 buildTool 工厂函数 ​

3.2.1 设计理念 ​

buildTool() 应用默认值,避免每个工具重复实现样板代码:

const TOOL_DEFAULTS = {
  isEnabled: () => true,
  isConcurrencySafe: () => false,
  isReadOnly: () => false,
  isDestructive: () => false,
  checkPermissions: () => Promise.resolve({ behavior: 'allow' }),
  toAutoClassifierInput: () => '',
  userFacingName: function() { return this.name },
  // ... 更多默认值
}

function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {
  return { ...TOOL_DEFAULTS, ...def }
}

3.2.2 使用示例 ​

const MyTool = buildTool({
  name: 'my_tool',
  inputSchema: z.object({ path: z.string() }),
  
  async call(args, context) {
    // 实现工具逻辑
    return { data: result }
  },
  
  async description() {
    return '工具描述'
  },
  
  async prompt() {
    return '给 AI 的工具使用提示'
  },
  
  renderToolUseMessage(input, options) {
    return <Text>Using: {input.path}</Text>
  },
  
  // 覆盖默认值
  isReadOnly: () => true,
  isConcurrencySafe: () => true,
  maxResultSizeChars: 50000,
})

3.3 内置工具清单 ​

3.3.1 核心工具 ​

工具名称

类型

并发安全

只读

描述

BashTool

执行

❌

❌

Shell 命令执行

FileReadTool

文件

✅

✅

文件读取

FileEditTool

文件

❌

❌

文件编辑(基于字符串替换)

FileWriteTool

文件

❌

❌

文件写入/创建

GlobTool

搜索

✅

✅

文件名模式搜索

GrepTool

搜索

✅

✅

文件内容搜索

WebFetchTool

网络

✅

✅

网页内容获取

WebSearchTool

网络

✅

✅

网络搜索

AgentTool

代理

❌

❌

子代理任务创建

SkillTool

技能

❌

❌

技能调用

3.3.2 条件编译工具 ​

以下工具仅在对应 Feature Flag 启用时编译到产物中:

工具

Feature Flag

描述

OverlapTestTool

OVERLAP_TEST_TOOL

重叠测试

REPLTool

REPL

交互式 REPL

ContextCollapseTool

CONTEXT_COLLAPSE

上下文折叠

TerminalPanelTool

TERMINAL_PANEL

终端面板

MonitorMcpTool

MONITOR_TOOL

MCP 监控

CronTools

WORKFLOWS

定时任务

3.3.3 任务相关工具 ​

工具

描述

TaskCreateTool

创建后台任务

TaskStopTool

停止任务

TaskGetTool

获取任务状态

TaskListTool

列出所有任务

SendMessageTool

向队友发送消息

3.3.4 特殊工具 ​

工具

描述

BriefTool

简洁摘要输出

NotebookEditTool

Jupyter Notebook 编辑

LSPTool

Language Server Protocol 交互

TungstenTool

内部特殊集成工具

SleepTool

延迟等待

3.4 工具池组装流程 ​

3.4.1 组装管线 ​

getAllBaseTools()
  │
  ├─ CLAUDE_CODE_SIMPLE 模式?
  │   └─ YES → 返回 [BashTool, FileReadTool, FileEditTool]
  │            (或含 REPL 替代)
  │
  ├─ NO → 加载所有内置工具
  │        ├─ 核心工具 (Bash, FileEdit, FileRead, FileWrite, ...)
  │        ├─ 检查 feature() 标志加载条件工具
  │        └─ 检查环境变量加载特殊工具
  │
  ▼
filterToolsByDenyRules(tools, permissionContext)
  │
  ├─ 检查 alwaysDenyRules
  │   └─ 完全匹配的工具被过滤掉
  │
  ▼
isEnabled() 过滤
  │
  ├─ 每个工具的 isEnabled() 检查
  │
  ▼
REPL 模式处理
  │
  ├─ 如果 REPL 启用,隐藏 REPL_ONLY_TOOLS
  │   (这些工具仅在 REPL 内部可用)
  │
  ▼
getTools(permissionContext) → 内置工具集
  │
  ▼
assembleToolPool(permissionContext, mcpTools)
  │
  ├─ 合并: [...内置工具, ...MCP工具]
  ├─ 按名称排序 (保持 prompt 缓存稳定性)
  └─ uniqBy(name) 去重 (内置优先)
  │
  ▼
最终工具池 → Tools (readonly Tool[])

3.4.2 关键函数 ​

// 获取当前权限下的内置工具
function getTools(permissionContext: ToolPermissionContext): Tools

// 组装完整工具池(内置 + MCP)
function assembleToolPool(
  permissionContext: ToolPermissionContext,
  mcpTools: Tools
): Tools

// 合并工具(不去重,用于内部场景)
function getMergedTools(
  permissionContext: ToolPermissionContext,
  mcpTools: Tools
): Tools

// 获取默认预设的工具名称列表
function getToolsForDefaultPreset(): string[]

3.5 工具权限检查 ​

3.5.1 权限检查流程 ​

工具调用请求
  │
  ▼
tool.checkPermissions(input, context)
  │
  ├─ 返回 PermissionResult:
  │   ├─ { behavior: 'allow' }       → 直接执行
  │   ├─ { behavior: 'ask', ... }    → 提示用户确认
  │   ├─ { behavior: 'deny', ... }   → 拒绝执行
  │   └─ { behavior: 'passthrough' } → 使用默认行为
  │
  ▼
wrappedCanUseTool(tool, input)
  │
  ├─ 规则匹配优先级:
  │   1. alwaysDenyRules (最高)
  │   2. alwaysAllowRules
  │   3. alwaysAskRules
  │   4. PermissionMode 默认
  │
  ├─ auto 模式:
  │   └─ YoloClassifier 自动判断
  │       ├─ shouldBlock: true → deny
  │       └─ shouldBlock: false → allow
  │
  ▼
执行/拒绝/等待用户确认

3.5.2 工具分类器 ​

type YoloClassifierResult = {
  thinking?: string       // 推理过程
  shouldBlock: boolean    // 是否阻止
  reason: string          // 原因
  unavailable?: boolean   // 分类器不可用
  transcriptTooLong?: boolean  // 上下文太长
  model: string           // 使用的模型
  usage?: ClassifierUsage // Token 使用
  durationMs?: number     // 耗时
  stage?: 'fast' | 'thinking'  // 阶段
}

3.6 代理工具限制 ​

不同代理类型有不同的工具访问权限:

3.6.1 代理禁止工具集 ​

ALL_AGENT_DISALLOWED_TOOLS = Set[
  TASK_OUTPUT_TOOL_NAME,
  EXIT_PLAN_MODE_V2_TOOL_NAME,
  ENTER_PLAN_MODE_TOOL_NAME,
  ASK_USER_QUESTION_TOOL_NAME,
  // 条件工具...
]

3.6.2 异步代理允许工具 ​

ASYNC_AGENT_ALLOWED_TOOLS = Set[
  FILE_READ_TOOL_NAME,    // 文件读取
  WEB_SEARCH_TOOL_NAME,   // 网络搜索
  GREP_TOOL_NAME,         // 代码搜索
  GLOB_TOOL_NAME,         // 文件查找
  WEB_FETCH_TOOL_NAME,    // 网页获取
  // 更多文件/Web 相关工具
]

3.6.3 进程内队友工具 ​

IN_PROCESS_TEAMMATE_ALLOWED_TOOLS = Set[
  TASK_CREATE_TOOL_NAME,
  TASK_GET_TOOL_NAME,
  TASK_LIST_TOOL_NAME,
  SEND_MESSAGE_TOOL_NAME,
  // 条件工具...
]

3.6.4 协调器模式工具 ​

COORDINATOR_MODE_ALLOWED_TOOLS = Set[
  AGENT_TOOL_NAME,            // 创建子代理
  TASK_STOP_TOOL_NAME,        // 停止任务
  SEND_MESSAGE_TOOL_NAME,     // 发送消息
  SYNTHETIC_OUTPUT_TOOL_NAME, // 合成输出
]

3.7 MCP 工具集成 ​

3.7.1 MCP 工具标识 ​

// MCP 工具具有特殊属性标记
tool.isMcp = true
tool.mcpInfo = {
  serverName: 'server-name',  // MCP 服务器名称
  toolName: 'tool-name'       // MCP 内工具名称
}

3.7.2 集成优先级 ​

当 MCP 工具与内置工具同名时:

  • assembleToolPool() 使用 uniqBy(name) 去重
  • 排序后的列表中,内置工具先出现
  • 因此 内置工具优先于同名 MCP 工具

3.7.3 权限过滤 ​

function filterToolsByDenyRules(tools, permissionContext) {
  // MCP 工具也受 deny 规则约束
  // 匹配条件: toolName (内置) 或 serverName:toolName (MCP)
  return tools.filter(tool => {
    if (tool.mcpInfo) {
      // 检查 server:tool 格式的匹配
    }
    // 检查纯工具名匹配
  })
}

3.8 工具辅助函数 ​

// 按名称或别名查找工具
function findToolByName(tools: Tools, name: string): Tool | undefined

// 检查工具名称匹配(含别名)
function toolMatchesName(
  tool: { name: string; aliases?: string[] },
  name: string
): boolean

// 过滤工具进度消息
function filterToolProgressMessages(
  progressMessages: ProgressMessage[]
): ProgressMessage<ToolProgressData>[]

// 获取空权限上下文
function getEmptyToolPermissionContext(): ToolPermissionContext

3.9 工具渲染模式 ​

每个工具可以提供多种渲染方法来控制 UI 显示:

渲染方法

时机

描述

renderToolUseMessage

发送调用时

工具使用消息(必需)

renderToolResultMessage

收到结果时

结果展示(可选)

renderToolUseProgressMessage

执行中

进度动画/状态(可选)

renderToolUseQueuedMessage

排队等待时

排队提示(可选)

renderToolUseRejectedMessage

被拒绝时

拒绝原因展示(可选)

renderToolUseErrorMessage

出错时

错误详情展示(可选)

renderGroupedToolUse

分组展示时

合并多个同类调用(可选)

renderToolUseTag

标签展示

简短标签标识(可选)

MIT