阅读,与值得关注的内容Readance

Harness 到底是什么:为什么同一个模型,换个 Coding Agent 结果会不一样?

架构师(JiaGouX)
我们都是架构师!
架构未来,你来不来?




前些日子,Tibo 分享了一个挺有意思的玩法:用 CLIProxyAPI,也就是大家常说的 CPA,把 GPT-5.6 Sol 接进 Claude Code。

这件事源于 Theo 的一次对比。同一个 GPT-5.6 Sol,放在 Claude Code 里,他觉得明显比放在 Codex 里更好用,连设计结果都不一样。第二天,Tibo 把接法整理成三步,还给启动命令取了个很形象的名字:claudex。

Tibo 分享通过 CLIProxyAPI 把 GPT-5.6 Sol 接入 Claude Code 的方法
Tibo 分享通过 CLIProxyAPI 把 GPT-5.6 Sol 接入 Claude Code 的方法

Tibo 给出的 claudex 接法,图中内容为平台自动翻译

这只是开发者的个人体验。不过,它带出了一个很有意思的问题:

模型没有变,为什么换一个 Coding Agent,做事的方式和最后的结果都会变?

要解释这个差别,就得看模型外面那套 Harness。

接上同一个模型,不等于得到同一个 Agent

CLIProxyAPI 做的事情,可以粗略理解为协议转换和请求转发。它让 Claude Code 能够调用 GPT-5.6 Sol,但 Claude Code 并没有因此变成 Codex。

模型收到什么系统指令,能看见哪些项目材料,工具怎样描述,子任务怎么分派,命令执行后返回什么,历史过长时怎样压缩,这些仍按 Claude Code 的方式组织和执行。Tibo 给出的 claudex 别名里,除了模型名,还设置了子 Agent 模型、推理开关、工具并发数等参数。换掉模型,只动了整套运行系统中的一部分。

Theo 感受到的差异可能来自很多地方。系统提示词和上下文会影响模型怎样理解任务;工具定义会影响它选择什么动作;循环与反馈会影响它在出错后怎样调整;并发、压缩和子 Agent 策略,又会改变任务能走多远。没有完整的对照实验,我们没法把差异归到某一个参数上。

社区体感之外,还有一组官方实验可以作参照。OpenAI 在一项特定的 ARC-AGI-3 实验中,让 GPT-5.6 Sol 保留推理信息,并调整上下文压缩策略,得分从 13.3% 提升到 38.3%,输出 Token 反而降到原来的六分之一。

这个数字不能直接套到编程任务上,却足以说明一件事:模型权重相同,模型外面的运行方式不同,结果可能差很多。

真要比较两套 Harness,同一任务、同一模型和验收条件要先固定,变化只留在模型外面的运行链里。

同一个模型进入不同 Harness 后,可能走出不同的行动路径
同一个模型进入不同 Harness 后,可能走出不同的行动路径

接通 API 只是第一关,行为是否等价还要重新评测

Harness 到底是什么

Earendil 在《What is a Harness?》里给了一个很朴素的定义:Harness 是一套为 AI 模型提供运行环境的软件。

文章用四个部分解释它:

  • System Prompt
     给模型当前工作的规则和背景;
  • Tools
     让模型能够搜索、读写文件、执行代码或调用外部服务;
  • Agentic Loop
     把模型调用和工具结果串起来,让任务可以一轮轮推进;
  • Translation Layer
     处理不同模型接口、消息和工具调用格式之间的差异。

这四项先把最小结构搭了起来。Agent 一旦进入代码库或业务系统,问题很快就会从“模型能不能调用工具”,变成“谁允许它执行、发生过什么、失败以后怎么接着走”。

如果从架构角度再补一句,我会这样理解:

Harness 既是模型的运行环境,也是模型和真实系统之间的执行边界。模型给出下一步,Harness 负责把这一步变成受约束、有记录、可验证的系统行为。

一项代码任务大致会走过两条方向相反的链路:

Harness 中动作向外、证据向内的两条运行链
Harness 中动作向外、证据向内的两条运行链

前一条链决定能做什么,后一条链决定下一轮知道什么

