目录
  1. 1. 一、Tool 抽象 (Tool.ts, 792 行)
    1. 1.1. 1.1 Tool 类型定义
    2. 1.2. 1.2 ToolUseContext — 工具执行上下文
    3. 1.3. 1.3 buildTool() — 工具工厂函数
  2. 2. 二、工具注册 (tools.ts, 390 行)
  3. 3. 三、30+ 内置工具详解
    1. 3.1. 3.1 文件操作类
      1. 3.1.1. FileEditTool 核心算法
    2. 3.2. 3.2 命令执行类
      1. 3.2.1. BashTool 安全架构
      2. 3.2.2. BashTool 命令分类
    3. 3.3. 3.3 Agent 类
      1. 3.3.1. AgentTool 子 Agent 机制
    4. 3.4. 3.4 搜索与网络类
    5. 3.5. 3.5 计划与任务类
    6. 3.6. 3.6 MCP 相关
    7. 3.7. 3.7 其他特殊工具
  4. 4. 四、工具执行流程
  5. 5. 五、工具结果存储
  6. 6. 六、isConcurrencySafe 决策树
【Claude Code源码剖析】03-工具系统 (Tool System)

“一切皆工具” —— 这是 Claude Code 最核心的抽象。LLM 通过工具与世界交互。


一、Tool 抽象 (Tool.ts, 792 行)

1.1 Tool 类型定义

每个工具本质上是一个符合以下接口的对象:

// Tool.ts (核心类型,简化)
type Tool = {
readonly name: string; // 工具名 (如 "Bash", "FileEdit")
description(input, options): Promise<string>; // 给 LLM 看的描述(异步函数)
readonly inputSchema: z.ZodType; // Zod schema,定义输入参数
userFacingName(input): string; // 给用户看的名称
isReadOnly(input): boolean; // 是否只读(决定能否并行)
isConcurrencySafe(input): boolean; // 是否并发安全
isEnabled(): boolean; // 是否启用(无参数)

// 核心执行函数(返回 Promise,非 AsyncGenerator)
call(args, context: ToolUseContext, canUseTool, parentMessage, onProgress?): Promise<ToolResult>;

// 权限检查(checkPermissions,非 hasPermission)
checkPermissions(input, context): Promise<PermissionResult>;

// UI 渲染
renderToolUseMessage(input): React.ReactNode;
renderToolResultMessage?(result): React.ReactNode;

// 验证
validateInput?(input, context): Promise<ValidationResult>;

maxResultSizeChars: number; // 结果超此长度则持久化到磁盘
}

1.2 ToolUseContext — 工具执行上下文

每次工具调用都携带一个丰富的上下文对象:

type ToolUseContext = {
options: {
tools: Tools; // 所有可用工具列表
commands: Command[]; // 所有命令列表
mcpClients: MCPServerConnection[];
agents: AgentDefinition[];
};
abortController: AbortController;
getAppState: () => AppState;
setAppState: (f) => void;
readFileCache: FileStateCache; // 文件读取缓存
setToolJSX: SetToolJSXFn; // 设置工具 UI
toolPermissionContext: ToolPermissionContext;
fileHistoryState: FileHistoryState;
attributionState: AttributionState;
// ...
};

1.3 buildTool() — 工具工厂函数

// 所有工具通过 buildTool() 创建
export function buildTool<TInput>(def: ToolDef<TInput>): Tool {
return {
name: def.name,
inputSchema: def.inputSchema,
call: async function*(input, context) {
// 1. 输入验证 (Zod parse)
// 2. 权限检查
// 3. 执行工具逻辑
// 4. yield 进度事件
// 5. 返回结果
},
// ... 其他方法
};
}

二、工具注册 (tools.ts, 390 行)

// tools.ts — 工具注册中心
import { BashTool } from './tools/BashTool/BashTool.js';
import { FileEditTool } from './tools/FileEditTool/FileEditTool.js';
import { FileReadTool } from './tools/FileReadTool/FileReadTool.js';
// ... 更多导入

