拆开 Codex Harness:模型之外,Agent 如何把活干完
原创 · 约 35 分钟阅读 · 阅读 --

拆开 Codex Harness:模型之外,Agent 如何把活干完

作者: Alex Xiang


古董级程序员,从大厂到创业公司,现在还在一线做 AI 相关开发。微信公众号「字与码」会继续更新工程实践、新技术判断,以及这些年踩过的坑。文章若对你有用,欢迎顺手关注。

最近「Harness」突然成了 Agent 领域的高频词。OpenAI 讲 Harness Engineering,DeepSeek 直接开源 DeepSeek Harness;社区里又出现各种 Codex Harness、Ralph Harness 和观察工具。名字堆在一起,很容易让人误以为:Codex Harness 是 OpenAI 新发布的另一个产品,或者它只是给 Codex 模型套了一层提示词。

两种理解都不准确。

OpenAI 对它的定义很直接:Codex Harness 是所有 Codex 体验底下的核心 Agent Loop 与执行逻辑。Codex CLI 把这层开源地呈现出来;Codex App、Cloud、VS Code 扩展则是在相同能力之上形成的不同产品入口。模型负责生成下一步,Harness 负责把下一步放进真实环境里,处理工具、权限、状态、失败、恢复和验证。

这一区分很重要。模型 benchmark 回答「在给定输入下,它能不能想出正确动作」;Harness 要回答的是「连续几百次动作之后,系统还能不能安全、可追溯地把任务交付」。前者像发动机台架测试,后者才是整车上路。

Codex Harness 将上下文、工具、权限、状态和验证组成闭环

先把三个 Codex 分开

今天讨论 Codex,至少有三层含义:

层次它是什么负责什么
Codex 模型面向软件工程优化的推理模型理解代码、规划动作、生成文本或工具调用
Codex HarnessAgent 运行时与执行控制层上下文、循环、工具、权限、沙箱、状态、压缩、恢复、观测
Codex 产品CLI、App、Cloud、VS Code 等入口交互、任务管理、远程环境和团队工作流

这三层不是完全松耦合的。模型训练会适配工具协议和上下文形态,Harness 也会针对模型的行为调整提示词、截断和重试策略。但它们仍然是不同工程对象:同一个模型放进不同 Harness,结果可能明显不同;同一套 Harness 换模型,也不会自动获得相同的可靠性。

OpenAI 在 2026 年 1 月发布的 Unrolling the Codex agent loop 里明确说,Harness 负责协调用户、模型和工具。这个定义比「AI 编程客户端」更接近源码。

run_turn 看 Codex Harness 的骨架

Codex CLI 的核心实现位于 Rust 工作区。当前源码中,codex-rs/core/src/session/turn.rsrun_turn 用一段很朴素的注释描述整个循环:模型要么返回函数调用,要么返回 assistant 消息;若是工具调用,执行后把结果送入下一次采样;若只剩 assistant 消息,这一轮结束。

简化以后,骨架大致是:

loop {
    let response = sample(model, prompt, tools).await?;

    if let Some(call) = ToolRouter::build_tool_call(response)? {
        let result = dispatch(call).await?;
        history.record(result);
        continue;
    }

    history.record(response);
    break;
}

真正的工程量都藏在这段伪代码省略的地方:采样前是否需要压缩,上下文怎样按本轮世界状态更新,工具 schema 怎样暴露,多个工具能否并行,调用是否需要批准,进程在哪个沙箱里执行,输出怎样截断,失败后是否升级权限重试,事件如何持久化,以及取消信号怎样一路传到底层。

所以,Agent Loop 的难点不是 while,而是循环中每一个边界都必须有确定语义。

1. 上下文不是 messages 数组,而是一份会变化的世界状态

ContextManager 内部确实保存了按时间排列的 ResponseItemEnvelope,但它同时维护:

  • history_version:压缩或回滚导致历史改写时递增;
  • reference_context_item:下一轮生成配置差异的基线;
  • world_state_baseline:最近一次写入模型历史的世界状态快照;
  • token_info:当前上下文使用情况。

关键点是 update_world_state():它并不每轮把所有环境信息重新塞给模型,而是拿当前快照与基线做差,生成本轮需要追加的上下文片段。工作目录、权限、模型、插件、AGENTS.md 等状态发生变化时,Harness 才把变化显式注入。

