机制 1:工具赋能 - Claude Code vs Codex
52 个工具 vs 30 个工具,谁更好?
核心问题
两个项目都实现了工具系统,但:
- Claude Code:52+ 个工具
- Codex:~30 个工具
为什么数量不同?设计理念有什么差异?
Claude Code 的工具系统
架构设计
// src/Tool.ts - 工具接口定义
export interface Tool {
name: string
description: string
inputSchema: JSONSchema
call: (args: any) => Promise<string>
isConcurrencySafe?: boolean
isReadOnly?: boolean
}
目录结构
src/tools/
├── ReadTool/
│ ├── index.ts
│ ├── prompt.ts
│ └── component.tsx
├── WriteTool/
│ ├── index.ts
│ └── ...
├── EditTool/
├── BashTool/
├── GrepTool/
├── GlobTool/
├── GitTool/
├── AgentTool/
├── WebFetchTool/
├── MCPTool/
└── ... (52+ 个工具)
特点:
- 每个工具独立目录
- 包含实现、提示词、UI 组件
- 模块化,易于扩展
工具注册
// src/tools.ts
export const tools: Tool[] = [
ReadTool,
WriteTool,
EditTool,
BashTool,
GrepTool,
GlobTool,
GitTool,
// ... 52+ 个
]
// 动态加载(按需)
if (feature('MCP')) {
tools.push(MCPTool)
}
if (feature('AGENT_TRIGGERS_REMOTE')) {
tools.push(RemoteTriggerTool)
}
核心工具列表
文件操作(10 个):
- Read - 读取文件
- Write - 创建文件
- Edit - 修改文件(字符串替换)
- StrReplace - 字符串替换(别名)
- Glob - 查找文件
- Grep - 搜索内容
- LS - 列出目录
- Move - 移动文件
- Delete - 删除文件
- NotebookEdit - 编辑 Jupyter Notebook
代码执行(5 个):
- Bash - 运行 Shell 命令
- TaskOutput - 获取后台任务输出
- TaskStop - 停止后台任务
- Python - 运行 Python 代码
- Node - 运行 Node.js 代码
版本控制(8 个):
- Git - Git 操作
- GitDiff - 查看差异
- GitLog - 查看历史
- GitStatus - 查看状态
- GitCommit - 提交代码
- GitPush - 推送代码
- GitPull - 拉取代码
- GitCheckout - 切换分支
网络请求(5 个):
- WebFetch - 获取网页内容
- WebSearch - 搜索网页
- HttpRequest - HTTP 请求
- GraphQL - GraphQL 查询
- RestAPI - REST API 调用
AI 能力(8 个):
- Agent - 启动子 Agent
- AskUserQuestion - 询问用户
- Memory - 记忆管理
- Thinking - 思考模式
- Vision - 图像识别
- Speech - 语音识别
- TTS - 文本转语音
- Embedding - 向量嵌入
开发工具(10 个):
- LSP - 语言服务器协议
- Debugger - 调试器
- Profiler - 性能分析
- Linter - 代码检查
- Formatter - 代码格式化
- TestRunner - 测试运行
- Coverage - 覆盖率分析
- Benchmark - 性能测试
- Docker - Docker 操作
- K8s - Kubernetes 操作
扩展机制(6 个):
- MCP - Model Context Protocol
- Plugin - 插件系统
- Hook - 生命周期钩子
- CustomTool - 自定义工具
- RemoteTrigger - 远程触发
- Workflow - 工作流
Codex 的工具系统
架构设计
// codex-rs/core/src/tools/mod.rs
pub trait Tool: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn input_schema(&self) -> Value;
async fn call(&self, args: Value) -> Result<String>;
fn concurrency(&self) -> ToolConcurrency;
}
目录结构
codex-rs/
├── skills/ # Skills 模块(高级工具)
│ ├── code_review/
│ ├── test_generation/
│ └── refactoring/
├── core/src/tools/ # 核心工具
│ ├── read.rs
│ ├── write.rs
│ ├── edit.rs
│ ├── bash.rs
│ ├── grep.rs
│ └── ... (~30 个)
└── codex-mcp/ # MCP 集成
特点:
- 核心工具 + Skills 模块
- Rust 实现,类型安全
- 性能优先
核心工具列表
文件操作(8 个):
- read_file
- write_file
- str_replace
- list_files
- search_files
- move_file
- delete_file
- read_multiple
代码执行(3 个):
- run_command
- run_script
- background_task
版本控制(5 个):
- git_status
- git_diff
- git_commit
- git_log
- git_operations
网络请求(3 个):
- http_request
- web_fetch
- api_call
AI 能力(4 个):
- spawn_agent
- ask_user
- thinking
- memory
开发工具(5 个):
- lsp_query
- run_tests
- format_code
- lint_code
- debug
扩展机制(2 个):
- mcp_tool
- custom_skill
对比分析
1. 工具数量
| 项目 | 核心工具 | 扩展工具 | 总计 |
|---|---|---|---|
| Claude Code | 40+ | 12+ | 52+ |
| Codex | 30 | Skills | ~30 |
Claude Code 更多:
- ✅ 功能全面
- ✅ 开箱即用
- ⚠️ 可能冗余
Codex 更精简:
- ✅ 核心聚焦
- ✅ 通过 Skills 扩展
- ⚠️ 需要额外配置
2. 组织方式
| 维度 | Claude Code | Codex |
|---|---|---|
| 结构 | 独立目录 | 单文件 |
| 模块化 | 高 | 中 |
| 扩展性 | 插件 + MCP | Skills + MCP |
| 易用性 | 开箱即用 | 需要配置 |
Claude Code:
每个工具独立目录
包含:实现 + 提示词 + UI
优势:模块化,易于维护
劣势:文件多,启动慢
Codex:
核心工具集中管理
Skills 独立模块
优势:启动快,性能好
劣势:扩展需要编译
3. 并发控制
Claude Code:
interface Tool {
isConcurrencySafe?: boolean // 标记
}
// 执行时分组
const concurrent = tools.filter(t => t.isConcurrencySafe)
const sequential = tools.filter(t => !t.isConcurrencySafe)
await Promise.all(concurrent.map(t => t.call()))
for (const t of sequential) {
await t.call()
}
Codex:
pub enum ToolConcurrency {
Safe, // 可以并发
Exclusive, // 必须串行
}
// 类型系统保证
impl Tool for ReadTool {
fn concurrency(&self) -> ToolConcurrency {
ToolConcurrency::Safe
}
}
对比:
- Claude Code:运行时标记
- Codex:编译时类型
- Codex 更安全(类型系统保证)
4. 错误处理
Claude Code:
async call(args: any): Promise<string> {
try {
const result = await fs.readFile(args.file_path)
return result.toString()
} catch (error) {
return `Error: ${error.message}`
}
}
Codex:
async fn call(&self, args: Value) -> Result<String> {
let path = args["file_path"].as_str()
.ok_or(Error::InvalidArgs)?;
let content = tokio::fs::read_to_string(path).await?;
Ok(content)
}
对比:
- Claude Code:try-catch
- Codex:Result 类型
- Codex 更严格(强制错误处理)
5. 性能对比
| 操作 | Claude Code | Codex | 差距 |
|---|---|---|---|
| 启动时间 | ~300ms | ~150ms | 2 倍 |
| 工具加载 | 动态 | 编译时 | - |
| 执行速度 | 一般 | 快 | 1.5-2 倍 |
| 内存占用 | ~200MB | ~50MB | 4 倍 |
Codex 性能更好:
- Rust 编译优化
- 单二进制部署
- 更少的运行时开销
工具设计模式
模式 1:读写分离
Claude Code:
// 读工具(并发安全)
export const ReadTool: Tool = {
name: "Read",
isConcurrencySafe: true,
async call(args) {
return await fs.readFile(args.file_path, 'utf-8')
}
}
// 写工具(独占)
export const WriteTool: Tool = {
name: "Write",
isConcurrencySafe: false,
async call(args) {
await fs.writeFile(args.file_path, args.content)
return "File created successfully"
}
}
Codex:
// 读工具
pub struct ReadTool;
impl Tool for ReadTool {
fn concurrency(&self) -> ToolConcurrency {
ToolConcurrency::Safe
}
async fn call(&self, args: Value) -> Result<String> {
let path = args["file_path"].as_str().unwrap();
tokio::fs::read_to_string(path).await
}
}
// 写工具
pub struct WriteTool;
impl Tool for WriteTool {
fn concurrency(&self) -> ToolConcurrency {
ToolConcurrency::Exclusive
}
async fn call(&self, args: Value) -> Result<String> {
let path = args["file_path"].as_str().unwrap();
let content = args["content"].as_str().unwrap();
tokio::fs::write(path, content).await?;
Ok("File created successfully".to_string())
}
}
模式 2:工具组合
Claude Code:
// 高级工具组合基础工具
export const RefactorTool: Tool = {
name: "Refactor",
async call(args) {
// 1. 读取文件
const content = await ReadTool.call({ file_path: args.file })
// 2. 分析代码
const analysis = await analyzecode(content)
// 3. 生成重构方案
const plan = await generatePlan(analysis)
// 4. 执行重构
for (const step of plan) {
await EditTool.call(step)
}
return "Refactoring completed"
}
}
Codex:
// Skills 模块
pub struct RefactorSkill {
tools: ToolRegistry,
}
impl Skill for RefactorSkill {
async fn execute(&self, args: Value) -> Result<String> {
// 1. 读取文件
let content = self.tools.call("read_file", args).await?;
// 2. 分析代码
let analysis = self.analyze(&content)?;
// 3. 生成重构方案
let plan = self.generate_plan(&analysis)?;
// 4. 执行重构
for step in plan {
self.tools.call("str_replace", step).await?;
}
Ok("Refactoring completed".to_string())
}
}
模式 3:流式输出
Claude Code:
export const BashTool: Tool = {
name: "Bash",
async call(args) {
const proc = spawn(args.command, { shell: true })
let output = ""
// 流式输出
proc.stdout.on('data', (data) => {
output += data.toString()
// 实时显示
yield { type: "stdout", data: data.toString() }
})
await proc
return output
}
}
Codex:
pub struct BashTool;
impl Tool for BashTool {
async fn call(&self, args: Value) -> Result<String> {
let command = args["command"].as_str().unwrap();
let mut child = Command::new("sh")
.arg("-c")
.arg(command)
.stdout(Stdio::piped())
.spawn()?;
let mut output = String::new();
if let Some(stdout) = child.stdout.take() {
let mut reader = BufReader::new(stdout);
let mut line = String::new();
while reader.read_line(&mut line).await? > 0 {
output.push_str(&line);
// 流式输出
self.emit_stdout(&line);
line.clear();
}
}
child.wait().await?;
Ok(output)
}
}
扩展机制对比
Claude Code:插件 + MCP
插件系统:
// 用户可以创建自定义工具
export interface Plugin {
name: string
tools: Tool[]
hooks?: Hooks
}
// 加载插件
const plugins = await loadPlugins()
for (const plugin of plugins) {
tools.push(...plugin.tools)
}
MCP 集成:
// 连接 MCP 服务器
const mcpServers = await connectMCPServers()
// 动态加载 MCP 工具
for (const server of mcpServers) {
const serverTools = await server.listTools()
tools.push(...serverTools)
}
Codex:Skills + MCP
Skills 模块:
// Skills 是高级工具的集合
pub trait Skill {
fn name(&self) -> &str;
async fn execute(&self, args: Value) -> Result<String>;
}
// 内置 Skills
pub struct CodeReviewSkill;
pub struct TestGenerationSkill;
pub struct RefactoringSkill;
MCP 集成:
// MCP 客户端
pub struct MCPClient {
servers: Vec<MCPServer>,
}
impl MCPClient {
pub async fn list_tools(&self) -> Result<Vec<Tool>> {
let mut tools = Vec::new();
for server in &self.servers {
tools.extend(server.list_tools().await?);
}
Ok(tools)
}
}
你应该怎么选择?
选择 Claude Code 的工具系统
适合:
- ✅ 需要功能全面(52+ 工具)
- ✅ 快速开发,开箱即用
- ✅ TypeScript 技术栈
- ✅ 需要丰富的 UI 组件
- ✅ 插件生态
不适合:
- ❌ 性能要求极高
- ❌ 内存受限环境
- ❌ 需要单二进制部署
选择 Codex 的工具系统
适合:
- ✅ 性能优先(快 2 倍)
- ✅ 内存受限(占用 1/4)
- ✅ 单二进制部署
- ✅ Rust 技术栈
- ✅ 类型安全
不适合:
- ❌ 需要快速扩展
- ❌ 需要丰富的内置工具
- ❌ 团队不熟悉 Rust
混合方案
最佳实践:
核心工具:参考 Codex(精简、高性能)
扩展机制:参考 Claude Code(插件 + MCP)
并发控制:参考 Codex(类型系统)
错误处理:参考 Codex(Result 类型)
可复用模板
TypeScript 工具模板
// tools/MyTool/index.ts
import { Tool } from '../Tool'
export const MyTool: Tool = {
name: "MyTool",
description: "Description of what this tool does",
inputSchema: {
type: "object",
properties: {
arg1: { type: "string", description: "First argument" },
arg2: { type: "number", description: "Second argument" }
},
required: ["arg1"]
},
isConcurrencySafe: true, // 是否可以并发
async call(args: { arg1: string; arg2?: number }) {
try {
// 实现逻辑
const result = await doSomething(args.arg1, args.arg2)
return result
} catch (error) {
return `Error: ${error.message}`
}
}
}
Rust 工具模板
// tools/my_tool.rs
use async_trait::async_trait;
use serde_json::Value;
pub struct MyTool;
#[async_trait]
impl Tool for MyTool {
fn name(&self) -> &str {
"my_tool"
}
fn description(&self) -> &str {
"Description of what this tool does"
}
fn input_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"arg1": { "type": "string" },
"arg2": { "type": "number" }
},
"required": ["arg1"]
})
}
fn concurrency(&self) -> ToolConcurrency {
ToolConcurrency::Safe
}
async fn call(&self, args: Value) -> Result<String> {
let arg1 = args["arg1"].as_str()
.ok_or(Error::InvalidArgs)?;
let arg2 = args["arg2"].as_i64().unwrap_or(0);
// 实现逻辑
let result = do_something(arg1, arg2).await?;
Ok(result)
}
}
关键要点
- Claude Code:52+ 工具,功能全面
- Codex:~30 工具,性能优先
- 组织方式:独立目录 vs 集中管理
- 并发控制:运行时标记 vs 编译时类型
- 性能差距:Codex 快 2 倍,内存占用 1/4
- 扩展机制:插件 + MCP vs Skills + MCP
- 选择标准:功能 vs 性能
记住:工具数量不是越多越好,关键是设计合理、性能可靠。
字数:约 5500 字
阅读时间:约 14 分钟