export function getTools(permissionContext): Tools {
const tools: Tool[] = [
// ===== 核心工具 (始终启用) =====
BashTool,
FileEditTool,
FileReadTool,
FileWriteTool,
GlobTool,
GrepTool,

// ===== 搜索/网络工具 =====
WebSearchTool,
WebFetchTool,

// ===== Agent 工具 =====
AgentTool,

// ===== 计划/任务工具 =====
EnterPlanModeTool,
ExitPlanModeV2Tool,
TaskCreateTool, TaskGetTool, TaskUpdateTool, TaskListTool,
TodoWriteTool,

// ===== MCP 工具 =====
ListMcpResourcesTool,
ReadMcpResourceTool,

// ===== 条件编译工具 (feature flag) =====
...(REPLTool ? [REPLTool] : []), // ant-only
...(WebBrowserTool ? [WebBrowserTool] : []), // WEB_BROWSER_TOOL flag
...(MonitorTool ? [MonitorTool] : []), // MONITOR_TOOL flag
];

// 过滤:去除被权限规则 deny 的工具
return tools.filter(tool => !getDenyRuleForTool(tool, permissionContext));
}

三、30+ 内置工具详解

3.1 文件操作类

工具 目录 功能 只读
FileReadTool tools/FileReadTool/ 读取文件(支持行范围)
FileWriteTool tools/FileWriteTool/ 创建新文件
FileEditTool tools/FileEditTool/ 编辑已有文件(搜索替换)
NotebookEditTool tools/NotebookEditTool/ 编辑 Jupyter Notebook
GlobTool tools/GlobTool/ 按 glob 模式搜索文件名
GrepTool tools/GrepTool/ 正则搜索文件内容 (ripgrep)

FileEditTool 核心算法

// FileEditTool 使用 "搜索-替换" 模式:
// 1. LLM 提供 old_string (要替换的原文)
// 2. LLM 提供 new_string (替换后的文本)
// 3. 工具在文件中找到 old_string 的精确匹配
// 4. 替换为 new_string
// 5. 保留原始文件编码和换行符

关键设计:要求 old_string 在文件中唯一出现,避免误编辑。

3.2 命令执行类

工具 目录 功能
BashTool tools/BashTool/ (1144 行) 执行 Shell 命令
PowerShellTool tools/PowerShellTool/ Windows PowerShell
REPLTool tools/REPLTool/ 交互式 REPL (ant-only)

BashTool 安全架构

LLM 请求执行: rm -rf /important


[1] 命令解析 (bash/ast.ts)
│ — 解析 AST,识别命令类型

[2] 安全检查 (bashSecurity.ts)
│ — 检查危险命令模式
│ — 检查路径是否在允许范围内

[3] 权限检查 (bashPermissions.ts)
│ — 匹配权限规则 (allow/deny/ask)
│ — 通配符规则匹配

[4] 分类器判断 (classifierDecision.ts)
│ — ML 分类器评估风险

[5] 用户确认 (PermissionRequest.tsx)
│ — 显示权限对话框

[6] 沙箱检查 (shouldUseSandbox.ts)
│ — 决定是否在沙箱中执行

[7] 执行 (Shell.ts)
│ — 超时控制
│ — 输出截断
└─ 返回 stdout + stderr + exit_code

BashTool 命令分类

// 搜索命令 (可折叠显示)
const BASH_SEARCH_COMMANDS = new Set([
'find', 'grep', 'rg', 'ag', 'ack', 'locate', 'which', 'whereis'
]);

// 读取命令 (可折叠显示)
const BASH_READ_COMMANDS = new Set([
'cat', 'head', 'tail', 'less', 'more', 'wc', 'stat', 'file',
'strings', 'jq', 'awk', 'cut', 'sort', 'uniq', 'tr'
]);

// 语义中性命令 (不影响读/写判断)
const BASH_SEMANTIC_NEUTRAL_COMMANDS = new Set([
'echo', 'printf', 'true', 'false', ':'
]);

3.3 Agent 类

工具 目录 功能
AgentTool tools/AgentTool/ 派生子 Agent
TeamCreateTool tools/TeamCreateTool/ 创建 Agent 团队
TeamDeleteTool tools/TeamDeleteTool/ 删除 Agent 团队
SendMessageTool tools/SendMessageTool/ 向 Agent 发消息

AgentTool 子 Agent 机制