这是一种很实用的控制面设计:仓库和环境在任务过程中会变,Prompt 也必须知道自己建立在哪个版本的现实上。 如果只在会话开头读一次说明,后面切分支、改权限或启用工具,模型看到的就可能是旧世界。

源码位置:ContextManager 与 world state diff

2. 工具先注册成能力,再被路由成执行

ToolRouter 持有两样东西:内部 ToolRegistry,以及模型可见的 ToolSpec 列表。收到模型响应后,build_tool_call() 将普通函数调用、自定义工具调用和客户端执行的工具搜索统一转成 ToolCall。真正执行时,再从 Registry 找到对应 runtime。

这个拆分解决了两个经常被混为一谈的问题:

  1. 模型知道哪些工具。 这是 schema 暴露与上下文预算问题。
  2. 系统实际允许哪些工具。 这是注册、权限和运行时策略问题。

不是每个已安装能力都必须占用模型上下文。Codex 代码里已经出现 deferred namespace、tool search 和不同 exposure 形态,这意味着工具系统正在从「启动时把所有 schema 塞进去」转向按需发现。

源码位置:ToolRouter

3. 审批与沙箱不是两个开关,而是一条状态机

ToolOrchestrator 顶部的模块注释,几乎可以当成 Codex 安全执行链的摘要:

approval → select sandbox → attempt
         → retry with escalated sandbox strategy on denial

它先根据 permission profile 和 approval policy 得出 ExecApprovalRequirement:跳过、需要批准,或明确禁止。需要批准时,决策可以交给用户,也可以按配置路由到自动 reviewer;批准结果可按规范化后的命令、工作目录、TTY 和权限范围缓存。之后才选择沙箱并执行。若受限环境拒绝了本可执行的操作,系统可以在策略允许时请求升级,再重试,而不是一上来就拿最高权限运行。

这里最值得借鉴的不是枚举名字,而是顺序:先决定能不能做,再决定在哪里做,执行失败后也只能沿着显式策略升级。 审批不能代替隔离,隔离也不能代替审批。

源码位置:ToolOrchestratorapproval routingsandbox policy

4. 压缩不是删聊天记录,而是建立检查点

长任务迟早会碰到上下文上限。compact.rs 中的设计比「把前半段总结一下」复杂得多:

  • 压缩前后都有 hooks;
  • 自动压缩与手动压缩分开记录触发原因和阶段;
  • 压缩产生新的 checkpoint metadata;
  • mid-turn 压缩会把初始上下文放回最后一条真实用户消息之前;
  • pre-turn 压缩则清空 reference baseline,让下一轮完整重注入环境状态。

这段实现揭示了一个容易忽略的问题:历史被总结以后,权限、环境与项目规则不能跟着丢。摘要保存的是任务进展,世界状态保存的是当前约束,两者不是同一种记忆。

源码位置:Compaction implementation

OpenAI 所说的 Harness Engineering,比 Codex CLI 更大

只看 CLI 源码,还不能解释 OpenAI 那篇 Harness Engineering 文章为什么引发这么大反响。文章讲的是一个更大的实验:三名工程师从空仓库开始,五个月内由 Codex 生成约一百万行代码、合并约 1500 个 PR,产品有内部日常用户和外部 Alpha 用户;应用代码、测试、CI、文档、可观测性和内部工具都由 Codex 写成。

它的关键并不是「模型一次写了一百万行」,而是团队逐步把环境改造成 Agent 能工作的样子:

  • AGENTS.md 只做地图,详细知识进入版本化的 docs/
  • UI、DOM、截图、日志、指标和 trace 都变成 Agent 可查询的反馈;
  • 每个 worktree 启动独立应用与可观测环境;
  • 架构依赖方向、文件大小、日志规范等被写成 lint 和结构测试;
  • 复杂任务用可提交的 execution plan 保存决策与进度;
  • 技术债通过周期性后台任务持续「垃圾回收」。

这说明 Harness 不只存在于 Codex 二进制里。仓库结构、CI、可观测性、文档和团队审批制度,也都是 Harness 的一部分。 运行时提供通用闭环,项目自身则提供领域闭环。

我更愿意把 Harness Engineering 定义成:把组织原本依赖经验、口头沟通和人工盯守的工程制度,改造成 Agent 可读取、可执行、可验证的系统。

DeepSeek Harness:不是复制 Codex,而是换了一种控制层哲学

DeepSeek Harness(dsh)是一个明确独立发布的开源项目,目前仍标注 Developer Preview。它和 Codex Harness 最大的差别,不在于界面是 Web 还是终端,而在于对「可替换性」的态度。