Harness 的很多工程难题,都出在这两条链的交接处。

模型做判断,运行时管执行

假设我们让 Agent 做一次跨模块重构。模型可以判断先读哪些文件、改什么代码、跑哪组测试。到了真正执行时,Harness 还要处理工作目录、文件权限、命令超时、网络访问、人工审批和进程取消。

放到系统边界里,模型输出的工具调用只是一份动作提议。它通过参数校验和权限检查以后,才会成为真正的系统调用。

这层分工看起来有点保守,却很实用。System Prompt 可以提醒模型不要碰生产数据,但它替代不了权限控制;工具参数有格式约束,也不代表业务参数一定合法;用户批准了一次命令,也不等于子进程已经被隔离。

Pi 的官方安全文档就专门提醒过:Project Trust 决定是否加载项目配置和扩展,并不是沙箱。Pi 及其 TypeScript Extension 默认继承启动用户的权限。遇到不可信仓库或无人值守任务,真正的隔离仍要交给容器、虚拟机、微型虚拟机或远程沙箱。

同样的道理也适用于其他 Harness。一个 Agent 同时能读私有文件、执行代码和访问网络,提示词只能算第一道约束,不能成为最后一道安全边界。

循环不难,难的是反馈怎么回来

Agent Loop 的核心代码往往不长:模型提出动作,系统执行工具,把结果放回上下文,模型再决定下一步。

前面梳理 Loop Engineering 时,我们其实已经碰到过同一个问题。循环本身不难,难的是每一轮结果以什么格式回来,谁判断它有没有用,失败后又从哪里继续。工具只返回一句“执行成功”,和返回退出码、标准输出、错误输出、耗时以及产物位置,下一轮模型能做出的判断完全不同。

还是前面的重构任务。测试命令退出码为 0,只能说明这条命令正常结束,未必说明重构符合需求。Harness 可以保存测试结果和代码差异,真正的完成条件还要来自 CI、验收规则或代码评审。

这也是 Harness 和 Environment(工作环境)容易混在一起的地方。Harness 安排任务怎样运行;Environment 是 Agent 正在操作的真实世界,它保存代码、CI 状态、工单和生产数据,也给出动作之后的反馈。反馈来源不可靠,Loop 跑得再勤快,也只是在更快地追逐噪声。

上下文能整理,发生过的事不能跟着改

任务跑久以后,Harness 还要回答一个问题:模型怎样记住前面做过什么?

最省事的办法,是把所有聊天和工具结果继续塞回上下文。问题是,上下文有长度限制。旧内容会被压缩,长日志会被裁剪,分支任务会重新排列材料。模型下一轮看到的是一份为了当前工作整理过的输入,不是完整的执行账本。

业务系统不会拿页面上的摘要当数据库,Agent 也不适合把上下文当作唯一事实源。

我们拆 Codex 时看到,它用 Thread、Turn、Item 区分会话、一次任务推进和具体事件;DSH 则把 Session 做成只追加的事件流,再从中投影出发给模型的消息。Pi 的 Session 采用树状 JSONL,支持恢复与分支。实现各不相同,解决的是同一个问题:

上下文可以压缩、重排和重建,已经执行过的命令、工具结果和人工审批要有稳定记录。

这条边界会直接影响恢复。一次写操作已经送到外部系统,Harness 却在收到响应前崩了,恢复后不能只因为上下文里没有结果就再做一遍。退款、发消息、创建工单这类动作,需要业务幂等键;结果不明时,先回到权威系统查询,再决定重试还是人工处理。

Harness 不一定要接管业务事务,但它至少要分清“准备执行”“已经发出”“结果未知”和“已经确认”。不然所谓断点续跑,很可能只是把副作用再执行一次。

Translation Layer 解决接入,解决不了等价

回到 claudex,CLIProxyAPI 帮 Claude Code 接通了 GPT-5.6 Sol,这正是 Translation Layer 的价值。不同 Provider 的请求、消息和工具调用格式不一样,中间需要一层翻译。

不过,接口接通和行为等价是两回事。

