OpenAI Codex 工作原理

内容管家 技术解析评论40字数 2669阅读8分53秒阅读模式

OpenAI Codex 工作原理深度解析

简介:不仅是一个模型

当 OpenAI 推出 Codex 这款云端编程智能体时,团队面对的最棘手问题几乎与 AI 模型本身无关。

Codex 的底层模型 codex-1,是基于 OpenAI o3 微调而来的软件工程专用版本。这个模型固然重要,但它只是整套系统的一个组件。真正的工程挑战集中在模型之外的部分:

  • 如何从五个不同来源组合出正确的 Prompt?
  • 对话历史不断膨胀、即将超出模型记忆上限时该怎么办?
  • 如何让同一个智能体在终端、网页浏览器和三款不同 IDE 中通用,而无需每次重写?

围绕这些问题,OpenAI 走出了一条自研协议和架构的道路。

正文图片

第一层:Agent Loop 运作机制

Codex 的核心是一个被称为 Agent Loop(智能体循环) 的机制。整体流程是:

  1. 接收用户输入
  2. 构建完整 Prompt
  3. 发送给模型进行推理
  4. 获取响应

关键在于,模型返回的不一定是最终答案——更多时候,它会返回一个工具调用(tool call),例如"运行这条 shell 命令,然后告诉我结果"。此时 Agent 执行该工具调用,将输出追加到 Prompt 中,再次查询模型。这个循环可能重复数十次,直到模型最终生成面向用户的最终消息。

Codex 可调用的工具包括:

正文图片
  • 读写文件
  • 执行 Shell 命令
  • 运行测试套件
  • 调用 Linter
  • 执行类型检查器

举一个实际场景:用户输入"修复 auth 模块中的这个 Bug",Agent 可能依次执行以下步骤——读取多个相关文件 → 运行现有测试观察失败情况 → 编辑代码 → 再次运行测试 → 修复 Lint 错误 → 最后运行测试确认通过 → 生成提交。

模型负责每一步的推理判断,而 Harness(控制框架)负责执行命令、收集输出、管理权限、判断循环何时终止。 这种分工直接影响了 Codex 的实际用法:OpenAI 内部工程团队用它来外包那些重复性的、边界清晰的任务,例如重构、批量重命名、编写测试用例,以及分诊 on-call 问题。

Agent Loop 还有一层"外循环":每一次推理加工具调用的组合被称为一个 Turn(轮次)。但对话不会在一个 Turn 后结束——用户发送跟进消息时,整个历史(包括之前所有的工具调用及其输出)都会被包含在下一轮 Prompt 中。这也是成本快速攀升的根源。

第二层:Prompt 构建与内存管理

当用户在 Codex 中输入一条请求时,这条消息会成为庞大 Prompt 的最底层。在它之上,系统会依次堆叠以下内容:

正文图片
层级 角色 说明
环境上下文 system 当前工作目录、Shell 环境信息
AGENTS.md 内容 developer 仓库中的项目级指令(代码规范、测试命令等)
沙盒权限规则 developer 安全边界定义
开发者配置文件 developer 用户自定义配置
模型特定指令 developer 针对 codex-1 的调优说明
工具定义 system 可用工具的描述与调用方式
系统消息 system 顶层系统级提示

每个层级都带有角色标签(system / developer / user),用于向模型表明优先级。服务端控制顶部层级的排序,客户端控制其余部分。

这种分层结构确保模型始终拥有丰富的执行环境上下文——但代价是,在用户说任何话之前,Prompt 本身就已经很庞大了。而且它只会越来越大。

关键问题:Token 消耗呈二次方增长。 模型每执行一次工具调用,产生的输出都会被追加到 Prompt 中;每开启一个新对话轮次,完整的历史记录(包含所有工具调用及输出)都会重新发送。这意味着:整个对话过程中发送给 API 的 JSON 数据量呈二次方增长

正文图片

第一个 Turn 发送 X 数据量;第二个 Turn 发送 X 加新数据;第三个 Turn 发送 X 加之前数据加更多数据……以此类推。

OpenAI 刻意接受了这个成本。他们本可以使用服务端参数来让 API 记忆之前的对话状态,避免重复发送,但这样做会破坏每个请求的无状态性,并导致无法支持需要"零数据保留(Zero Data Retention)"的客户。因此,每个请求都是自包含的,携带完整对话历史。

上下文管理:缓存、前缀与压缩

Codex 的关键优化手段是提示词缓存。由于 Codex 总是将新内容追加到现有提示词的末尾,旧提示词始终是新提示词的精确前缀。这种前缀特性使得 OpenAI 能够复用先前推理计算的结果——即便数据传输量呈二次方增长,实际模型运算量仍能保持在近线性水平。