Codex Harness 与 DeepSeek Harness 的集成式和插件式路线

DeepSeek 的口号是 Everything is a Plugin。模型、工具、技能、会话、沙箱、存储、Agent Loop、调度和 UI 都可以由 Cordis 插件提供;Cordis 内核主要处理加载、卸载和依赖关系。Profile 再通过 bundle 和 cordis.patch.yml 把一组插件组合成 Web、headless 或自定义运行形态。

源码能验证这不是一句营销话:

  • ReactLoopAgent 是默认循环的一个实现,它通过 Context 获得 session、LLM、system prompt 和 tool 服务;
  • profile.ts 按 bundle 顺序叠加 patch,最后再叠加用户与启动器层;
  • tool-calls.ts 会把独占工具变成 barrier,把并行工具放进有上限的滚动池;
  • 并行调用可以同时 dispatch,但结果仍按模型原始顺序提交,避免并发完成顺序污染会话;
  • session 以追加事件作为事实来源,turn/start、assistant message、tool call 和 result 都可回放;
  • compaction 只有在工具调用与结果配对平衡的位置切割,防止压缩出「记得调用、不见结果」的历史。

源码位置:ReactLoopAgenttool call schedulerProfile compositioncompaction tool pairing

两条路线,不能压缩成「封闭 vs 开放」

简单说 Codex 封闭、DeepSeek 开放,也不准确。Codex CLI 本身是 Apache 许可的开源项目,已经提供 AGENTS.md、Skills、MCP、插件、hooks、app-server 和多 Agent;DeepSeek Harness 虽然插件边界更彻底,默认发行版仍然需要为插件选择实现、版本和权限。

更准确的比较是:

维度Codex HarnessDeepSeek Harness
首要目标把软件工程执行链收敛成稳定体验把 Agent 运行时拆成可组合能力
核心形态集成式 Rust runtimeCordis 微内核 + TypeScript 插件树
Agent Loop核心执行路径,扩展点围绕它组织默认 Loop 本身也是可替换插件
状态thread/session、rollout、world state diff追加式 session log、surface、projection
工具Registry、Router、Orchestrator 分层Registry 与执行流水线均可由插件参与
并发语义工具声明是否支持并行,由 runtime 调度bounded pool 并行 dispatch,按模型顺序提交
安全策略审批、permission profile、沙箱与升级重试深度集成沙箱、审批、权限 preset 是可组合插件
定制成本常用路径开箱即用,深层替换成本较高替换空间大,同时承担插件治理成本
当前成熟度已有 OpenAI 内部真实产品长期使用证据开发者预览,仍明确会破坏兼容性

我的判断是:

Codex 像一套经过强意见打磨的 Agent 操作系统发行版;DeepSeek Harness 更像允许替换关键子系统的 Agent 运行时开发平台。

前者优先减少使用者必须做的决定,后者优先增加开发者可以做的决定。它们都合理,但服务的团队阶段不同。

已经有人在用吗?有,但证据强度不一样

Codex:有真实产品闭环,不只是 benchmark

OpenAI 的 Harness Engineering 实践 是目前最强的一手证据:产品已经有数百名内部用户,单次 Codex 运行常超过六小时,代码会真实部署、出错、修复并继续演进。

社区也开始围绕 Codex CLI 再加一层外部 Harness。例如 Ralph Harness 讨论 把短循环、仓库内规格、时间上限、git hook、CI 与覆盖率门禁包在 Codex CLI 外面。这不代表它已经大规模生产采用,但说明「运行时之外还需要项目控制层」已经被开发者转化成工具。

DeepSeek Harness:已经有人跑、有人写插件,也已经有人踩坑

DeepSeek 官方社区里已经能看到主题、桌面封装、成本面板、OpenTelemetry、飞书接入和 Pi 生态桥接等插件;这些代码与安装说明,比不断变化的 Star 数更能证明有人在实际试用。官方的 社区欢迎帖 汇总了多种扩展。

另一面同样真实:开发者已经报告子 Agent 卡住、会话恢复失败、服务停止后 UI 仍显示运行中,以及不同 Windows/Node 环境问题。比如 多个子 Agent 卡住的讨论后台停止后状态不收敛。这些不是「项目不行」的证据,而是它已经从 README 进入真实运行边界的证据。

