本章概述
系列目录:Claude Code 源码分析系列索引
Tools 工具系统是 Claude Code 的核心,它让 AI 能够安全地与文件系统、终端、网络和其他服务交互。本章将深入分析工具系统的设计理念、实现机制和最佳实践。
你将学到
- ✅ Tools 系统的架构设计
- ✅ 30+ 内置工具的分类与功能
- ✅ AgentTool 子代理系统
- ✅ 工具权限控制机制
- ✅ 工具结果处理流程
工具系统概览
flowchart TB
subgraph ToolSystem["Tools 系统"]
A[tools.ts] --> B[30+ 工具实现]
B --> C1[文件操作]
B --> C2[代码搜索]
B --> C3[终端执行]
B --> C4[网络请求]
B --> C5[子代理]
B --> C6[MCP]
end
subgraph Flow["调用流程"]
D[AI 请求工具] --> E[权限检查]
E --> F[工具执行]
F --> G[结果处理]
G --> H[返回 AI]
end
subgraph Permission["权限系统"]
I[规则匹配] --> J[用户确认]
J --> K[自动允许]
end
B --> D
E --> I
核心文件结构
src/
├── tools.ts # 工具注册中心
├── Tool.ts # 工具基类与类型定义
├── tools/
│ ├── AgentTool/ # 子代理工具
│ │ ├── AgentTool.tsx
│ │ ├── runAgent.ts
│ │ └── built-in/ # 内置代理类型
│ ├── BashTool/ # 终端执行
│ │ ├── BashTool.tsx
│ │ ├── bashPermissions.ts
│ │ └── bashSecurity.ts
│ ├── FileEditTool/ # 文件编辑
│ ├── FileReadTool/ # 文件读取
│ ├── FileWriteTool/ # 文件写入
│ ├── GlobTool/ # 文件匹配
│ ├── GrepTool/ # 内容搜索
│ ├── SkillTool/ # 技能调用
│ ├── WebFetchTool/ # 网页抓取
│ ├── WebSearchTool/ # 网络搜索
│ ├── LSP-related/ # LSP 工具
│ └── MCP-related/ # MCP 工具
└── utils/
└── permissions/ # 权限控制
工具类型定义
// Tool.ts - 工具基础定义
export type Tool = {
name: string
description: string
inputSchema: ToolInputJSONSchema
execute: (input: unknown) => Promise<unknown>
}
// 工具定义构建器
export function buildTool<TInput, TResult>(
def: ToolDef<TInput, TResult>
): Tool {
return {
name: def.name,
description: def.description,
inputSchema: def.inputSchema,
execute: def.execute,
}
}
工具定义接口
// Tool.ts - 工具定义接口
export type ToolDef<TInput, TResult> = {
name: string
description: string
inputSchema: ToolInputJSONSchema
execute: (input: TInput, context: ToolUseContext) => Promise<TResult>
// 可选:权限检查
canUse?: CanUseToolFn
// 可选:结果渲染
renderResult?: (result: TResult) => React.ReactNode
// 可选:进度回调
onProgress?: (progress: ToolProgressData) => void
}
工具分类
Claude Code 内置 30+ 工具,可分为以下几类:
1. 文件操作类
| 工具 |
功能 |
安全级别 |
FileReadTool |
读取文件内容 |
低 |
FileWriteTool |
写入文件 |
高 |
FileEditTool |
编辑文件(查找替换) |
高 |
GlobTool |
文件模式匹配 |
低 |
2. 代码搜索类
| 工具 |
功能 |
安全级别 |
GrepTool |
内容搜索(ripgrep) |
低 |
LSPTool |
语言服务器协议 |
中 |
3. 终端执行类
| 工具 |
功能 |
安全级别 |
BashTool |
执行 shell 命令 |
高 |
4. 网络请求类
| 工具 |
功能 |
安全级别 |
WebFetchTool |
抓取网页 |
中 |
WebSearchTool |
网络搜索 |
低 |
5. 子代理类
| 工具 |
功能 |
安全级别 |
AgentTool |
启动子代理 |
中 |
TeamCreateTool |
创建团队 |
中 |
TeamDeleteTool |
删除团队 |
高 |
SendMessageTool |
发送消息给子代理 |
低 |
6. MCP 类
| 工具 |
功能 |
安全级别 |
MCPTool |
MCP 服务器调用 |
中 |
ListMcpResourcesTool |
列出 MCP 资源 |
低 |
ReadMcpResourceTool |
读取 MCP 资源 |
低 |
7. 任务管理类
| 工具 |
功能 |
安全级别 |
TaskOutputTool |
获取任务输出 |
低 |
TodoWriteTool |
写入 Todo 列表 |
低 |
8. 计划模式类
| 工具 |
功能 |
安全级别 |
EnterPlanModeTool |
进入计划模式 |
低 |
ExitPlanModeTool |
退出计划模式 |
低 |
9. 工作区类
| 工具 |
功能 |
安全级别 |
EnterWorktreeTool |
进入工作树 |
中 |
ExitWorktreeTool |
退出工作树 |
中 |
AgentTool 是 Claude Code 最强大的工具之一,它允许启动并行工作的子代理。
flowchart TB
subgraph AgentTool["AgentTool"]
A[接收任务] --> B[创建代理]
B --> C{执行模式}
C -->|同步| D[等待完成]
C -->|异步| E[后台运行]
C -->|fork| F[隔离执行]
end
subgraph Lifecycle["生命周期"]
G[初始化] --> H[执行]
H --> I{完成?}
I -->|是| J[返回结果]
I -->|否| H
H --> K[错误] --> L[错误处理]
end
B --> G
// AgentTool.tsx:82-101
const baseInputSchema = lazySchema(() => z.object({
description: z.string().describe('A short (3-5 word) description of the task'),
prompt: z.string().describe('The task for the agent to perform'),
subagent_type: z.string().optional().describe('The type of specialized agent to use'),
model: z.enum(['sonnet', 'opus', 'haiku']).optional().describe('Optional model override'),
run_in_background: z.boolean().optional().describe('Set to true to run this agent in the background')
}));
const fullInputSchema = lazySchema(() => {
const multiAgentInputSchema = z.object({
name: z.string().optional().describe('Name for the spawned agent'),
team_name: z.string().optional().describe('Team name for spawning'),
mode: permissionModeSchema().optional().describe('Permission mode for spawned teammate')
});
return baseInputSchema().merge(multiAgentInputSchema).extend({
isolation: z.enum(['worktree']).optional().describe('Isolation mode'),
cwd: z.string().optional().describe('Absolute path to run the agent in')
});
});
内置代理类型
// AgentTool/built-in/generalPurposeAgent.ts
export const GENERAL_PURPOSE_AGENT = {
name: 'general-purpose',
description: 'General purpose agent for researching complex questions, searching for code, and executing multi-step tasks',
tools: ['*'], // 可以使用所有工具
model: 'sonnet'
};
子代理执行流程
// AgentTool/runAgent.ts - 简化示意
export async function runAgent(params: RunAgentParams) {
// 1. 创建代理上下文
const agentContext = await createAgentContext(params);
// 2. 加载工具集
const tools = assembleToolPool(params.agentType);
// 3. 构建系统提示词
const systemPrompt = buildEffectiveSystemPrompt(params);
// 4. 执行对话循环
while (!isComplete) {
const response = await callClaudeAPI({
messages,
tools,
systemPrompt
});
// 处理工具调用
for (const toolCall of response.tool_calls) {
const result = await executeTool(toolCall);
messages.push(toolResultToMessage(result));
}
}
// 5. 返回结果
return finalizeResult(messages);
}
BashTool 是最危险的工具之一,Claude Code 实现了多层安全机制。
命令分类
// BashTool/BashTool.tsx:60-81
// 搜索命令(可折叠显示)
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_LIST_COMMANDS = new Set(['ls', 'tree', 'du']);
// 静默命令(成功时无输出)
const BASH_SILENT_COMMANDS = new Set([
'mv', 'cp', 'rm', 'mkdir', 'rmdir',
'chmod', 'chown', 'touch', 'ln'
]);
权限检查流程
// BashTool/bashPermissions.ts - 简化示意
export function bashToolHasPermission(
command: string,
permissionContext: PermissionContext
): PermissionResult {
// 1. 解析命令
const parsed = parseCommand(command);
// 2. 检查危险命令
if (isDangerousCommand(parsed)) {
return { allowed: false, reason: 'Dangerous command' };
}
// 3. 检查权限规则
for (const rule of permissionContext.rules) {
if (matchesRule(parsed, rule)) {
return rule.allowed
? { allowed: true }
: { allowed: false, reason: rule.reason };
}
}
// 4. 默认拒绝
return { allowed: false, reason: 'No matching rule' };
}
破坏性命令警告
// BashTool/destructiveCommandWarning.ts
export function getDestructiveCommandWarning(command: string): string | null {
if (command.includes('rm -rf') || command.includes('rm -fr')) {
return '⚠️ This command will recursively delete files';
}
if (command.includes('> /dev/null')) {
return '⚠️ Output will be discarded';
}
// ... 其他危险模式
return null;
}
工具注册与发现
工具注册
// tools.ts - 工具注册中心
export function getTools() {
return [
AgentTool,
BashTool,
FileEditTool,
FileReadTool,
FileWriteTool,
GlobTool,
GrepTool,
NotebookEditTool,
TaskOutputTool,
TodoWriteTool,
WebFetchTool,
WebSearchTool,
// ... 其他工具
].filter((tool): tool is NonNullable<typeof tool> => tool != null);
}
动态工具集
// 根据场景组装工具集
export function assembleToolPool(agentType: string): Tool[] {
const baseTools = [
BashTool,
FileReadTool,
GlobTool,
GrepTool,
];
switch (agentType) {
case 'explore':
return [...baseTools, FileWriteTool, SkillTool];
case 'plan':
return [...baseTools, TodoWriteTool];
case 'execute':
return [...baseTools, FileEditTool, FileWriteTool];
default:
return baseTools;
}
}
工具结果处理
结果类型
// Tool.ts - 工具结果类型
export type ToolResult =
| { type: 'success'; data: unknown }
| { type: 'error'; error: string }
| { type: 'permission_denied'; reason: string }
| { type: 'pending'; message: string };
结果存储
// utils/toolResultStorage.ts
export function generatePreview(result: unknown, maxSize: number): string {
const content = JSON.stringify(result, null, 2);
if (content.length <= maxSize) {
return content;
}
return content.slice(0, maxSize) + '\n... (truncated)';
}
export async function buildLargeToolResultMessage(
result: unknown,
toolName: string
): Promise<string> {
const resultPath = getToolResultPath(toolName);
await writeFile(resultPath, JSON.stringify(result));
return `Result saved to: ${resultPath}`;
}
MCP 工具集成
MCP 工具架构
flowchart TB
subgraph ClaudeCode["Claude Code"]
A[MCPTool] --> B[MCP Client]
end
subgraph MCP["MCP Protocol"]
B --> C[Tools]
B --> D[Resources]
B --> E[Prompts]
end
subgraph Servers["MCP Servers"]
F[File System]
G[GitHub]
H[Database]
I[Custom]
end
C --> F
C --> G
C --> H
C --> I
MCP 工具调用
// tools/MCPTool/MCPTool.ts
export async function callMCPTool(
serverName: string,
toolName: string,
args: Record<string, unknown>
): Promise<ToolResult> {
// 1. 获取 MCP 客户端
const client = await getMCPClient(serverName);
// 2. 调用工具
const result = await client.callTool(toolName, args);
// 3. 转换结果格式
return {
type: 'success',
data: mcpResultToToolResult(result)
};
}
最佳实践
1. 工具设计原则
// ✅ 好的工具设计
const goodTool = buildTool({
name: 'read_file',
description: 'Read the contents of a file at the specified path',
inputSchema: {
type: 'object',
properties: {
file_path: {
type: 'string',
description: 'The absolute path to the file'
}
},
required: ['file_path']
},
async execute({ file_path }) {
// 安全检查
if (!isPathAllowed(file_path)) {
throw new PermissionError('Path not allowed');
}
return await readFile(file_path);
}
});
2. 权限控制
// ✅ 细粒度权限控制
const secureTool = buildTool({
name: 'edit_file',
// ...
canUse: (context, input) => {
// 检查路径权限
if (!context.allowedPaths.includes(input.file_path)) {
return {
allowed: false,
reason: 'File path not in allowed list'
};
}
return { allowed: true };
}
});
3. 错误处理
// ✅ 详细的错误信息
async function executeTool(input) {
try {
return await doSomething(input);
} catch (error) {
if (error instanceof FileNotFoundError) {
return {
type: 'error',
error: `File not found: ${error.path}`
};
}
if (error instanceof PermissionError) {
return {
type: 'permission_denied',
reason: error.message
};
}
throw error; // 未知错误,向上传播
}
}
小结
本章深入分析了 Claude Code 的工具系统:
核心概念
| 概念 |
说明 |
应用场景 |
| ToolDef |
工具定义接口 |
定义工具行为 |
| AgentTool |
子代理工具 |
并行任务处理 |
| BashTool |
终端工具 |
系统命令执行 |
| MCPTool |
MCP 集成 |
外部服务调用 |
| 权限控制 |
安全检查 |
危险操作防护 |
架构优势
- 类型安全 - TypeScript 确保工具和输入的类型正确
- 可扩展 - 易于添加新工具
- 安全 - 多层权限控制机制
- 模块化 - 工具独立,可组合使用
学习收获
- 🔧 工具设计模式 - 如何设计 AI 可用的工具
- 🛡️ 安全实践 - 危险操作的多层防护
- 🚀 子代理系统 - 并行任务处理架构
- 🔌 MCP 集成 - 标准化的外部服务接入
系列导航:
参考资源