不同模型对系统消息、工具定义、推理信息、提示词缓存和流式事件的处理并不相同。有些返回字段还要在下一轮原样带回。Pi 作者 Mario Zechner 把跨模型服务商(Provider)的上下文交接称为 best effort,意思是尽力转换,但不能承诺语义无损。

Armin Ronacher 也记录过类似的取舍。他们早期使用统一 SDK,后来发现一套统一接口很难长期抹平模型、Provider 侧工具、缓存控制和消息历史的差异,于是改为直接掌握各家 SDK 和 Agent Loop。

对一套 Harness 来说,模型迁移至少有三道关:API 能调用,任务状态和产物能带走,换完以后质量、成本与安全仍然过线。前两道可以靠适配和自己的数据边界解决,最后一道只能重新评测。

这也解释了 Theo 那次对比:它没有证明哪套 Coding Agent 普遍更强,却提醒我们:把同一个模型接到另一套 Harness,只能保证“能跑”;至于跑出来还是不是同一种行为,要看整个运行环境怎样配合。

架构设计,先把责任线画清楚

Pi、Codex 和 DSH 都可以叫 Harness,内部取舍却很不一样。

Pi 保持很薄的默认核心,把更多能力留给 Extension、Skill 和使用者自己的工作流。Codex 把 Thread、Turn、Item、命令执行、沙箱和审批收进一套执行语义,再通过 CLI、SDK 和 App Server 提供给不同产品。DSH 则用 Cordis 组织可替换的运行图,用 Session 事件流保存已经发生的事。

很难脱离场景说哪一种更先进。一个人在本机盯着 Agent 做短任务,薄一些往往更透明;任务要运行几小时,由多个客户端接管,还会操作生产系统,状态、权限、恢复和审计自然要做厚。

做架构设计时,我通常不会先照着某个项目把模块抄一遍,而会先把几条责任问清楚:

  • 谁拥有业务事实,谁只保存 Agent 的工作记录;
  • 谁批准动作,谁负责最终的权限校验;
  • 中断后从哪里恢复,结果不明时找谁确认;
  • 模型说“完成”以后,哪一份证据才算真正完成;
  • Provider、工具和提示词变化后,拿什么重新评估质量。

边界定下来,具体模块反而比较容易取舍。短任务可能一条小 Loop 加受限工具就够;长任务需要持久状态、取消传播和恢复协议;涉及业务副作用时,还要把幂等、补偿和审计留在合适的系统里。

再回到 claudex

Tibo 用几行配置就把 GPT-5.6 Sol 接进了 Claude Code。模型可以换,API 可以转,但 Agent 最终怎样工作,仍由模型和 Harness 一起决定。

所以,Harness 到底是什么?

它是模型外面的执行系统。模型决定下一步想做什么,Harness 决定这一步能不能做、怎样做,以及做完以后留下什么证据。

模型还会继续变化。如果任务记录、工具契约、运行产物和评测样本留在自己的系统里,底层模型切换时,我们至少还能解释一次任务是怎么完成的,也有依据重新做选择。


参考资料

  • Theo:GPT-5.6 Sol 在 Claude Code 与 Codex 中的个人体验
  • Theo:通过 CLIProxyAPI 连接 Claude Code 与 Codex 认证
  • Tibo:claudex 的三步接法
  • CLIProxyAPI
  • Earendil:What is a Harness?
  • OpenAI:Codex as a platform: build on the open agent harness
  • Pi 官方文档:Security、Sessions
  • Mario Zechner:What I learned building an opinionated and minimal coding agent
  • Armin Ronacher:Agent Design Is Still Hard
  • Anthropic:Effective harnesses for long-running agents

如喜欢本文,请点击右上角,把文章分享到朋友圈
如有想了解学习的技术点,请留言给若飞安排分享

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享

·END·

相关阅读:


      版权申明:内容来源网络,仅供学习研究,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!

      架构师

      我们都是架构师!


      图片

      关注架构师(JiaGouX),添加“星标”

      获取每天技术干货,一起成为牛逼架构师

      技术群请加若飞:1321113940 进架构师群

      投稿、合作、版权等邮箱:[email protected]

       

      前往微信阅读全文

      内容来自公众号,可前往微信查看原文。

      查看作者的更多文章 →