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