Overview

这篇文章想系统回答一个问题:Codex 到底是怎么工作的

很多人第一次接触 Codex 时,都会有一种很强的“违和感”:

  • 它不只是聊天,而是真的会读代码、改文件、跑命令;
  • 它不是每次都等命令跑完才说话,而是会一边看输出一边继续推进任务;
  • 它看上去像一个模型,但很多关键行为其实并不发生在模型内部;
  • 它既能在本地执行,也能在云端环境里跑,而且这两种模式的安全边界还不完全一样。

如果只把 Codex 看成“一个会写代码的 LLM”,很多现象会解释不清。更准确的理解方式是:

Codex 是一个由模型负责决策、由 harness 负责编排、由 runtime 负责执行、并由 sandbox 与 approvals 负责边界控制的 agent system。

这篇文章会把这个系统拆开来看。重点不是介绍某个 API 参数,而是建立一个稳定的心智模型:当用户发出一个请求后,究竟发生了什么,哪些职责属于模型,哪些职责属于 harness,哪些职责属于 runtime,沙盒和审批又分别控制什么。

Why Codex Feels Different

Codex 和普通对话模型最大的差别,不在于“更会写代码”,而在于它被放进了一个可执行的闭环里。

普通聊天模型的典型行为是:

  1. 读取上下文;
  2. 生成一段回复;
  3. 结束这一轮。

而 Codex 的典型行为更像:

  1. 读取上下文和工具定义;
  2. 决定下一步动作;
  3. 调用工具;
  4. 观察工具结果;
  5. 根据新观察继续推理;
  6. 重复这个循环,直到任务结束。

因此,Codex 的关键特征不是“回答得更聪明”,而是它能把用户目标拆成一系列可执行动作,并在执行结果的反馈下持续调整后续行为。

这也是为什么理解 Codex 时,只看模型往往不够。很多决定产品体验的关键能力,例如:

  • 能不能真正跑 shell 命令;
  • 命令失败后能不能恢复;
  • 写文件时有没有边界;
  • 什么时候需要用户审批;
  • 长命令的输出怎么流式展示;
  • 多个 agent 怎样协同;

这些都不只属于模型,而属于模型外面的整套执行系统。

Message Roles and Instruction Hierarchy

先看最上层的上下文结构。

过去很多人熟悉的 chat 格式里,角色通常只有:

  • system
  • user
  • assistant

但在现在的 Codex / OpenAI agent 语境里,developer 同样是核心角色。它往往承载的是宿主程序写给模型的工作规则,而不是普通对话内容。

可以粗略理解为:

  • system:平台级规则;
  • developer:应用级规则,也就是 Codex 这个产品要求 agent 如何工作;
  • user:当前任务;
  • assistant:模型之前已经给出的自然语言回复或工具调用结果。

在 Codex 里,developer 往往会规定这类事情:

  • 你是一个 coding agent;
  • 先读代码再改代码;
  • 优先使用哪些工具;
  • 输出分成 commentaryfinal
  • 不要做哪些危险 git 操作;
  • 什么时候要更新用户进度;
  • 什么情况下必须遵守沙盒和审批策略。

所以在架构上,developer 更像一层应用运行规则,而不是普通聊天历史。Codex 之所以表现得像“有工作流程”的 agent,很大程度上就是因为它始终处在一套强约束的指令体系之下。

Tools: Spec vs Implementation

再往下看工具。

模型并不会直接看到工具的源码实现。它首先看到的是一份 tool spec,也就是结构化接口描述。这个 spec 通常会告诉模型:

  • 工具名是什么;
  • 这个工具做什么;
  • 参数有哪些;
  • 参数的类型和约束是什么;
  • 结果大概会返回什么结构。

例如一个执行命令的工具,spec 里可能会包含:

  • name = exec_command
  • description = Runs a command in a PTY
  • parameters.cmd = string
  • parameters.workdir = string
  • parameters.yield_time_ms = number

模型真正会做的,是基于这份 spec 决定:

  1. 现在需不需要调用工具;
  2. 如果需要,应该调用哪个工具;
  3. 参数该怎么填。

所以从抽象上说:

  • tool spec 是暴露给模型看的接口定义;
  • tool implementation 是宿主程序里真正干活的代码。

这和传统软件里的“API 文档”和“后端实现”关系非常像。模型看到的不是实现细节,而是能力边界。

Harness: The Control Plane

接下来进入最容易混淆、但也最重要的一层:harness

如果用一句话定义:

Harness 是包在模型外面、把用户任务组织成持续 agent loop 的控制系统。