因此更准确的结论是:Codex 有成熟产品与内部生产闭环的公开证据;DeepSeek Harness 已经形成活跃的早期使用与插件生态,但还不能把热度等同于生产成熟度。

业界评论真正关心的,已经从模型转向运行时

一条很有代表性的 Codex issue 标题就是:What Codex Is Missing: It’s the Harness, Not the Model。作者同时使用 Codex 与 Claude Code,主观感受是模型能力已经接近,日常差异更多来自任务完成可信度、中断程度和工作流连贯性。

这只是一个用户观点,不是 benchmark,但它点中了 Harness 的价值:用户最终感知的不是单步推理分数,而是「我离开一小时以后,回来看到的是可审查结果,还是一条卡死的任务」。

公开问题也说明,Harness 自身会制造新的工程故障。Codex 的一个 长时间 /goal issue 报告了单日 34 GB 日志、巨大单行 trace 和异常 token 计数。无论具体版本如何修复,这类案例都提醒我们:长任务把日志、追踪、状态、取消和计费放进同一个放大器里。循环跑得越久,「可观测」越可能反过来成为资源风险。

独立研究也在尝试量化 Harness 的影响。Agentic Harness Engineering 报告,通过迭代工具、中间件和长期记忆,其 Terminal-Bench 2 的 pass@1 从 69.7% 提升到 77.0%,高于论文实验中的 Codex CLI 71.9%。这不是 OpenAI 或 DeepSeek 的官方结论,也不能直接外推到所有任务,但至少说明:不改模型权重,只改外围执行系统,也可能显著改变任务成功率。

我的观点:Harness 不是 Agent 的外壳,而是可执行的组织制度

把 Harness 比作「马具」或者「操作系统」都有帮助,但还差一层。

真正让 Agent 在团队里持续工作的,是一套过去由人默默承担的制度:新人去哪里找设计依据,危险操作找谁批准,代码怎样证明没破坏功能,线上故障怎样复现,失败后怎样恢复,什么时候应该停止并升级给人。Harness 的任务,是把这些制度从人的默契变成机器能读、能执行、能留下证据的接口。

这也是为什么我不认为「Everything is a Plugin」天然比集成式设计先进。插件化提高的是变化自由度,同时增加版本、权限、供应链和状态组合的可能性。对一个仍在寻找产品形态的 Agent 平台,这种自由很有价值;对追求稳定交付的团队,过多可替换点可能只是把运行时维护工作转嫁给自己。

反过来,Codex 的集成式设计也不是终点。紧密协同能带来更好的默认体验,却可能让深层策略、模型路由和状态语义更难替换。第三方在 Codex CLI 外继续套 Harness,恰好说明任何通用运行时都无法完整替代项目自己的验收、架构和治理层。

我会用下面这个乘法,而不是工具数量,评价一套 Harness:

Harness 质量
= 上下文有效性
× 工具执行可靠性
× 权限与隔离
× 状态恢复
× 验证闭环
× 可观测性

之所以用乘法,是因为任意一项接近零,长任务都会失去可信度:工具很强但状态不能恢复,跑六小时也可能白跑;上下文很全但没有机械验证,最终只能相信 Agent 自己说「已经完成」;插件很多但权限边界含糊,扩展性会直接变成攻击面。

现在该怎么选

如果你只是要稳定完成日常软件工程任务,Codex 的集成式 Harness 更像一套完成度较高的默认答案。先把 AGENTS.md、测试、权限和可观测环境配置好,比先研究怎样替换 Agent Loop 更有收益。

如果你在做 Agent 平台、模型评测、定制工作流,或者明确需要替换存储、Loop、UI 和工具治理,DeepSeek Harness 更值得做源码级试验。但它仍在 Developer Preview,合理姿势是锁版本、用无敏感数据的小仓库验证、记录 session 与工具轨迹,并准备回滚,而不是把「可插件化」直接翻译成「可生产」。

如果你正在自研 Harness,不要先画一张塞满组件的架构图。先挑十到二十个真实长任务,记录首次通过率、人工接管次数、恢复成功率、危险动作拦截率、验证证据完整度、总 token 与墙钟时间。能让这些指标持续改善的模块才有价值。

模型决定 Agent 能想到多好的下一步,Harness 决定这些下一步能否积累成可靠结果。未来模型会继续变强,但只要 Agent 还要接触文件、进程、网络、凭据和真实用户,Harness 就不会消失;它只会从一个不起眼的外壳,变成软件工程新的控制平面。

参考资料

打开原图 ↗