// runAgent.ts — 子 Agent 的运行机制
async function runAgent(agentDefinition, prompt, parentContext) {
// 1. 创建独立的上下文 (不共享父级的消息历史)
const subContext = createSubagentContext(parentContext);

// 2. 连接 Agent 专属的 MCP 服务器
const { clients, tools } = await initializeAgentMcpServers(
agentDefinition, parentContext.mcpClients
);

// 3. 构建 Agent 专属的系统 prompt
const systemPrompt = buildAgentSystemPrompt(agentDefinition);

// 4. 运行独立的 query() 循环
for await (const event of query(userMessage, [], systemPrompt, tools)) {
// 将事件传给父级 UI
yield event;
}

// 5. 返回 Agent 的最终输出
return agentResult;
}

3.4 搜索与网络类

工具 功能
WebSearchTool 网页搜索
WebFetchTool 获取网页内容
ToolSearchTool 在可用工具中搜索(当工具太多时)
LSPTool Language Server Protocol 调用

3.5 计划与任务类

工具 功能
EnterPlanModeTool 进入计划模式(先规划再执行)
ExitPlanModeV2Tool 退出计划模式
TaskCreateTool 创建后台任务
TaskGetTool 获取任务状态
TaskUpdateTool 更新任务状态
TaskListTool 列出所有任务
TodoWriteTool 写入 TODO 列表

3.6 MCP 相关

工具 功能
ListMcpResourcesTool 列出 MCP 服务器资源
ReadMcpResourceTool 读取 MCP 资源内容
MCPTool 动态代理的 MCP 工具

3.7 其他特殊工具

工具 功能 条件
SleepTool 等待指定时间 PROACTIVE / KAIROS
SnipTool 截断对话历史 HISTORY_SNIP
ConfigTool 修改运行时配置 始终
BriefTool 简洁回复模式 始终
SyntheticOutputTool 结构化输出 (JSON) 需配置
AskUserQuestionTool 向用户提问 始终

四、工具执行流程

// services/tools/toolExecution.ts
export async function* runToolUse(
toolUse: ToolUseBlock,
assistantMessages: AssistantMessage[],
canUseTool: CanUseToolFn,
context: ToolUseContext,
): AsyncGenerator<MessageUpdate> {

// 1. 查找工具定义
const tool = findToolByName(context.options.tools, toolUse.name);

// 2. 解析输入
const parsed = tool.inputSchema.safeParse(toolUse.input);
if (!parsed.success) {
yield errorResult("输入格式错误");
return;
}

// 3. 权限检查
const permission = await canUseTool(tool, parsed.data);
if (permission.behavior === 'deny') {
yield rejectedResult(permission.reason);
return;
}
if (permission.behavior === 'ask') {
// 显示权限对话框,等待用户决定
const decision = await askUser(tool, parsed.data);
if (decision === 'deny') {
yield rejectedResult("用户拒绝");
return;
}
}

// 4. 执行工具
for await (const progress of tool.call(parsed.data, context)) {
yield progressUpdate(progress);
}

// 5. 返回结果
yield toolResult(result);
}

五、工具结果存储

大型工具结果(如长文件内容、大量 shell 输出)会使用磁盘存储,避免占满上下文窗口:

// utils/toolResultStorage.ts
const PREVIEW_SIZE_BYTES = 8192; // 8KB 预览

function buildLargeToolResultMessage(fullContent: string) {
if (fullContent.length <= PREVIEW_SIZE_BYTES) {
return fullContent; // 小内容直接返回
}

// 大内容:存磁盘 + 返回预览
const path = getToolResultPath(toolUseId);
writeToFile(path, fullContent);

return generatePreview(fullContent, PREVIEW_SIZE_BYTES) +
`\n[Content truncated. Full output saved to ${path}]`;
}

六、isConcurrencySafe 决策树

工具调用到来

├─ tool.isReadOnly() === true?
│ ├─ YES → 检查 isConcurrencySafe(input)
│ │ ├─ YES → 放入并行批次
│ │ └─ NO → 放入串行批次
│ │
│ └─ NO → 放入串行批次 (写操作不能并行)

└─ 未知工具 → 放入串行批次 (安全默认)

这个设计保证了:

  • 多个 FileRead + Grep 可以并行执行(提速)
  • FileEditBashTool 串行执行(避免竞态)
  • 新工具默认串行(安全第一)
打赏
  • 微信
  • 支付宝

评论