来源:互联网 更新时间:2026-07-08 07:14
一次对 claude.exe (225MB) 和 codex.exe (308MB) 的二进制逆向分析,揭开了两种截然不同的 Agent 协议设计哲学。一个选择了无状态 HTTP,每次对话都像第一次见面;另一个则用 WebSocket 构建了有状态的会话记忆。这不仅仅是技术选型的差异,更是对“理想的编程助手应该是什么样子”这个根本问题的不同回答。

AI 编程助手已经成了很多开发者的日常搭档。当你习惯地在终端里敲下“帮我修复这个 bug”,然后回车——背后到底发生了什么?每一次工具调用、每一条“让我先看看这个文件”,到底对应多少次 API 请求?每次请求都要把完整的系统提示词重新发送一遍吗?
这些问题听起来像是“实现细节”,但说实话,它们直接决定了推理速度、token 成本、上下文质量,以及为什么你在一个工具里能连续对话两小时,而在另一个里半小时就开始“失忆”。
这次我们就通过对
| 维度 | Claude Code | Codex CLI |
|---|---|---|
文件 | claude.exe | codex.exe |
路径 | npm/@anthropic-ai/claude-code/bin/ | npm/@openai/codex/.../bin/ |
大小 | 225 MB | 308 MB |
类型 | PE32+ Console x86-64 | PE32+ Console x86-64 |
节数 | 12 | 10 |
语言 | TypeScript → Bun 编译 | Rust → MSVC 编译 |
JS 引擎 | Bun (Ja vaScriptCore) | V8 (嵌入) |
配置语言 | JSON/TOML | Starlark (Bazel 方言) |
API 后端 | api.anthropic.com | chatgpt.com/backend-api/codex |
API 协议 | Anthropic Messages API (HTTP) | OpenAI Responses API (WebSocket) |
两者的共同点是都把自己编译成了独立可执行文件——不是 Node.js wrapper,也不是 Python 脚本,而是包含了完整运行时环境的原生二进制。这意味着你不需要安装 Node、Python 或任何运行时依赖,下载即用。这一点倒是英雄所见略同。
但它们的共同点到此为止。在 API 调用机制上,两者做出了截然不同的选择。一个选择了简单可靠的传统 HTTP,另一个则走向了高效精巧的 WebSocket 有状态协议。
Claude Code 的每次 API 调用都是一个独立的 HTTP POST 请求:
POST https://api.anthropic.com/v1/messages
Authorization: x-api-key sk-ant-...
anthropic-version: 2023-06-01
Content-Type: application/json
{
"model": "claude-fable-5",
"system": "You are Claude... [~8000 tokens 的系统提示词]",
"messages": [
{"role": "user", "content": "帮我修复这个 bug"},
{"role": "assistant", "content": [
{"type": "tool_use", "name": "Grep", ...}
]},
{"role": "user", "content": [
{"type": "tool_result", ...}
]},
// ... 完整历史 ...
],
"tools": [/* ~50+ 工具定义,每个包含完整 JSON Schema */],
"max_tokens": 32000,
"thinking": {"type": "enabled", "budget_tokens": 16000}
}
通过对 codex.exe 二进制的逆向分析,我们发现它实现了一个精巧的
TurnStart 请求 = {
clientUserMessageId: string, // 客户端消息 ID
input: UserInput, // 用户输入
responsesapiClientMetadata: {...}, // 客户端元数据 (版本/OS/终端类型)
additionalContext: [...], // Skills, Memory, Git status...
environments: {...}, // 环境变量
runtimeWorkspaceRoots: [...], // 工作区根目录
approvalPolicy: string, // on-request | never | always
approvalsReviewer: string, // 审核者设置
sandboxPolicy: string, // readonly | workspace-write | ...
serviceTier: string, // Free | Plus | Pro | Team | Enterprise
effort: string, // low | medium | high | xhigh
outputSchema: {...}, // 输出格式约束
collaborationMode: string, // primary | review | ...
multiAgentMode: string, // disabled | proactive | ultra
// 系统提示词和工具定义也在此发送!
system_prompt: "...",
tools: [...]
}
TurnSteer 请求 = {
expectedTurnId: string, // 服务端状态索引
// 只发送工具调用的结果,不重复系统提示词和工具定义!
tool_results: [...]
}
假设用户输入“帮我修复 login 模块的空指针异常”,模型需要 5 步完成(搜索 → 读取 → 分析 → 编辑 → 总结)。来看看两种协议下,每个步骤到底消耗了多少 token。
用户消息 #1 (Turn 开始)
│
├─ API 请求 #1: POST /v1/messages
│ ├─ system: [8,000 tokens]
│ ├─ tools: [2,000 tokens]
│ ├─ user_msg: "帮我修复..."
│ └─ 总输入: ~11,000 tokens
│
├─ API 请求 #2: POST /v1/messages
│ ├─ system: [8,000 tokens] ← 再次发送
│ ├─ tools: [2,000 tokens] ← 再次发送
│ ├─ 完整历史 + tool_result
│ └─ 总输入: ~15,000 tokens
│
├─ API 请求 #3: POST /v1/messages
│ ├─ system: [8,000 tokens] ← 再次发送
│ ├─ tools: [2,000 tokens] ← 再次发送
│ ├─ 完整历史 + tool_result
│ └─ 总输入: ~18,000 tokens
│
├─ API 请求 #4: ... (继续累积)
│
└─ API 请求 #5: ...
└─ 总输入: ~25,000 tokens
累计 input tokens:
原始 ≈ 11K + 15K + 18K + 21K + 25K = 90,000 tokens
考虑 Prompt Caching (system+tools 缓存后降价 90%):
实际 ≈ 11K + 6K + 9K + 12K + 16K = 54,000 tokens
用户消息 #1 (Turn 开始)
│
├─ TurnStart (WebSocket msg #1)
│ ├─ system_prompt: [3,000 tokens]
│ ├─ tools: [5,000 tokens]
│ ├─ context: [2,000 tokens]
│ └─ 总输入: ~10,000 tokens (截断限制)
│
├─ TurnSteer (WebSocket msg #2)
│ ├─ 只发增量: tool_result + next_prompt
│ ├─ 不重复 system_prompt
│ ├─ 不重复 tools
│ └─ 总增量: ~2,000 tokens
│
├─ TurnSteer (WebSocket msg #3)
│ └─ 增量: ~3,000 tokens
│
├─ TurnSteer (WebSocket msg #4)
│ └─ 增量: ~3,000 tokens
│
└─ TurnSteer (WebSocket msg #5)
└─ 增量: ~2,000 tokens
累计 input tokens: ~10K + 2K + 3K + 3K + 2K = 20,000 tokens
同一个任务(5 步完成),input tokens 消耗:
Claude Code (无缓存): ████████████████████████████████████████ 90,000
Claude Code (有缓存): ████████████████████████ 54,000
Codex CLI: ████████ 20,000
├────────────────────────────────────────┤
0 90,000 tokens
差距一目了然。不过要注意,这只是 input token 维度的对比。实际体验还受到输出速度、延迟、可用性等多方面因素影响。
在 codex.exe 的 .rdata 段中,我们找到了嵌入的 TypeScript 类型定义文件。这相当于 OpenAI 把源码直接打包进了二进制:
// TurnSteerParams.ts (嵌入在 codex.exe 中的源文件) /** * Required active turn id precondition. * The request fails when it does not match the currently active turn. */ expectedTurnId: string
以及错误处理逻辑:
"expectedTurnId must not be empty" "no active turn to steer"
这些字符串告诉我们,服务端严格校验 turn 状态,不允许在无活动 turn 时发送 steer 请求。
OpenAI 的服务端维护一个
TurnSession {
turn_id: "turn_abc123",
thread_id: "thread_xyz",
// ⬇ 以下内容在 TurnSteer 时不再传输
system_prompt: { // 完整的系统指令
base_instructions: "...",
personality: "friendly",
skills: [...],
memory_entries: [...]
},
tool_registry: { // 完整的工具注册表
"fs/readFile": { schema: {...} },
"fs/writeFile": { schema: {...} },
"command/exec": { schema: {...} },
// ... 50+ 工具
},
conversation: [ // 累积的完整对话
{role: "user", content: "..."},
{role: "assistant", tool_calls: [...]},
{role: "tool", content: "..."},
// ...
],
settings: { // Turn 级设置快照
approval_policy: "on-request",
sandbox_policy: "workspace-write",
service_tier: "plus",
effort: "medium"
},
model_state: { // GPT-5.5 推理状态
kv_cache: [...], // 已计算的 KV Cache
position: 15432 // 当前 token 位置
}
}
关键是
expectedTurnId 找到对应的 session这意味着 TurnSteer 的
对比 Claude Code,每次 HTTP POST 都要完整地 prefill system prompt + tools + history,即使有 Prompt Caching 降低了计费成本,
Claude Code 的设计哲学:
"可靠性 > 效率"
"简单 > 精巧"
优点:
├─ 容错性极强: 任何一个请求失败,重试就是完整的,不需要恢复任何会话状态
├─ 服务端简单: 不需要维护 WebSocket 会话状态,水平扩展毫无压力
├─ 无状态扩展: 请求可以路由到任意服务器,负载均衡无缝
├─ 跨 turn 复用: Prompt Caching 可以横跨多个请求,甚至跨用户
├─ 调试友好: 每个请求都是可独立复现的,curl 就能验证
└─ 1M 上下文窗口: 有空间容纳重复发送的开销,不怕浪费
代价:
├─ 每次请求都要发送完整 payload(网络开销)
├─ 每次请求都要 prefill(延迟)
└─ 依赖服务端缓存来降低成本(不是所有场景都生效)
Codex CLI 的设计哲学:
"效率 > 简单"
"精巧 > 通用"
优点:
├─ Token 成本极低: turn 内不重复发送上下文
├─ TTFT 极低: KV Cache 持续复用,几乎零延迟
├─ 实时性好: WebSocket 天然支持 streaming + 通知,双向通信灵活
├─ 分层设计: TurnStart/TurnSteer/TurnInterrupt 各司其职,职责清晰
└─ 协议级支持: turn 是一等概念,不是通过无状态模拟出来的
代价:
├─ 服务端复杂度高: 需要维护大量并发 Turn Session,有状态服务运维难度大
├─ 容错性差: 断连 = 整个 turn 丢失,需要额外的重连和恢复机制
├─ 不可跨 turn 复用: 每个用户消息都是新 TurnStart,之前的 KV cache 作废
├─ 硬截断风险: 10K tokens 的截断上限,长对话内容被直接丢弃
└─ 调试困难: 无法独立复现单个 TurnSteer,需要模拟整个会话序列
| 策略 | Claude Code | Codex CLI |
|---|---|---|
窗口大小 | 最高 1M tokens | 272K tokens |
截断方式 | Auto-compact 自动摘要 | 10K tokens 硬截断 |
长对话管理 | 渐进压缩 → 摘要 | 激进截断 → 丢失 |
跨 turn 记忆 | Memory 文件系统 | Memory 系统 (类似) |
子 Agent | 独立上下文窗口 | 共享 session |
这解释了为什么很多用户感觉 Claude Code 在长对话中更“持久”——不是因为它完全不丢上下文,而是因为 1M 的窗口太大,在达到极限之前 Auto-compact 已经帮你摘要了。而 Codex 的 10K 硬截断意味着,如果你的对话 + system prompt + tools 超过了这个阈值,早期内容会被直接丢弃。这可以看作是一种更激进的“遗忘”策略。
ANTHROPIC_DEFAULT_FABLE_MODEL → claude-fable-5 ANTHROPIC_DEFAULT_OPUS_MODEL → claude-opus-4-8 ANTHROPIC_DEFAULT_SONNET_MODEL → claude-sonnet-4-6 ANTHROPIC_DEFAULT_HAIKU_MODEL → claude-haiku-4-5 ANTHROPIC_SMALL_FAST_MODEL → (备选快速模型)
{
"slug": "gpt-5.5",
"display_name": "GPT-5.5",
"description": "Frontier model for complex coding, research, and real-world work.",
"context_window": 272000,
"max_context_window": 272000,
"auto_compact_token_limit": null,
"truncation_policy": { "mode": "tokens", "limit": 10000 },
"default_reasoning_level": "medium",
"supports_parallel_tool_calls": true
}
max_context_window: 1,000,000(预留扩展) 从模型配置能看出,OpenAI 也在为长上下文预留空间,但当前的截断策略仍然非常激进。而 Anthropic 则选择了更大的窗口和更聪明的摘要策略。
| 维度 | Claude Code | Codex CLI |
|---|---|---|
认证方式 | API Key / OAuth / AWS Bedrock / GCP Vertex / Foundry | ChatGPT OAuth / API Key / AWS Bedrock |
沙箱策略 | readonly / workspace-write / danger-full-access / linux-seccomp | readonly / workspace-write / danger-full-access / windows-sandbox |
审批机制 | never / on-request / always + Reviewer Agent | never / on-request / always + Guardian Agent |
遥测端点 | api.anthropic.com | ab.chatgpt.com/otlp/v1/metrics + Sentry |
联邦认证 | OIDC Federation + WIF | JWT Agent Identity |
两者在安全模型上高度相似——都有沙箱分层、审批门控、代码审查 Agent,这已经成了这个品类的基本安全基线。差异主要在于实现细节:Claude Code 支持更多企业认证方式(Vertex AI、Foundry),Codex 的 Windows 沙箱集成更深,可能跟微软生态有关。
| 问题 | Claude Code 的答案 | Codex CLI 的答案 |
|---|---|---|
每次 API 调用都发系统提示词吗? | 是。但 Prompt Caching 将成本降到 10% | 不。TurnStart 发一次,TurnSteer 不发 |
一个用户消息调用多少次 API? | N 次(每个 tool round-trip 一次 HTTP POST) | 1 次 TurnStart + (N-1) 次 TurnSteer |
谁能用更少的 token 完成同样任务? | ~54,000(有缓存时) | ~20,000(无缓存也低) |
谁的首字延迟更低? | 每次都要 prefill | TurnSteer 时 KV Cache 直接续,接近零延迟 |
谁的长对话体验更好? | 1M 窗口 + auto-compact | 272K 窗口 + 10K 硬截断 |
谁的架构更简单? | 无状态 HTTP,水平扩展友好 | 有状态 WebSocket,运维复杂度高 |
谁更容易调试? | 每个请求是独立的、可复现的 | 依赖会话状态,复现需要模拟整个序列 |
差异在于它们在同一个根本问题上做出了相反的选择:
Anthropic 的回答是:“客户端负责每次把完整上下文发给我,我用缓存帮你省钱。” OpenAI 的回答是:“你第一次发完整上下文,后面只发增量,我帮你在服务端记着。”
两种方案经过各自优化后的总成本和体验差距并没有看起来那么大——真正的差异在于生态位。Claude Code 靠 1M 窗口 + Prompt Caching 在“持久对话”这个场景里占优,Codex CLI 靠 KV Cache 复用在“快速迭代”的场景里更敏捷。
最终用户感受到的差异,往往不是协议层的选择导致的,而是
俄罗斯最大yandex入口外贸日报直达链接
腾讯元宝怎么用来分析股票基金的基本面信息?
美好的简约网名男生(精选100个)
盖乐世社区怎么删除帖子?盖乐世社区个人发布内容撤回步骤
Bubbly无法连接服务器修复方法
欧易OKX官方网站直达入口 2026欧易官方App安卓版v7.1.0下载安装
新浪人工智能热点小时报丨2026年06月20日02时_今日实时人工智能热点速递
问题:CIA币好不?Cia Protocol币今日上线:价格预测、代币经济学和未来潜力
国际贵金属走低,现货黄金价格跌0.49%
wallpaper壁纸声音怎么开启
倒数日怎么注册 倒数日账号注册教程
币安Binance交易所官方入口 币安App下载安装与实名注册教程
短剧《退休金断供,女儿女婿慌了》剧情介绍
动漫《KiraKira 光之美少女 A La Mode》剧情介绍
《梦幻西游》特殊鬼怪怎么抓-隐藏变异鬼应对要点
漫威新剧《钢铁侠和他的超能朋友们》今日炸更11集,Thor和Loki惊喜客串
以太坊(ETH)未来数周或持续呈现低迷态势,多重因素制约价格走势
宝马水鸟摩托车的官方指导价是多少
三个字的带七男生网名(精选100个)
文雅简易网名男生可爱(精选100个)
手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc