跳到主要内容

OpenAI Codex CLI — 架构与原理

30 秒导读: Codex CLI 是 OpenAI 出的一个跑在你本机终端里的编码 agent——你用自然语言提需求,它读你的代码、跑命令、改文件,帮你把活干完。它用 Rust 写成,最值得学的三件事是:① 把「模型说话 → 执行工具 → 结果回灌」串成一个干净的回合循环;② 一套独门的 apply_patch 模糊补丁格式,让模型不必逐字复现原文也能精确改代码;③ 用操作系统级沙箱(macOS seatbelt / Linux landlock)把模型跑的命令关进笼子,并在被拒时按策略再升级


1. 这是什么(零基础也能懂)

  • 一句话定义: Codex CLI 是一个本地运行的编码 agent——一个能读写你项目文件、执行 shell 命令、并由大模型驱动的命令行程序。

  • 解决什么问题 / 给谁用: 假设你在终端里,想让 AI 帮你「给这个函数加单测」「把这个 bug 修了」「把依赖升级一版」。你不想把代码贴到网页、也不想 AI 在你机器上乱跑命令。Codex 就是干这个的:它在你本机跑,能看到整个仓库,能真的执行命令验证自己改得对不对,同时被沙箱和审批策略管着,不至于失控。

  • 它能做什么:

    • 多回合对话式地理解任务,自主决定下一步调哪个工具;
    • apply_patch 改文件、用 shell 跑命令、跑测试看结果;
    • 按你设的「审批策略 + 沙箱策略」决定哪些操作自动放行、哪些要问你;
    • 上下文塞满时自动压缩历史继续干;
    • 接 MCP 工具、skills、子 agent、IDE 等扩展面。
  • 用起来什么样: 装好后在项目目录里敲 codex,然后像聊天一样提需求:

$ codex
› 给 src/seek_sequence.rs 里的 normalise 函数补几个单测

• 读取 src/seek_sequence.rs
• apply_patch src/seek_sequence_tests.rs (+42 行) [自动批准]
• cargo test seek_sequence [在沙箱中运行]
test result: ok. 5 passed; 0 failed
已加好测试并验证通过。

注意每一步——读文件、打补丁、跑测试——都是模型主动发起的工具调用,Codex 负责执行、把结果喂回去,直到模型认为干完了。

  • 一句话直觉/类比: 把 Codex 想成一个坐在你电脑前、戴着手铐的结对程序员。「大脑」是远端的模型,「手」是本地的工具(改文件 / 跑命令),「手铐」是沙箱(它只能在你划定的范围内动手),「管家」是审批策略(危险动作得先问你)。整份代码库就是在精心设计这套「大脑—手—手铐—管家」怎么协作。

2. 顶层全景(它大概怎么转)

Codex 是一个庞大的 Rust workspace(codex-rs/ 下有 100+ 个 crate),但价值高度集中在 codex-core 这一个 crate。其余 crate 大多是它的卫星:协议定义、各前端(TUI / exec / MCP server)、沙箱实现、补丁解析器等。

先看大盘——一次请求的数据流:

你(终端 / IDE / exec)
│ Op::UserInput ← 提交「指令」(protocol crate 定义)

┌─────────────────────────────────────────────┐
│ ThreadManager → CodexThread → Session │ 会话/线程编排
│ (core::thread_manager / session) │
└───────────────┬───────────────────────────────┘
│ 起一个 RegularTask

┌─────────────────────────────────────────────┐
│ run_turn ── 回合循环 ──┐ │ ← 本项目的心脏
│ ① 压缩(如需) ② 采样请求 ③ 执行工具 ④ 回灌 │
│ (core::session::turn) │ │
└──────┬──────────────────┼─────────────────────┘
│ 采样 │ 工具
▼ ▼
ModelClient ToolRouter → ToolOrchestrator
(Responses API) (审批→选沙箱→执行→失败升级)
│ │
▼ ▼
远端大模型 shell / apply_patch / MCP …


OS 沙箱(seatbelt / landlock)

怎么读这张图: 从上往下是一次用户指令的生命周期。左路「采样」去问模型下一步干嘛,右路「工具」把模型的决定落到真实世界,二者在 run_turn 里反复交替,直到模型只回一句话(不再要工具)为止。

主要部件一句话职责:

部件干什么在哪
protocol crate定义 agent 与前端之间的「指令(Op)/事件(EventMsg)」数据契约,以及审批/沙箱策略枚举codex-rs/protocol/src/protocol.rs
ThreadManager / Session编排会话、线程、配置、各类 manager(MCP/skills/插件)codex-rs/core/src/thread_manager.rssession/session.rs
run_turn(回合循环)反复「采样→执行工具→回灌」,中途按需压缩上下文codex-rs/core/src/session/turn.rs
ModelClient通过 Responses API(WebSocket)流式向模型采样codex-rs/core/src/client.rs
ToolRouter / ToolOrchestrator把模型的工具调用路由到 handler,并统一做审批+沙箱+重试codex-rs/core/src/tools/router.rstools/orchestrator.rs
apply_patch解析并落地独门的模糊补丁格式codex-rs/apply-patch/core/src/tools/handlers/apply_patch.rs
sandboxingseatbelt(mac)/ landlock+seccomp(linux)/ 受限令牌(win)三套 OS 沙箱codex-rs/sandboxing/
context_manager / compact维护对话历史,token 超限时压缩codex-rs/core/src/context_manager/compact.rs

主线走一遍(高层,不进代码):

  1. 前端(TUI/exec/MCP)把你的话包成一条 Op::UserInput 提交给 Session
  2. Session 起一个 RegularTask,进入 run_turn
  3. run_turn 先把历史拼成一次采样请求,经 ModelClient 流式发给模型。
  4. 模型回的若是工具调用(如 shell / apply_patch),ToolRouter 路由到对应 handler,ToolOrchestrator 走「审批→选沙箱→执行→失败可升级」,结果作为 function output 回灌历史,继续下一轮采样
  5. 模型回的若只是一句话(不再要工具),回合结束,把这句话作为最终回复发回前端。
  6. 任意一轮发现 token 快满,就触发自动压缩(把旧历史换成摘要)后再继续。

3. 核心机制(本库挑了三个最值得学的)

这个项目太大,面面俱到会变成「源码考古」。我们只深入讲最能代表 Codex、也最可借鉴的三条主线,各占一章:

机制一句话章节
回合循环「采样→工具→回灌」如何串成一个会自动压缩、能并发执行工具、能被打断的循环01-agent-loop.md
apply_patch一套让模型「大致写对就能精确改代码」的模糊补丁格式 + 四级容错匹配02-apply-patch.md
沙箱与安全审批策略 × OS 沙箱 × 失败再升级,三层叠起来既安全又少打扰03-sandbox-safety.md

4. 阅读地图(建议顺序)

  1. 先读本页 §1–§2——建立「这是什么、大盘怎么转」的直觉。
  2. 01-agent-loop.md——理解 Codex 的「心跳」。读懂它,其余都好挂上去。
  3. 02-apply-patch.md——Codex 最独特的工程亮点,可单独拿走借鉴。
  4. 03-sandbox-safety.md——Codex 区别于「玩具 agent」的地方:它敢在你真机上跑命令,靠的就是这套护栏。

5. 横向对比(同 shelf 兄弟)

Codex 在 ai-agent-reference / coding-agents 这一格,和 Aider、Claude Code 等是兄弟。几个取舍上的差异:

维度Codex 的取舍
实现语言Rust(多数同类是 Python/TS)——换来单二进制分发、OS 沙箱能力、和原生进程隔离
编辑格式独门 apply_patch(*** Begin Patch 标记 + 上下文锚点 + 多级模糊匹配),而非 unified diff 或整文件重写
安全模型OS 级沙箱(seatbelt/landlock)做成一等公民,且「沙箱被拒 → 按审批策略再升级」
模型接口走 OpenAI Responses API(支持 WebSocket 流式),回合内复用同一连接

具体「为什么模糊匹配」「沙箱为什么分三层」见对应章节;跨库的「编辑落地」「沙箱化」原理对比见本 shelf 总库 doc。

6. 代码地图(导航索引)

主题文件关键符号
回合循环入口codex-rs/core/src/session/turn.rsrun_turnrun_sampling_request
任务包装codex-rs/core/src/tasks/regular.rsRegularTaskSessionTask::run
工具路由codex-rs/core/src/tools/router.rsToolRouterdispatch_tool_call_with_terminal_outcome
工具编排(审批+沙箱+重试)codex-rs/core/src/tools/orchestrator.rsToolOrchestratorrunrun_attempt
补丁解析codex-rs/apply-patch/src/parser.rsparse_patchHunkUpdateFileChunk
模糊匹配codex-rs/apply-patch/src/seek_sequence.rsseek_sequencenormalise
补丁拦截/落地codex-rs/core/src/tools/handlers/apply_patch.rsintercept_apply_patch
协议数据契约codex-rs/protocol/src/protocol.rsOpEventMsgAskForApprovalSandboxPolicy
安全评估codex-rs/core/src/safety.rsassess_patch_safetySafetyCheck
沙箱管理codex-rs/sandboxing/src/manager.rsSandboxManagerSandboxType
seatbelt 策略codex-rs/sandboxing/src/seatbelt_base_policy.sbpl(deny default) 起的策略
上下文/历史codex-rs/core/src/context_manager/history.rsContextManager
压缩codex-rs/core/src/compact.rsSUMMARIZATION_PROMPTrun_inline_auto_compact_task