它关注的不是“某条命令怎么 spawn”,而是更上层的问题:

  • 这一轮该不该调用工具;
  • 工具调用前要不要审批;
  • 失败后要不要重试;
  • 当前任务是否已经完成;
  • 输出该展示给用户什么;
  • 多 agent 之间如何分工;
  • 哪些规则需要始终保留在上下文里。

因此,harness 更像 control plane。它在意的是任务过程的组织、约束与调度。

在 Codex 语境里,harness 一般会包含这些职责:

  1. Agent loop orchestration
    把“读上下文 -> 选动作 -> 调工具 -> 看结果 -> 再决策”组织成一个可持续运行的闭环。

  2. Instruction layering
    systemdeveloperuser 等不同来源的指令组织成上下文,并维护优先级。

  3. Tool routing
    接住模型发出的 tool call,把它路由给对应的本地或云端实现。

  4. Approval and policy gating
    在真正执行动作之前,先判断是否落在当前权限边界内,是否需要用户批准。

  5. State and session management
    维护会话状态、长进程 session、子 agent 状态、工具调用历史等。

  6. 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.rslandlock.rs、Windows sandbox 后端则更接近具体 runtime backend;
  • spawn.rs 负责最终的子进程启动。

因此,一个更贴切的说法是:

Harness 是管“过程”的,runtime 是管“落地执行”的。

Sandboxing, Approvals, and Trust Boundaries

理解 Codex 时,最容易混淆的另一个点,是把 sandboxapproval 当成一回事。实际上它们是两层不同的控制。

可以这样记:

  • 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-only
  • workspace-write
  • danger-full-access

这些模式回答的都是同一个问题:agent 技术上能碰到哪些文件和哪些系统能力

Approval Policy

审批层关心的不是“能不能做到”,而是“遇到越界或高风险动作时,要不要停下来问用户”。

例如:

  • 访问网络;
  • 写工作区之外的目录;
  • 执行不在允许规则内的命令;
  • 执行明显具有破坏性的操作。

常见审批模式包括:

  • untrusted
  • on-request
  • on-failure
  • never

所以,一个动作可能在技术上可执行,但策略上仍要求先审批;反过来,一个动作即使用户愿意批准,如果底层沙盒根本不允许,也不能直接执行。

Local vs Cloud

这里顺便补上本地与云端的区别,因为这和 sandbox 的实现方式直接相关。

在本地模式下:

  • 模型推理仍在云上;
  • 但命令执行和文件修改发生在你的机器上;
  • 沙盒依赖你的操作系统机制来约束本地进程。

在云端模式下:

  • agent 跑在 OpenAI 管理的隔离容器里;
  • 官方文档采用两阶段模型:setup 阶段可装依赖,agent 阶段默认离线;
  • secrets 只在 setup 阶段可用,进入 agent 阶段前会被移除。

这说明“本地 / 云端”的差异,不只是文件放在哪,而是整个执行边界和安全模型都不同

End-to-End Lifecycle: From Query to Response

把前面的概念串起来,Codex 的一次完整生命周期可以画成这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
User Query
   |
   v
+------------------------------+
| 1. Harness receives request  |
| - session context            |
| - system/developer rules     |
| - tool specs                 |
+------------------------------+
   |
   v
+------------------------------+
| 2. Model inference           |
| - interpret user intent      |
| - choose next action         |
| - emit text or tool call     |
+------------------------------+
   |
   +-------------------------------> If plain response and task is done
   |                                 -> return final answer
   |
   v
+------------------------------+
| 3. Harness validates action  |
| - route tool                 |
| - check policy/rules         |
| - decide approval needed?    |
+------------------------------+
   |
   +-------------------------------> Needs approval
   |                                 -> ask user
   |                                 -> approved / denied
   |
   v
+------------------------------+
| 4. Runtime builds execution  |
| - cwd / env / stdio          |
| - timeout / streaming        |
| - sandbox transform          |
+------------------------------+
   |
   v
+------------------------------+
| 5. Sandbox + OS execution    |
| - spawn child process        |
| - file/network restrictions  |
| - collect stdout/stderr      |
+------------------------------+
   |
   v
+------------------------------+
| 6. Tool result returned      |
| - output chunks              |
| - exit code / errors         |
| - session id for long tasks  |
+------------------------------+
   |
   v
+------------------------------+
| 7. Model sees new evidence   |
| - summarize progress         |
| - decide next tool call      |
| - or conclude task           |
+------------------------------+
   |
   v
Assistant Response

这张图里最关键的点有两个。

