上个月我们团队换了一次 agent loop。从 Claude Code 切到 OpenCode。
切换本身很轻——prompt 改改,工作流调调,两天上手。但切完第三天,周一早上打开 dashboard,CI 全绿。我松了口气。然后随手点开一条 PR 的 review 记录——空的。再点开一条——还是空的。
不是代码质量出了问题。是 pipeline 里有一条规则:检测注释里的 // Generated by Claude Code 标记,命中就触发额外的 AI 代码 review 流程。OpenCode 不打这个标记。于是这条规则永远不触发,review 流程形同虚设。CI 是绿的,但绿得没有意义。
一条规则,把整个团队锁死在一个工具上。不是因为我们选定了 Claude Code,是因为我们的基础设施离不开它。
我在 代码是 AI 写的了,品味住在哪里 里说,品味从代码搬到了 harness——CI pipeline、release 节奏、事故响应。但那篇文章没有回答一个紧接着的问题: harness 本身,应该跟 agent loop 是什么关系?
答案是:好的 harness 不挑笔。
生成侧和验收侧
先把两个概念分开。
Agent loop 是生成侧。 它负责把意图变成代码。Cursor、Claude Code、Codex、Copilot、Windsurf——都是生成侧的不同实现。它们的输出有风格差异:Cursor 爱加注释,Claude Code 偏好长函数,Codex 喜欢拆小文件。但这些是 生成策略,不是质量标准。
Harness 是验收侧。 它负责判定代码能不能进入系统。lint、type check、test suite、release gate、postmortem 模板——都是验收侧的组件。它们定义的是「什么算合格」,不是「怎么生成」。
生成侧(可换) 验收侧(稳定)
───────────── ─────────────
Cursor lint rules
Claude Code type check
Codex test suite
Copilot release gate
人(极端情况) postmortem 模板
# generated by hugo AI
这两侧的关系是 契约关系:不管你用什么工具、什么模型、什么 prompt 策略,出来的东西必须过同一套关。
类比:造纸厂定义纸的规格——克重、白度、吸墨性。它不关心你用什么笔写。钢笔、圆珠笔、毛笔,写上去不洇不透就是合格。如果一种纸只能配一种笔,那不是纸好,是纸窄。
挑 agent loop 的 harness 长什么样
反面比正面更有教学意义。三种常见的耦合:
一、检查来源,不检查质量。
「我们加了一条规则,检测 AI 生成的注释风格。如果是 AI 写的,触发额外 review。」
这条规则的隐含假设是:AI 写的代码比人写的更需要审查。但真正需要审查的不是「AI 写的」,是「质量不够的」。一段人写的烂代码和一段 AI 写的烂代码,对系统的伤害是一样的。你按来源分流,等于放过了人写的烂代码,同时给 AI 写的合格代码加了不必要的摩擦。
正确做法:检查质量标准本身。覆盖率低于阈值就拦,不管谁写的。
二、把验收标准塞进生成侧。
「我们的 prompt template 里规定了代码风格,所以 CI 里不再检查格式。」
这更危险。你把验收标准从 harness 挪到了 prompt 里。prompt 是生成侧的配置——换一个 agent loop,prompt 就变了,验收标准就丢了。你以为 CI 是绿的,其实是因为没有人在检查。
正确做法:验收标准永远在验收侧。prompt 里可以写风格偏好(提高一次通过率),但 CI 里必须有独立的格式检查(兜底)。
三、测试适配工具的输出结构。
「这个集成测试只在 Claude Code 生成的代码上跑,因为 Cursor 生成的目录结构不一样,测试路径对不上。」
这是最隐蔽的耦合。你的测试在适配工具的输出特征,而不是验证系统行为。工具一换,测试就废。或者更糟——测试还在跑,但测的不是你以为的东西。
正确做法:测试验证行为,不验证结构。「调用这个 API 返回 200」是行为测试。「src/controllers/user.ts 文件存在」是结构测试。前者不挑工具,后者挑。
不挑笔的 harness 怎么搭
正面说。四条原则:
一、检查质量标准,不检查生成来源。
lint 规则不关心代码是人写的还是 AI 写的。type check 不关心类型标注是手打的还是模型补的。测试不关心实现是 Copilot 补全的还是你手敲的。
如果你的 harness 里有任何一条规则需要知道「这段代码是怎么来的」才能决定怎么检查,把它改成「这段代码是否满足质量标准」。
二、验收标准独立于生成配置。
Prompt 里写的规则是 建议——提高一次通过率,减少返工。CI 里写的规则是 法律——不管你怎么生成的,过不了就不能合。
两者可以重叠(prompt 里说「用 4 空格缩进」,CI 也检查缩进),但不能只有前者没有后者。建议可以换,法律不能换。
三、测试验证行为,不验证结构。
✅ 行为测试(不挑笔):
POST /api/orders → 201, body 包含 order_id
输入非法金额 → 400, error message 包含 "amount"
❌ 结构测试(挑笔):
src/services/order_service.py 存在
类名是 OrderService
方法签名是 def create_order(self, data: dict)
# generated by hugo AI
结构是生成侧的选择。不同 agent loop 会给出不同的结构——有的拆三个文件,有的合一个文件,有的用 class,有的用函数。只要行为对,结构不该是验收标准。
四、harness 的演进由事故驱动,不由工具驱动。
在 代码是 AI 写的了,品味住在哪里 里我说过:有品味的工程师,每次事故都让 harness 变厚一层。
这里补一条:harness 变厚的方向应该是「堵住质量漏洞」,不是「适配新工具」。
✅ 事故驱动(稳定):
上次因为没检查空指针,线上崩了 → 加 null check lint rule
上次因为没跑集成测试,API 契约破了 → 加 contract test
❌ 工具驱动(脆弱):
换了 Claude Code,它生成的代码喜欢用 any → 加 no-any 规则
换了 Cursor,它爱生成 utils.ts → 加文件数量检查
# generated by hugo AI
第一种规则,不管用什么工具都有效。第二种规则,工具一换就过时。
和信任架构的同构
这个设计原则和 Agent 时代的权限:从 RBAC 到五层信任架构 是同构的。
五层信任架构里,Agent Proxy 不关心 Agent 内部怎么推理。它只校验:你是谁(身份)、你能做什么(权限)、你替谁做(委托)、你怎么证明(凭证)。Agent 的推理过程是黑盒,Proxy 不介入。
Harness 对 agent loop 的关系一模一样:
| 信任架构 | Harness |
|---|---|
| Agent Proxy 不关心 Agent 怎么推理 | Harness 不关心代码怎么生成 |
| 校验身份、权限、凭证 | 校验质量、行为、演进 |
| Agent 被劫持了,Proxy 兜住 | Agent loop 输出垃圾了,Harness 拦住 |
| 凭证不进入 Agent 运行环境 | 验收标准不进入生成配置 |
两侧解耦的核心收益是:任何一侧出问题,另一侧兜得住。
Agent 被 prompt injection 劫持了,Proxy 的短期凭证机制限制损害半径。Agent loop 生成了垃圾代码,Harness 的质量门禁拦住它进入主干。你不需要信任生成侧,因为验收侧是独立的。
反过来,如果两侧耦合了——验收标准写在 prompt 里、测试适配工具的输出结构、检查规则按来源分流——那生成侧一出问题,验收侧同时失效。两道防线变成一道,而且是你看不见的那道。
一个思想实验
假设明天所有 agent loop 都消失了。AI 不写代码了,所有人回到手敲。
你的 harness 还能用吗?
如果答案是「能」——lint 还在跑,测试还在过,release 节奏不变,postmortem 模板不变——说明你的 harness 是工具无关的。它检查的是工程质量,不是工具特征。
如果答案是「不能」——有些规则失效了,有些测试跑不了了,有些流程断了——说明你的 harness 里混入了工具适配逻辑。那些逻辑在工具消失的瞬间就变成了死代码。
这个思想实验的价值不在于「AI 真的会消失」,而在于它帮你 分离关注点:哪些规则是质量底线(永远需要),哪些规则是工具适配(工具换了就该删)。
最后
回到开头那次工具切换。
那条检测 // Generated by Claude Code 的规则,我当天就删了。换成了一条不挑笔的规则:所有新增代码必须有对应的测试覆盖,覆盖率低于 80% 的 PR 不能合。不管代码是 Claude Code 写的、OpenCode 写的、还是实习生手敲的,标准一样。
切换工具的成本从「改 CI + 改测试 + 改流程」变成了「改 prompt」。两天搞定。
Agent loop 是笔,harness 是纸的规格。好的纸不挑笔。
你的 CI pipeline 里,有没有一条规则是只有当前工具在的时候才成立的?如果有,它不是质量底线,是工具依赖。趁还没换工具,把它改成不挑笔的版本。
你在团队里换过 AI 编码工具吗?harness 跟着改了多少?欢迎留言讨论。