Overview
这篇文章想系统回答一个问题:Codex 到底是怎么工作的。
很多人第一次接触 Codex 时,都会有一种很强的“违和感”:
- 它不只是聊天,而是真的会读代码、改文件、跑命令;
- 它不是每次都等命令跑完才说话,而是会一边看输出一边继续推进任务;
- 它看上去像一个模型,但很多关键行为其实并不发生在模型内部;
- 它既能在本地执行,也能在云端环境里跑,而且这两种模式的安全边界还不完全一样。
如果只把 Codex 看成“一个会写代码的 LLM”,很多现象会解释不清。更准确的理解方式是:
Codex 是一个由模型负责决策、由 harness 负责编排、由 runtime 负责执行、并由 sandbox 与 approvals 负责边界控制的 agent system。
这篇文章会把这个系统拆开来看。重点不是介绍某个 API 参数,而是建立一个稳定的心智模型:当用户发出一个请求后,究竟发生了什么,哪些职责属于模型,哪些职责属于 harness,哪些职责属于 runtime,沙盒和审批又分别控制什么。
Why Codex Feels Different
Codex 和普通对话模型最大的差别,不在于“更会写代码”,而在于它被放进了一个可执行的闭环里。
普通聊天模型的典型行为是:
- 读取上下文;
- 生成一段回复;
- 结束这一轮。
而 Codex 的典型行为更像:
- 读取上下文和工具定义;
- 决定下一步动作;
- 调用工具;
- 观察工具结果;
- 根据新观察继续推理;
- 重复这个循环,直到任务结束。
因此,Codex 的关键特征不是“回答得更聪明”,而是它能把用户目标拆成一系列可执行动作,并在执行结果的反馈下持续调整后续行为。
这也是为什么理解 Codex 时,只看模型往往不够。很多决定产品体验的关键能力,例如:
- 能不能真正跑 shell 命令;
- 命令失败后能不能恢复;
- 写文件时有没有边界;
- 什么时候需要用户审批;
- 长命令的输出怎么流式展示;
- 多个 agent 怎样协同;
这些都不只属于模型,而属于模型外面的整套执行系统。
Message Roles and Instruction Hierarchy
先看最上层的上下文结构。
过去很多人熟悉的 chat 格式里,角色通常只有:
systemuserassistant
但在现在的 Codex / OpenAI agent 语境里,developer 同样是核心角色。它往往承载的是宿主程序写给模型的工作规则,而不是普通对话内容。
可以粗略理解为:
system:平台级规则;developer:应用级规则,也就是 Codex 这个产品要求 agent 如何工作;user:当前任务;assistant:模型之前已经给出的自然语言回复或工具调用结果。
在 Codex 里,developer 往往会规定这类事情:
- 你是一个 coding agent;
- 先读代码再改代码;
- 优先使用哪些工具;
- 输出分成
commentary和final; - 不要做哪些危险 git 操作;
- 什么时候要更新用户进度;
- 什么情况下必须遵守沙盒和审批策略。
所以在架构上,developer 更像一层应用运行规则,而不是普通聊天历史。Codex 之所以表现得像“有工作流程”的 agent,很大程度上就是因为它始终处在一套强约束的指令体系之下。
Tools: Spec vs Implementation
再往下看工具。
模型并不会直接看到工具的源码实现。它首先看到的是一份 tool spec,也就是结构化接口描述。这个 spec 通常会告诉模型:
- 工具名是什么;
- 这个工具做什么;
- 参数有哪些;
- 参数的类型和约束是什么;
- 结果大概会返回什么结构。
例如一个执行命令的工具,spec 里可能会包含:
name = exec_commanddescription = Runs a command in a PTYparameters.cmd = stringparameters.workdir = stringparameters.yield_time_ms = number
模型真正会做的,是基于这份 spec 决定:
- 现在需不需要调用工具;
- 如果需要,应该调用哪个工具;
- 参数该怎么填。
所以从抽象上说:
tool spec是暴露给模型看的接口定义;tool implementation是宿主程序里真正干活的代码。
这和传统软件里的“API 文档”和“后端实现”关系非常像。模型看到的不是实现细节,而是能力边界。
Harness: The Control Plane
接下来进入最容易混淆、但也最重要的一层:harness。
如果用一句话定义:
Harness是包在模型外面、把用户任务组织成持续 agent loop 的控制系统。
它关注的不是“某条命令怎么 spawn”,而是更上层的问题:
- 这一轮该不该调用工具;
- 工具调用前要不要审批;
- 失败后要不要重试;
- 当前任务是否已经完成;
- 输出该展示给用户什么;
- 多 agent 之间如何分工;
- 哪些规则需要始终保留在上下文里。
因此,harness 更像 control plane。它在意的是任务过程的组织、约束与调度。
在 Codex 语境里,harness 一般会包含这些职责:
-
Agent loop orchestration
把“读上下文 -> 选动作 -> 调工具 -> 看结果 -> 再决策”组织成一个可持续运行的闭环。 -
Instruction layering
把system、developer、user等不同来源的指令组织成上下文,并维护优先级。 -
Tool routing
接住模型发出的 tool call,把它路由给对应的本地或云端实现。 -
Approval and policy gating
在真正执行动作之前,先判断是否落在当前权限边界内,是否需要用户批准。 -
State and session management
维护会话状态、长进程 session、子 agent 状态、工具调用历史等。 -
User interaction
决定什么时候发中间进度、什么时候等待审批、什么时候给最终结果。
因此,harness 的关键词不是“执行”,而是编排。
Runtime: The Execution Plane
与 harness 相对,runtime 更像 execution plane。
如果 harness 负责回答“该不该做、怎样组织做”,那么 runtime 负责回答:
既然决定要做了,那这件事怎样在真实环境里安全地执行起来?
runtime 更靠近操作系统,典型职责包括:
- 把工具请求转成真实的进程执行;
- 设置工作目录、环境变量、stdio 策略;
- 应用沙盒策略;
- 应用网络限制;
- 处理超时、取消、输出截断、流式输出;
- 收集 stdout / stderr 并回传给 harness。
所以更准确的关系不是“harness 和 runtime 并列夹在模型与 OS 中间”,而是:
- harness 是更外层的控制系统;
- runtime 往往是 harness 里的执行子系统。
在 Codex 的开源实现里,这个边界是能看到的:
exec_policy一类模块偏向 policy / approval / orchestration;tools/sandboxing这类模块承担工具运行编排;exec.rs把执行请求构造成真正可跑的对象;seatbelt.rs、landlock.rs、Windows sandbox 后端则更接近具体 runtime backend;spawn.rs负责最终的子进程启动。
因此,一个更贴切的说法是:
Harness 是管“过程”的,runtime 是管“落地执行”的。
Sandboxing, Approvals, and Trust Boundaries
理解 Codex 时,最容易混淆的另一个点,是把 sandbox 和 approval 当成一回事。实际上它们是两层不同的控制。
可以这样记:
- sandbox:技术边界,决定“做不做得到”
- approval policy:交互边界,决定“越界前要不要先问人”
这两层结合起来,才构成 Codex 的真实信任边界。
Sandbox
沙盒的作用是限制 agent 能碰到什么。
本地 CLI / IDE 场景下,OpenAI 官方文档明确说明 Codex 使用的是 OS-level sandboxing:
- macOS:Seatbelt,底层通过
sandbox-exec - Linux:默认是 bubblewrap +
seccomp - Windows:WSL 下沿用 Linux 语义,原生 Windows 则走单独实现
在默认模式下,Codex 一般具有这样的边界:
- 只能在当前 workspace 内读写;
.git、.codex、.agents这类路径可以被进一步保护;- 网络默认关闭;
- 通过工具启动的命令同样继承沙盒,而不是只有“内建文件编辑”才受限制。
官方文档里常见的几种模式是:
read-onlyworkspace-writedanger-full-access
这些模式回答的都是同一个问题:agent 技术上能碰到哪些文件和哪些系统能力。
Approval Policy
审批层关心的不是“能不能做到”,而是“遇到越界或高风险动作时,要不要停下来问用户”。
例如:
- 访问网络;
- 写工作区之外的目录;
- 执行不在允许规则内的命令;
- 执行明显具有破坏性的操作。
常见审批模式包括:
untrustedon-requeston-failurenever
所以,一个动作可能在技术上可执行,但策略上仍要求先审批;反过来,一个动作即使用户愿意批准,如果底层沙盒根本不允许,也不能直接执行。
Local vs Cloud
这里顺便补上本地与云端的区别,因为这和 sandbox 的实现方式直接相关。
在本地模式下:
- 模型推理仍在云上;
- 但命令执行和文件修改发生在你的机器上;
- 沙盒依赖你的操作系统机制来约束本地进程。
在云端模式下:
- agent 跑在 OpenAI 管理的隔离容器里;
- 官方文档采用两阶段模型:
setup阶段可装依赖,agent阶段默认离线; - secrets 只在 setup 阶段可用,进入 agent 阶段前会被移除。
这说明“本地 / 云端”的差异,不只是文件放在哪,而是整个执行边界和安全模型都不同。
End-to-End Lifecycle: From Query to Response
把前面的概念串起来,Codex 的一次完整生命周期可以画成这样:
|
|
这张图里最关键的点有两个。
第一,模型并不直接操作操作系统。模型只能生成“下一步动作意图”,真正把它落成系统调用的是 harness 和 runtime。
第二,工具调用不是一次性的插曲,而是 agent loop 的一部分。工具结果会重新进入上下文,继续驱动模型的下一轮决策。
因此,Codex 不是“模型 + 插件”的松耦合结构,而是一个把观察、动作、验证和回复连接起来的闭环系统。
Long-running Commands and Streaming
Codex 的长命令体验之所以看起来“像有人在后台盯着终端看”,就是因为这里存在两条并行通道。
第一条通道是 原始进程输出流。
命令启动后,runtime 会持续读取 stdout / stderr,并把新增内容流式推给前端或宿主程序。这部分并不一定要求模型重新推理,所以你看到的很多实时日志,其实只是进程本身在打印。
第二条通道是 工具结果驱动的新推理。
典型流程通常像这样:
- 启动命令;
- 等一个
yield_time_ms; - 收集当前输出;
- 把这部分输出作为 tool result 返回;
- 如果进程还在运行,则保留
session_id; - 后续再用
write_stdin(session_id, chars="")轮询新输出。
因此更准确的理解方式是:
|
|
所以看起来像“边跑边汇报”,本质上是三件事叠加:
- runtime 负责维持进程和流式输出;
- tool result 负责把阶段性观察送回模型;
- 模型负责把这些观察翻译成更易读的自然语言或下一步行动。
Multi-agent as a Tree of Threads
再往上看 multi-agent。
Codex 的 multi-agent 更像一棵线程树,而不是多个 agent 共用一份上下文的共享池。
通常会有:
- 一个 root agent;
- 若干 child agent;
- 每个 child agent 都有自己的消息历史、任务输入、工具状态和执行循环。
因此默认情况下,子 agent 并不会天然共享父 agent 的完整上下文。常见的信息传递方式有三种:
-
spawn_agent(..., fork_context = true)
显式复制父线程上下文; -
send_input/assign_task
给目标 agent 发送结构化任务; -
wait_agent/list_agents
查看状态并决定何时整合结果。
从架构上说,multi-agent 并没有改变 harness / runtime 的基本关系。它只是把“单个 agent loop”扩展成了“多个相互隔离、但可由上层协调的 agent loop”。
这意味着 multi-agent 的核心不是“共享脑子”,而是:
- 上下文默认隔离;
- 需要时再显式复制或显式传递;
- 上层 harness 负责协调并汇总结果。
The Architecture in One Picture
如果把 Codex 的主要模块放到一张图里,可以得到这样一个更稳定的架构视图:
|
|
这张图里有几个关键判断:
Model
模型负责推理,但不直接触碰操作系统。它的输出是“意图”,不是最终系统调用。
Harness
harness 是总调度台。它关心上下文怎么组织、工具怎么暴露、审批怎么插入、任务何时结束。
Runtime
runtime 是执行引擎。它关心工具请求怎样变成真实命令、如何拿到输出、如何处理长进程和超时。
Sandbox
sandbox 是技术边界。它不是“建议模型克制一点”,而是底层真正限制命令能做什么。
Approval
approval 是人机协作边界。它决定哪些事情必须停下来问用户,而不是自动继续。
OS / Container
OS 或云容器才是真正执行系统调用的地方。文件到底被谁改了、进程到底在哪里被 spawn,发生在这一层。
因此,把这些模块串起来后,一个常见误解就可以被纠正:
Codex 不是模型直接“会用电脑”,而是模型在 harness 的调度下,通过 runtime 和 sandbox 受限地使用执行环境。
A Practical Mental Model
如果要把整篇文章压缩成一个简化心智模型,我觉得最有用的是下面这组对应关系:
- 模型:负责想下一步做什么;
- tool spec:告诉模型有哪些动作可以选;
- harness:负责把整个任务过程组织起来;
- runtime:负责把动作真正执行起来;
- sandbox:负责限制它能碰什么;
- approval:负责决定何时必须先问用户;
- OS / cloud env:负责真正执行命令和文件操作。
换成一句更口语的话:
LLM 负责下工单,harness 负责调度流程,runtime 负责施工,sandbox 和 approvals 负责围栏,OS 或容器才是真正动手干活的地方。
Final Notes
理解 Codex 的关键,不是记住几个术语,而是分清不同层的职责边界。
很多表面上看像“模型能力”的东西,其实属于模型外部系统:
- 可不可以本地改文件;
- 长命令为什么能流式展示;
- 为什么有时候会被要求审批;
- 为什么子 agent 不自动共享全部上下文;
- 为什么本地和云端的安全模型不同。
把这些边界理清之后,Codex 就不会再像一个神秘的“会写代码的黑盒”。它更像一套分层明确的 agent architecture:
- 上层是指令和目标;
- 中层是 harness 编排和模型决策;
- 下层是 runtime 执行与沙盒限制;
- 最底层才是真实的操作系统或云容器环境。
也正因为如此,Codex 的很多产品体验,其实不只是模型问题,而是 harness engineering 问题。模型决定上限,harness 和 runtime 决定它能不能稳定、可控、可恢复地把事情做完。
References
[1] OpenAI Developers, Sandboxing, accessed March 28, 2026.
[2] OpenAI Developers, Agent approvals & security, accessed March 28, 2026.
[3] OpenAI Developers, Agent internet access, accessed March 28, 2026.
[4] OpenAI, Introducing the Codex app, accessed March 28, 2026.
[5] OpenAI Cookbook, GPT-5-Codex Prompting Guide, accessed March 28, 2026.
[6] OpenAI Codex GitHub repository, openai/codex, accessed March 28, 2026.
[7] OpenAI Codex source, codex-rs/core/src/exec.rs, accessed March 28, 2026.
[8] OpenAI Codex source, codex-rs/core/src/seatbelt.rs, accessed March 28, 2026.
[9] OpenAI Codex source, codex-rs/core/src/landlock.rs, accessed March 28, 2026.
[10] OpenAI Codex source, codex-rs/core/src/spawn.rs, accessed March 28, 2026.
[11] OpenAI Codex source, codex-rs/core/src/tools/sandboxing.rs, accessed March 28, 2026.
[12] OpenAI Codex source, codex-rs/execpolicy, accessed March 28, 2026.