第一,模型并不直接操作操作系统。模型只能生成“下一步动作意图”,真正把它落成系统调用的是 harness 和 runtime。

第二,工具调用不是一次性的插曲,而是 agent loop 的一部分。工具结果会重新进入上下文,继续驱动模型的下一轮决策。

因此,Codex 不是“模型 + 插件”的松耦合结构,而是一个把观察、动作、验证和回复连接起来的闭环系统。

Long-running Commands and Streaming

Codex 的长命令体验之所以看起来“像有人在后台盯着终端看”,就是因为这里存在两条并行通道。

第一条通道是 原始进程输出流

命令启动后,runtime 会持续读取 stdout / stderr,并把新增内容流式推给前端或宿主程序。这部分并不一定要求模型重新推理,所以你看到的很多实时日志,其实只是进程本身在打印。

第二条通道是 工具结果驱动的新推理

典型流程通常像这样:

  1. 启动命令;
  2. 等一个 yield_time_ms
  3. 收集当前输出;
  4. 把这部分输出作为 tool result 返回;
  5. 如果进程还在运行,则保留 session_id
  6. 后续再用 write_stdin(session_id, chars="") 轮询新输出。

因此更准确的理解方式是:

1
2
3
4
5
6
启动进程
-> 收到一部分输出
-> 模型读到当前输出并解释进度
-> 再轮询进程
-> 收到更多输出
-> 模型继续解释或决定下一步

所以看起来像“边跑边汇报”,本质上是三件事叠加:

  • runtime 负责维持进程和流式输出;
  • tool result 负责把阶段性观察送回模型;
  • 模型负责把这些观察翻译成更易读的自然语言或下一步行动。

Multi-agent as a Tree of Threads

再往上看 multi-agent。

Codex 的 multi-agent 更像一棵线程树,而不是多个 agent 共用一份上下文的共享池。

通常会有:

  • 一个 root agent;
  • 若干 child agent;
  • 每个 child agent 都有自己的消息历史、任务输入、工具状态和执行循环。

因此默认情况下,子 agent 并不会天然共享父 agent 的完整上下文。常见的信息传递方式有三种:

  1. spawn_agent(..., fork_context = true)
    显式复制父线程上下文;

  2. send_input / assign_task
    给目标 agent 发送结构化任务;

  3. wait_agent / list_agents
    查看状态并决定何时整合结果。

从架构上说,multi-agent 并没有改变 harness / runtime 的基本关系。它只是把“单个 agent loop”扩展成了“多个相互隔离、但可由上层协调的 agent loop”。

这意味着 multi-agent 的核心不是“共享脑子”,而是:

  • 上下文默认隔离;
  • 需要时再显式复制或显式传递;
  • 上层 harness 负责协调并汇总结果。

The Architecture in One Picture

如果把 Codex 的主要模块放到一张图里,可以得到这样一个更稳定的架构视图:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
+------------------------------------------------------------------+
| User / IDE / CLI / App                                           |
| - submit task                                                    |
| - review output                                                  |
| - approve or deny sensitive actions                              |
+------------------------------------------------------------------+
                              |
                              v
+------------------------------------------------------------------+
| Harness (control plane)                                          |
| - maintain session and agent loop                                |
| - assemble system/developer/user context                         |
| - expose tool specs to model                                     |
| - route tool calls                                               |
| - enforce policy / approvals / rules                             |
| - manage subagents, retries, checkpoints, progress updates       |
+------------------------------------------------------------------+
                              |
                              v
+------------------------------------------------------------------+
| Model                                                            |
| - interpret request                                              |
| - reason over context and tool results                           |
| - emit natural language or structured tool calls                 |
+------------------------------------------------------------------+
                              |
                              v
+------------------------------------------------------------------+
| Runtime (execution plane)                                        |
| - turn tool calls into executable requests                       |
| - set cwd / env / stdio / timeout                                |
| - stream stdout / stderr                                         |
| - manage long-running sessions                                   |
| - collect outputs and return structured results                  |
+------------------------------------------------------------------+
                              |
                              v
+------------------------------------------------------------------+
| Sandbox / Approval Boundary                                      |
| - filesystem restrictions                                        |
| - network restrictions                                           |
| - approval gates for sensitive actions                           |
| - platform-specific enforcement                                  |
+------------------------------------------------------------------+
                              |
                              v
+------------------------------------------------------------------+
| OS / Container / Cloud Environment                               |
| - real process spawn                                             |
| - actual file edits                                              |
| - actual network requests                                        |
| - actual command execution                                       |
+------------------------------------------------------------------+

这张图里有几个关键判断:

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.