“一切皆工具” —— 这是 Claude Code 最核心的抽象。LLM 通过工具与世界交互。
每个工具本质上是一个符合以下接口的对象:
type Tool = { readonly name: string; description(input, options): Promise<string>; readonly inputSchema: z.ZodType; userFacingName(input): string; isReadOnly(input): boolean; isConcurrencySafe(input): boolean; isEnabled(): boolean;
call(args, context: ToolUseContext, canUseTool, parentMessage, onProgress?): Promise<ToolResult>;
checkPermissions(input, context): Promise<PermissionResult>;
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; toolPermissionContext: ToolPermissionContext; fileHistoryState: FileHistoryState; attributionState: AttributionState; };
|
export function buildTool<TInput>(def: ToolDef<TInput>): Tool { return { name: def.name, inputSchema: def.inputSchema, call: async function*(input, context) { }, }; }
|
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,
AgentTool,
EnterPlanModeTool, ExitPlanModeV2Tool, TaskCreateTool, TaskGetTool, TaskUpdateTool, TaskListTool, TodoWriteTool,
ListMcpResourcesTool, ReadMcpResourceTool,
...(REPLTool ? [REPLTool] : []), ...(WebBrowserTool ? [WebBrowserTool] : []), ...(MonitorTool ? [MonitorTool] : []), ];
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) |
✅ |
关键设计:要求 old_string 在文件中唯一出现,避免误编辑。
3.2 命令执行类
| 工具 |
目录 |
功能 |
| BashTool |
tools/BashTool/ (1144 行) |
执行 Shell 命令 |
| PowerShellTool |
tools/PowerShellTool/ |
Windows PowerShell |
| REPLTool |
tools/REPLTool/ |
交互式 REPL (ant-only) |
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
|
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 发消息 |
async function runAgent(agentDefinition, prompt, parentContext) { const subContext = createSubagentContext(parentContext);
const { clients, tools } = await initializeAgentMcpServers( agentDefinition, parentContext.mcpClients );
const systemPrompt = buildAgentSystemPrompt(agentDefinition);
for await (const event of query(userMessage, [], systemPrompt, tools)) { yield event; }
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 |
向用户提问 |
始终 |
四、工具执行流程
export async function* runToolUse( toolUse: ToolUseBlock, assistantMessages: AssistantMessage[], canUseTool: CanUseToolFn, context: ToolUseContext, ): AsyncGenerator<MessageUpdate> {
const tool = findToolByName(context.options.tools, toolUse.name);
const parsed = tool.inputSchema.safeParse(toolUse.input); if (!parsed.success) { yield errorResult("输入格式错误"); return; }
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; } }
for await (const progress of tool.call(parsed.data, context)) { yield progressUpdate(progress); }
yield toolResult(result); }
|
五、工具结果存储
大型工具结果(如长文件内容、大量 shell 输出)会使用磁盘存储,避免占满上下文窗口:
const PREVIEW_SIZE_BYTES = 8192;
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 可以并行执行(提速)
FileEdit 和 BashTool 串行执行(避免竞态)
- 新工具默认串行(安全第一)