引言:为什么需要 Harness Engineering
Vibe Coding 碰壁
你可能有过这样的下午。跟 Agent 说一个需求,几分钟后代码就出来了,能跑。再来一个,又好了。一个下午搞定了过去要写两天的东西,你觉得效率确实上了一个台阶。
后来你开始发现不对劲的地方。让 Agent 在已有的代码上改一个功能,它改了,但另一个功能出了问题。让它修,修好了,又冒出新的 bug。来回改了四五轮,你花在检查和修补 Agent 产出上的时间比省下来的还多。
问题不在模型能力或 prompt 技巧上,这两个维度的改进只能推高天花板,不能消除天花板。过去两年模型从 GPT-4 到 Claude 3.5 Sonnet 到 Opus 4.6,每一代都更强,你确实感受到了进步,能 handle 的项目更大了。你自己也在进步,prompt 写得更精确了,给的上下文更有针对性了。但每隔一段时间,同样的崩溃模式会在更大的规模上重现。项目再大一点,迭代再多几轮,又是改一个坏一个,Agent 忘了之前约定的规范,产出开始偏离预期。天花板在升高,但天花板还在。某种更根本的结构性限制在起作用。
注意力随对话长度衰减,就是这种结构性限制的一个具体表现。你在对话前期定下的约束,到后期可能已经对 Agent 的输出没有实际影响。
比如你在第五轮定下了一条架构约束,所有 API 返回值必须包含 error code 字段。Agent 照做了。对话继续推进十几轮,讨论了别的功能,生成了大量代码。到第三十轮你让它加一个新接口,error code 字段消失了。你去翻对话,那条约束还在第五轮的位置。
原因出在 attention 机制上。LLM 每生成一个 token 时,会通过 attention 机制回顾 context 中的所有内容,为每个部分计算一个相关性权重,然后综合这些加权信息做出选择。这个权重分配不是均匀的。研究表明,模型对 context 开头和结尾的信息关注度较高,中间部分的召回率显著下降(lost in the middle)。随着对话变长,你早期定下的约束被夹在越来越多的代码输出和功能讨论之间,分到的注意力权重越来越低,低到不再实质性地影响 Agent 的输出。信息还在 context 里,但 Agent 实际上已经看不见了。
对话继续变长之后还会触发 compaction。系统把早期对话压缩成摘要来腾出空间。你能看到 compaction 发生了,但你无法控制哪些信息被保留、哪些被丢弃。你在第五轮定义的那条约束可能在摘要中变成一句丢失了细节的概括,也可能完全没有出现在摘要里。注意力衰减是信息还在但 Agent 看不清,compaction 是信息被直接删除了。两者叠加,长对话中的意图对齐建立在一个不断流失的基础上。
注意力衰减和 compaction 只是你碰到的问题的一部分。它们背后有一个更完整的图景,能解释你遇到的所有那些墙,也能解释为什么同样的工具在不同人手里效果差异如此大。
大部分开发者的 Agent 使用体验跟你类似,体感快了,综合生产力提升在 1.5 到 2 倍之间。但同样的工具,少数人做到了截然不同的成绩。PingCAP 的 CTO 黄东旭用 AI 将 TiDB 的 PostgreSQL 兼容层重写为接近生产水平的代码。Pigsty 创始人冯若航一个人用 AI 维护着集成了 460 多个扩展的企业级 PostgreSQL 发行版,日常同时调度十个 Agent 并行推进。他们的生产力提升以数十倍计,产出的是经过验证、上了生产的代码。
同样的模型,同样的工具,差距以数十倍计。差在工程制度上。能够大规模使用 Agent 的团队都建立了一套与 Agent 结构性特征匹配的闭环控制体系,用规约把模糊的意图变成精确的输入,用自动化验证检查每一次产出,用持续演进保证体系本身不退化。行业把这套方法叫做 harness engineering。
为什么你需要 Harness
Harness 的必要性来自 Agent 作为执行者与人类的结构性差异。理解这些差异,你就能诊断自己碰到的每一面墙,也能判断当前的工程实践是否在解决真实的问题。
Agent 的结构性特征
Agent 的行为由两层技术架构决定。底层是 LLM,基于所有输入内容逐个生成最可能的下一个 token。每生成一个 token,模型通过 attention 机制回顾输入中的所有部分,为每个部分计算相关性权重,综合加权信息做出选择。上层是 Agentic Loop,让 LLM 能与外部世界交互。Agent 接收指令,推理下一步行动,调用工具(读文件、执行命令、调 API),观察工具返回的结果,再推理,再行动。这个循环持续进行直到任务完成。每一步的输入和输出都追加到 context window 中。
从这两层架构,可以推导出 Agent 作为执行者的五个结构性特征。每个特征都是架构的内在属性,不会随着模型能力提升而消失。
忠实执行
Agent 忠实地执行你给它的输入。给它清晰完整的 spec,产出质量高。给它模糊的描述,每个模糊点都被编译成一个随机决策。
这是 LLM 工作方式的直接结果。输出完全由输入决定,模型处理的是你实际提供的文字,而不是你脑子里的意图。你的意图只有被写成文字送进 context 的那部分才会影响输出。你对 Agent 说,加一个搜索功能。搜索的范围是文章标题还是全文?结果按什么排序?关键词为空时显示什么?每个没有说清楚的点,Agent 按当前 context 下概率最高的方案填充,然后忠实执行。这些选择可能偏离你的意图,你在审查产出之前无法得知。
人类程序员遇到同样的模糊需求,会调用业务常识来填补空白,会看看现有代码里类似功能是怎么做的,或者直接走过来问你一句。Agent 跳过了所有这些补全步骤,直接从模糊的输入生成确定的输出。
你的团队里有大量未文档化的隐性知识,Agent 对这些知识完全没有访问权限。为什么某个模块选用了特定的设计模式,为什么某个 API 的错误处理有自己的特殊逻辑而不走统一的 error handler,某个客户的数据格式有哪些已知的异常需要兼容。人类程序员通过 code review、站会、日常协作逐步吸收这些知识。只有被写进 context 的知识才存在于 Agent 的世界中,产出的代码会在功能上正确地忽略所有未被显式提供的知识。
你说得是否足够清楚,只有在看到产出之后才能判断。你有多少隐性知识忘了显式提供,你自己也不知道。在开环控制下,每一个遗漏都变成输出中的一个不确定性来源。
有限处理容量
Agent 的工作记忆有硬上限,有效容量远小于标称数字。所有信息给得越多效果越好的直觉是错的。
Agent 的全部工作记忆就是 context window。你的指令、代码文件、对话历史、工具返回的结果,所有信息被拼接成一个 token 序列送入模型。这个序列有长度上限,当前主流模型从 128K 到 1M tokens,看起来很大。但标称容量和有效容量是两回事。前面讲过,attention 在 context 上的分配不是均匀的,开头和结尾关注度较高,中间部分召回率显著下降。信息越多,每条信息分到的 attention 权重越少。到某个临界点之后,继续添加信息的效果是负面的,关键约束被淹没在噪声里。标称 128K tokens 的窗口,有效利用的部分可能只有一半甚至更少。
这个限制在两个场景下表现得特别明显。
第一个场景是大任务。小任务涉及几个文件、一个功能点,所有相关信息都在有效注意力范围内,Agent 表现很好。大任务需要同时考虑数据库 schema、API 契约、前端状态管理和权限模型,相关信息的总量超过了有效容量,Agent 开始顾此失彼。人类程序员对整个系统有一个持久的心智模型,能在处理局部代码时维持全局一致性。Agent 每次都在有限的窗口内从头构建理解,装不下的部分直接被忽略。
第二个场景是长链推理。Agentic Loop 的每一步都往 context 里追加内容,窗口内的信息持续增长。第 5 步做出的接口设计决策,到第 50 步时已经被推到窗口远端,获得的 attention 权重很低。Agent 前半段采用的设计模式在后半段被无声地替换成另一种,它自己意识不到前后矛盾。
在开环控制下,你在两种失败模式之间左右为难。信息给少了,Agent 缺乏必要的上下文。信息给多了,关键信息被噪声淹没。你没有可靠的手段判断当前处于哪种状态。
无记忆积累
Agent 的记忆止于会话边界。会话从你发起指令开始,到任务完成或会话关闭结束。会话期间,所有信息都在 context window 里积累。会话结束后,context 被清空,下一次会话从空白开始。你昨天花二十分钟教它的架构约定、踩过的坑、约定的接口规范,今天全部归零。第一百次会话和第一次会话的起点完全相同。
人类团队的知识积累方式完全不同。一个程序员在项目上工作越久,对项目的理解越深。架构决策的历史原因、各模块的脆弱点、特定业务场景的处理惯例,这些知识大多从未被写成文档,但活在团队成员的脑子里,通过 code review、站会、日常协作自然传递和更新。Agent 驱动的开发缺乏这个自然的积累过程。
你可以把知识外化为文档来弥补,但文档本身也需要持续维护。人脑中的知识随项目演化自动更新,你重构了一个模块,你脑子里对这个模块的理解同步更新了。文档不会自动更新。三个月前写的架构文档,如果没有人显式维护,可能已经和实际代码对不上了。过时的文档比没有文档更糟糕,因为它给 Agent 提供的是错误的信息,Agent 会忠实地按照错误的信息执行。
无后果感知
Agent 的目标函数是当前指令的满足度。你让它加一个功能,它加了。你让它改一个 bug,它改了。目标到这里就结束了。代码的长期可维护性、技术债的积累水平、架构的一致性,这些维度不在它的优化目标里。人类程序员会想到三个月后自己还要维护这段代码,会为了可读性牺牲一些短期效率。Agent 的每一次执行都是独立的,当前任务完成就是全部目标。
这个特征带来一个自强化循环。Agent 在生成新代码时会参考代码库中已有的模式。你之前赶工留下的一段 workaround,在 Agent 看来就是项目中已建立的实现模式,会被忠实地复制到新代码中。合并后的代码成为后续生成的参考集,坏模式不断被复制和放大。人类团队积累同等规模的技术债通常需要几个月到一年,Agent 驱动的团队可能在几周内达到这个水平。系统中没有任何内在力量推动重构或质量改进。
Agent 对所有任务分配同等的注意力和速度。修改一段展示页面的文案和修改支付扣款的核心逻辑,在执行层面完全一样。人类面对高风险操作会本能地放慢节奏,增加确认步骤,找同事一起看。Agent 对所有任务一视同仁。高风险操作混在大量低风险操作中间,以同样的速度被处理。
高吞吐零边际成本
前四个特征在人类的执行速度下都是可管理的问题。你来得及 review 每个 PR,来得及在新会话开始时重新教一遍关键约定,来得及发现一个模糊的规约产出了偏离预期的实现然后修正它。人类程序员的产出速度本身就是一种错误遏制机制。产出得慢,偏差积累得慢,你有时间在偏差扩散之前发现和纠正。代码审查、架构评估、集成测试,这些下游活动的节奏和人类产出速度天然匹配。
Agent 的产出速度是人类的 10 到 100 倍。同时,它可以被轻松地并行实例化。启动第二个、第十个、第一百个 Agent 实例的成本趋近于零,不需要招聘、培训或沟通协调。
这个特征自身不产生新的问题类型,但把前四个特征的影响放大一到两个数量级。一个模糊的规约,人类程序员执行后产出两三个需要修正的偏差,你来得及逐个纠正。同一个规约交给 Agent,可能在一个小时内产出几十个偏差各异的实现。无记忆在每天两三个会话时是一个不便,在每天几十个会话时变成严重的知识断裂。无后果感知在人类速度下积累技术债需要几个月,百倍速下几周就能达到同等规模。
百倍速打破了产出和审查之间的节奏匹配。审查从逐行 review 退化为抽样检查。偏差在被人类发现之前已经被后续几十次提交固化,成为代码库中新的既成事实。你的最后一道防线,人工 review,在百倍产出面前失守了。你不可能以百倍速度审查百倍产出。开环控制在 Agent 的速度和规模下彻底不可行。
Harness 的本质
五个特征共同指向一个需求。你需要外部的、自动化的、独立于 Agent 的反馈机制,来替代人类执行者自带的那些能力。这个机制由两个原则构成。
闭环控制保证每一次执行可靠。闭环做两件事。第一件是用规约定义清楚什么是对的,把你脑子里的意图变成 Agent 可以对照执行的精确描述。一份规约包含意图(做什么,为什么做),验收条件(怎么算做对了),和约束(改动的边界在哪,什么不该动)。有了规约,Agent 的输出从不可预测的随机变成了可以检查的有限集合。第二件是用验证检查做对了没有。验证是独立于 Agent 的自动化检查机制,在偏差产生的时刻就捕获和纠正它,而不是在最终交付时由人类肉眼发现。规约和验证构成反馈回路,偏差被即时发现并纠正。
持续演进保证闭环本身不会退化。规约、测试、流程文档构成了你为 Agent 搭建的外部知识体系,替代人类执行者自带的业务常识、项目记忆和质量意识。前面讨论无记忆积累时已经指出了一个关键问题:外化的知识不会自动更新。三个月前写的 spec,如果没有人维护,可能已经和当前代码对不上了。
这时无记忆和无后果感知两个特征叠加出一个危险的组合。Agent 每次会话都从这些文档重新开始,它没有能力判断文档是否过时。同时它也不会主动质疑文档的合理性。过时的 spec 指导 Agent 生成偏离当前需求的代码,这些代码被合并后成为后续 Agent 的参考基线,偏差在闭环的保护下被制度化。闭环本应保障质量,在这个场景下反而固化了错误。
所以闭环需要一个配套原则。规约、测试、流程文档都需要随项目演化持续更新和迭代。演进不是闭环之外的额外工作,是闭环存活的必要条件。
闭环控制加持续演进,这是本书对 harness engineering 的完整定义。不是一份 AGENTS.md 文件,不是一套工具集,是一个围绕 Agent 结构性特征设计的工程体系。
这个定义与行业中已有的实践一致。HashiCorp 联合创始人 Mitchell Hashimoto 最先使用 harness engineering 这个词,他的核心做法是用 AGENTS.md 引导 Agent 行为,用编程化工具让 Agent 验证自己的产出。OpenAI 在一个三人团队生成百万行代码的案例中把 harness 定义为围绕 Agent 的完整系统。Martin Fowler 把 harness 分解为 guides(前馈控制)和 sensors(反馈控制)。这些实践都在做对的事,AGENTS.md 是规约的一种形式,验证工具是闭环的一个组件,Fowler 的分解是闭环结构的一种表达。本书提供的是这些实践背后的分析框架,让你理解每个组件在应对什么结构性挑战,判断自己的体系是否充分,知道碰到新场景时该怎么调整。
全书路线图
全书沿生产力阶梯展开,每一卷对应一个跃迁阶段。
卷一解决可靠性。你坐在 Agent 前面一问一答,但产出从碰运气变成工程化交付。规约章节讲怎么把模糊的意图变成 Agent 能精确执行的输入。验证章节讲怎么用自动化手段证明产出符合意图。掌握这两章,你在单次交互层面建立起闭环。
卷二解决规模。闭环建立之后你才有可能放手让 Agent 自主执行。缺少闭环的自主执行就是 YOLO mode,灾难是确定的。第四章处理长期执行中的上下文管理和跨会话记忆,让一个 Agent 能持续推进复杂任务而不丢失关键信息。第五章扩展到多 Agent 并行,解决隔离与集成的问题。你从实时操作者变成任务的设计者和验收者。
卷三解决组织。个人效率不再是瓶颈后,瓶颈转移到团队层面。分工、流程、角色定义都是为人类的执行速度设计的,需要重新匹配 Agent 时代的节奏。卷一卷二建立的工程实践是组织级协作的基础设施,没有这些基础设施,团队级的 Agent 协作无从谈起。
三类读者可以从不同入口开始。如果你是工程师,正在从自己写代码转向指挥 Agent 写代码,从卷一开始,沿着生产力阶梯一路走下去。如果你是产品人或编程新手,已经用 vibe coding 做出了能跑的产品,卷一的规约和验证会直接帮到你。如果你是技术负责人,正在推动团队 AI 转型,可以先看卷三了解组织层面的挑战,再回到卷一卷二了解支撑组织变革的工程基础。
Harness Engineering Playbook · AgentsZone Community