Skip to content

Prompt 告诉 Agent "做什么",Harness 告诉 Agent "做对了没有" — 总结

来源:KM平台文章
作者:binghuiluo
发布时间:2026-03-13
标签:Agent、Coding、AI、Harness


一、引子:一句话与 1.2 亿 token

作者在一次 Agent 协作中,输入了一句 "e2e 测试验证检查",Agent 从上午9点跑到晚上9点,单个 session 消耗约 1.2 亿 token(约等于几百本书的文字量)。

Agent 并非在空转——它在与真实运行环境中的边缘问题搏斗:macOS 内核缓冲区限制导致数据静默丢失、不同版本 Shell 语法行为不一致、用户配置文件中第三方插件冲突、网络分片时序导致信号被拆散……每修好一个,下一个不同的问题又冒出来。

关键洞察:这 12 小时能持续迭代,恰恰是因为 Harness 给出的反馈足够精确、足够多样。产出的不只是功能代码,而是一整套 Harness——从此同类问题再也不需要 12 小时了。


二、核心观点:环境才是 Agent 的天花板

Agent 的效能天花板不在模型,在环境。准确说,在你愿不愿意为构建验证环境付出必要的成本。

大部分 AI Coding 讨论聚焦于 prompt 怎么写、模型怎么选、context window 够不够长,但真正拿 Agent 干过活的人会发现——瓶颈是项目的运行环境

跑通闭环的四个条件

条件说明
模型不蠢当前大模型已能分辨测试失败是 feature 变了还是代码有 bug,这个门槛已过
验证环境接近幂等同样的代码、同样的输入,跑出来的判定必须一致,不能今天绿明天红
验收条件够明确pass 就是 pass,fail 就是 fail,不能是"看起来像对的"
问题够边缘核心逻辑模型写得动,真正难的是运行环境带来的不确定性

四个条件中,后三个全是环境问题,而且互相依赖。


三、运行环境的三个层次

Harness 不是一个东西,是一组分层的环境,每一层消灭一类不确定性:

1️⃣ 隔离层:消灭"在我机器上能跑"

  • 目的:幂等
  • 做法
    • 测试运行在临时目录,不碰用户真实 HOME
    • 环境变量受控(PATH 最小集合,HOME 指向临时目录)
    • 外部依赖容器化(数据库、SSH、消息队列等,测试后销毁)
  • 检验标准:项目 clone 到全新机器,装好运行时和包管理器,npm test 一次通过
  • 对 Agent 的意义:隔离层是 Agent 的"世界观基准"

2️⃣ 进程层:覆盖操作系统的"意见"

  • 目的:处理跨平台、跨版本的操作系统行为差异
  • 典型问题
    • macOS PTY 行缓冲区仅 1024 字节(Linux 4096),超长数据被内核静默丢弃
    • macOS 自带 bash 3.2(2007年)vs Linux bash 5.x,语法行为不同
    • 用户 .bashrc / .zshrc 加载的插件引入不可预期副作用
  • 做法:spawn 真实进程,用 stdin/stdout 通信,在隔离用户环境中验证,不 mock 任何东西
  • 特点:暴露出来的问题往往最诡异,正因如此更需要自动化覆盖

3️⃣ 栈层:端到端才是验收基石

  • 目的:验证完整链路,而非局部行为
  • 典型环境:浏览器自动化 + 前端开发服务器 + 后端服务 + 容器化依赖 + 全局 setup/teardown
  • 测试内容:网络传输丢数据?WebSocket 分片导致时序错乱?浏览器事件循环导致异步操作被饿死?
  • 对 Agent 的意义:栈层测试是最终验收裁判,只有栈层说"过了",任务才算完成

三层对比

层次消灭的不确定性反馈速度
隔离层逻辑错误、接口契约秒级
进程层操作系统行为差异、进程间交互十秒级
栈层完整链路集成、网络时序、并发竞态分钟级

Agent 修一个栈层失败时,真正的 root cause 往往要回到隔离层或进程层定位。三层联动才构成完整的 Harness。


四、Harness 的设计原则

1. 幂等优先

  • 怎么强调都不过分。环境不幂等是 Agent 效能的头号杀手
  • 不幂等时 Agent 进入死循环:改代码 → 测试不稳定 → 无法判断 → 继续改 → 耗费大量推理资源做无效分析
  • 对客户端项目的两层含义:
    • 单元/集成测试环境要隔离干净(保证反馈确定性)
    • 端到端测试要故意暴露在真实环境下(让边缘问题提前浮出来)

2. 信号明确

  • 验收结果必须是机器可读的结构化信号(JSON、exit code、结构化协议消息)
  • 不能是"看终端输出像不像对的"、"日志里没有 ERROR 字样"
  • Agent 可以 grep、正则匹配、解析 JSON,但没法"看一眼终端觉得大概对了"

3. 分层捕获

  • 不同类型的失败在不同层暴露(这是客观规律,不是美学追求)
  • 字符串转义 bug → 隔离层就该挂掉
  • 进程配置异常 → 只有进程层测试才暴露
  • 系统缓冲区溢出 → 只有栈层测试才暴露
  • 跳过任何一层 = 给那一类问题留了免检通道

4. 超时和降级

  • 每个环节都应有独立超时,超时 ≠ 失败,超时是降级
  • Agent 需要区分:超时(外部环境暂时不可用)vs 错误结果(代码 bug)
  • 没有超时机制 → Agent 面对无限等待的黑洞

五、AI Coding 是放大器

工程基础好 + Agent = 效率爆炸
工程基础差 + Agent = 灾难加速

  • 好的情况:Harness 到位,Agent 能在一个 session 里完成多文件修改、跑几百个测试、反复 debug 直到全绿
  • 差的情况:没有 Harness,Agent 会"自信地"写出能编译、能通过 lint、但行为完全错误的代码
  • 更糟的情况:只有单元测试没有端到端验收,Agent 会"过拟合"到单元测试层——把单元测试调绿,但真实环境跑不通
  • 反面也是正面:Agent 不怕脏活,愿意在不确定环境里一个问题一个问题地啃。1.2 亿 token 是一次性的基建成本,不是持续的运行开销

六、Accept Automation 才是目的

Harness Engineering 的目标不是"写更多测试",而是 Accept Automation——自动化验收

  • TDD、CI/CD、契约测试,这些理念一个比一个正确,一个比一个难落地
  • 难不在技术,在于组织上总有理由不做(进度压力、deadline、"差不多就行")
  • Agent 是第一个真正无法"跳过测试"的开发者——没有偷懒动机,没有赶进度压力,只认环境反馈
  • 为 Agent 构建的 Harness 人类开发者一样受益

七、结语

Prompt 告诉 Agent "做什么"。Harness 告诉 Agent "做对了没有"。
前者是需求,后者是工程。没有后者,前者只是一句愿望。

Harness Engineering 本质上就是软件工程本身——讲了几十年的工程化,终于不用再假装达成了。因为现在有了一个不会绕路的执行者(Agent),它才变成了必需品。

那 1.2 亿 token,就是认真做工程的代价。贵,但一次性。建好之后,每一次后续的 Agent 协作都在享受这笔投入的回报。


核心金句摘录

  1. "Agent 的效能天花板不在模型,在环境"
  2. "Harness 不是一个东西,是一组分层的环境,每一层消灭一类不确定性"
  3. "环境不幂等是 Agent 效能的头号杀手"
  4. "Agent 是第一个真正无法'跳过测试'的开发者"
  5. "AI Coding 是放大器:工程基础好效率爆炸,工程基础差灾难加速"
  6. "1.2 亿 token 是一次性的基建成本,不是持续的运行开销"