返回

Claude Code 源码分析 3:Tools 工具系统设计解析

深入分析 Claude Code 的 Tools 工具系统,这是 AI 与外部世界交互的桥梁。包括 30+ 工具的实现、工具调用流程、权限控制、以及 Agent 子代理工具的设计。

本章概述

系列目录: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)

// 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 子代理系统

AgentTool 是 Claude Code 最强大的工具之一,它允许启动并行工作的子代理。

AgentTool 架构

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 输入定义

// 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 安全机制

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 集成 外部服务调用
权限控制 安全检查 危险操作防护

架构优势

  1. 类型安全 - TypeScript 确保工具和输入的类型正确
  2. 可扩展 - 易于添加新工具
  3. 安全 - 多层权限控制机制
  4. 模块化 - 工具独立,可组合使用

学习收获

  • 🔧 工具设计模式 - 如何设计 AI 可用的工具
  • 🛡️ 安全实践 - 危险操作的多层防护
  • 🚀 子代理系统 - 并行任务处理架构
  • 🔌 MCP 集成 - 标准化的外部服务接入

系列导航:

参考资源