正文图片

然而,前缀特性相当脆弱。任何改变提示词开头或中间部分的操作——如切换模型、更改工具或修改沙箱配置——都会破坏缓存命中。OpenAI 添加 MCP 工具支持时,曾意外引入一个 bug:工具列表在不同请求间的排列顺序不一致。这种不一致足以直接摧毁缓存命中率。

即便有缓存机制保驾护航,对话终究会触及上下文窗口上限,即模型在单次推理调用中能处理的最大令牌数。一旦触及这个上限,Codex 会对对话进行压缩——用一个小得多的代表性版本替换完整历史记录,同时通过一个携带模型潜变量的加密载荷来保留模型对事件的理解。现实中压缩机制比简单摘要更为精细,但核心思路不变:管理上下文窗口是一个需要一等重视的工程问题,而非事后补救。

AGENTS.md:上下文归属的设计决策

值得单独一提的是 AGENTS.md 文件,它代表了一种关于上下文应处于何处的设计选择。OpenAI 并未将项目特定知识硬编码进系统,而是让开发者将这些文件放在代码仓库中,与代码平级。文件告诉 Codex 如何浏览代码库、执行哪些测试命令、如何遵循项目规范。模型有了它们表现更好,但也能在缺少它们的情况下正常工作。

正文图片

多端落地:App Server 架构

Codex 起源于一款命令行工具,在终端中运行,操作本地代码库。

随后 OpenAI 需要将它集成到 VS Code、Web 应用、macOS 桌面应用,以及 JetBrains 和 Xcode 等第三方 IDE 中。为每个平台重写 Agent 逻辑显然不可行。

如前所述,第一步尝试是将 Codex 作为 MCP 服务器暴露。但团队发现 MCP 的语义无法承载 Agent 对话的全部分量——Codex 需要以流式方式逐步输出模型推理过程,需要在执行某些命令前暂停并请求用户审批,需要输出结构化 diff。这些交互模式过于丰富,MCP 当时的表达能力不足以支撑。

于是 App Server 应运而生。所有核心 Agent 逻辑——Agent 循环、线程管理、工具执行、配置与认证——都集中在 OpenAI 称为 "Codex Core" 的单一代码库中。App Server 用 JSON-RPC 协议将其包装,任何客户端都可以通过标准输入输出与其通信。

正文图片

双向协议与人机协作

该协议支持全双向通信:

  • 客户端向服务端发请求:启动线程、提交任务。
  • 服务端向客户端发请求:例如在执行 shell 命令前请求审批。

Agent 的当前轮次会暂停,直到用户回复"允许"或"拒绝"。这种设计让 Agent 在自主性与人工监督之间取得平衡,而无需将这些策略硬编码到 Agent 循环本身。

不同平台的部署差异

  • VS Code 扩展与桌面应用:将 App Server 二进制文件打包,启动为子进程,保持双向 stdio 通道。
  • Web 应用:App Server 运行在云端容器中。Worker 检出代码仓库、启动二进制文件,通过 HTTP 将事件流推送到浏览器。状态存储在服务端,用户关闭标签页后工作仍可继续。
  • 第三方合作(如 Xcode):客户端保持稳定,仅在有新版本 App Server 时更新指向。协议设计为向后兼容,旧版客户端可以安全地与新版服务端通信。

这一架构并非一开始就规划好的。它从 CLI 出发,经历了一次失败的 MCP 尝试,最终演化为支撑所有 Codex 界面的 App Server 协议。这条演进路径本身就是关于系统设计的有益教训:正确的抽象通常要到试过错误的之后才会出现

正文图片

总结与实用建议

OpenAI 的实践验证了一个核心观点:模型是组件,Agent 是系统。大部分工程工作量实际上在系统层面。

如果你是 Codex 用户,理解这些机制能帮助你更高效地使用它:

  • 编写清晰的 AGENTS.md 文件,为 Agent 提供项目特定的上下文,显著提升输出质量。
  • 任务范围宜窄不宜宽:模糊、开放式的请求效果不佳,Agent 循环在每个周期都有明确下一步时效率最高。
  • 了解长对话会因上下文窗口限制和压缩而质量下降,为新任务开启新线程往往能获得更好的结果。

现存局限

Codex 仍有明显的局限:不支持前端工作的图像输入;无法在任务中途纠正 Agent 方向;委托给远程 Agent 的响应延迟高于交互式编辑,这种工作流转变需要适应。OpenAI 正在推进让与 Codex 的交互更像是与同事的异步协作,但愿景与当前产品之间的差距仍然显著。

延伸阅读

 
内容管家

发表评论