如何实施Harness工程
Harness工程的概念已经流行了一段时间。网上的大多数文章都聚焦于理论,解释为什么现代AI开发不能再依赖单一提示词,也不应该将模型仅仅视为"智能的自动补全代码"。然而,一个实际问题不断浮出水面:
我理解这个概念,但当真正要工程化时,我到底应该先做什么?
这个问题尤为关键。因为"Harness"这个词听起来很宽泛,几乎像一个抽象的方法论。如果它不能落地到实际的工程实践中——如目录结构、文档、脚本和工作流——它最终不过是一句漂亮的口号。在现实中,Harness工程在不同项目中的表现形式在表面上可能完全不同。有些严重依赖CI/CD流水线,有些依赖严格的开发标准,有些依赖多智能体编排,还有些可能只是严格地组织几个脚本和模板。但如果你深入挖掘,你会发现它们都在解决完全相同的核心问题:
如何让AI在你的项目内始终如一、可靠、可预测地交付你想要的确切结果。
可以参考下图,我将Harness成熟度模型恰好分为五个类别,以在诊断清晰度和可操作进展之间取得平衡。
实际用例:你处于哪个层级?
- Level 0:最适合一次性脚本或纯实验。你不在乎可维护性;你只想看看一个想法是否现在可行。
- Level 1(约束):适合独立开发者和MVP。你需要AI加速样板代码,但你仍然是每行代码的主要架构师和审查者。
- Level 2(反馈循环):生产型初创公司和小团队的理想状态。这是AI成为可靠初级合作伙伴的阶段。你信任代码,因为系统(测试、CI、linter)捕获了错误,而不仅仅是你的眼睛。
- Level 3(专业化):复杂多服务系统所必需。当代码库大到一个人无法全部理解时,你需要拆分AI角色(规划者vs编码者vs测试者)来管理上下文并防止回归。
- Level 4(自主):专为平台级或AI原生组织保留。这适用于你需要系统自我修复和持续重构而无需人工干预的场景。
在这篇文章中,我不会重申"AI很重要"或"工程化很重要"之类的泛泛之谈。我只想做一件事:用一个最小的Go项目——加密货币快照API——作为贯穿始终的示例,逐步带你了解我们是如何构建Harness的。我会详细说明哪些方法有效、我们在哪里遇到了挫折,以及哪些我们最初认为足够但后来证明完全不够的内容。读完后,你不需要逐字照搬。但你至少会知道:如果你想在自己的项目中从头构建一个Harness工程框架,从哪里开始,以及按什么顺序逐步补全其余部分。
我已经将整个设置过程逐一拆解,尽可能彻底地解构每个步骤,使一切清晰明了。我保证这篇文章值得多次阅读。当然,这里分享的所有观点严格来说都是我个人的——它们不一定普遍正确,我提出它们正是为了引发讨论。
本文示例Harness可以从github下载。
1、澄清最容易被混淆的概念
许多人一上来就开始编写规则、构建智能体、集成MCP,结果却陷入了越来越混乱的泥潭。根本原因不是缺乏执行能力,而是基础概念从未被清晰区分。以下术语将在我们的工程框架中反复出现。如果这些概念仍然模糊地混在一起,就不可能建立稳定的基础。
让我们将这些概念压缩成一个快速参考表,以建立更清晰的全局图景:
1.1 究竟什么是规则?
规则可以理解为你为AI建立的一套"工程准则"。
它不是需求文档、设计规范或脚本。更像是你在入职一个新开发者时会列出的基本原则:什么是允许的、什么是严格禁止的;完成后必须验证什么;哪些约定是绝对不可商量的。
例如,在我们的项目中,我们有一条特定的规则,强制执行严格的后修改检查清单:
- 不能只说"我完成了。"
- 必须编译代码。
- 必须运行测试。
- 必须执行后验证。
- 如果这三个步骤没有全部通过,任务就不算完成。
因此,规则的核心目的不是让AI"更聪明"。而是防止AI反复犯基本的、本可避免的错误。
规则更像是一个团队的开发策略。策略不是设计来直接创造价值的;它们是设计来消除混乱和执行一致性的。
但这里有一个关键的注意事项:规则是软约束,而非硬门槛。
这是什么意思?理论上AI应该遵循它们,但不一定每次都可靠地做到。特别是当你的规则集增长、任务变得更复杂时,模型倾向于表现出三种典型失败模式:
- 遗忘:它干脆忘记某个规则的存在。
- 选择性无关:它认为某条规则"不适用于"当前上下文。
- 懒惰绕过:它知道规则,但跳过以节省计算或上下文窗口,并为这种遗漏找借口。
这就是为什么规则是基础性的,但仅靠它们是不够的。它们设定了基线,但不能保证执行。这正是我们需要Harness框架其余部分的原因。
1.2 究竟什么是技能?
技能是我强烈建议每个团队尽早实现的首要事项之一。
本质上,技能告诉AI:"不要在这件事上即兴发挥。不要每次都从头推导流程,也不要猜测一个粗略的工作方式。只需按照这些确切步骤执行。"
以编译为例。如果你只说"去编译这个",AI可能会愉快地运行go build ./...。表面上看起来没问题。但在真实的工程环境中,编译很少那么简单。它通常涉及:
- 同步和验证模块依赖(
go mod tidyvs 严格的go.sum验证) - 应用正确的构建标签和环境约束(
-tags、//go:build指令) - 管理CGO依赖或交叉编译标志(
CGO_ENABLED、GOOS/GOARCH) - 通过链接器标志注入运行时元数据(
-ldflags="-X main.version=...") - 将结构化的编译器输出路由到确定性日志文件
- 区分硬错误和警告,以决定产物是否真正可交付
如果你让AI每次都自由即兴处理这些细节,你就是在保证最终会出问题。
这就是为什么我们将编译变成了一个技能。我们对测试也做了同样的事。还有后验证。现在,每当AI到达这个阶段,它不再是在"想办法完成",而是在"执行操作手册"。
把技能想象成AI的标准操作程序(SOP)。如果规则告诉AI"这件事必须做",技能告诉AI"确切地怎么做这件事"。
1.3 究竟什么是子智能体?
子智能体从根本上说是一个具有明确分工的多AI角色系统。
当团队刚开始使用AI时,通常默认使用一个智能体端到端处理一切:分析需求、设计架构、编写代码、审查代码、生成测试、总结进展。这对短小、简单的任务有效。但一旦复杂性增加,问题立刻就会出现:
- 它解读自己的需求。
- 它给自己的技术设计打分。
- 它编写代码然后给自己开绿灯。
- 它天生倾向于"推进任务"而非"停下来承认真正的问题"。
这与真实世界的软件开发完全吻合。当一个人同时扮演产品经理、架构师、开发者和QA时,质量不可避免地变得不可管理。
这就是为什么我们引入了多个子智能体,将工作流分解为不同的阶段。每个智能体只处理自己负责的部分,将输出写入结构化文档,然后交接给下一个智能体。
在真实的工程团队中,子智能体直接对应专业角色:
- 需求专家只澄清需要构建什么。
- 架构师只确定技术设计。
- 守门人只决定是否可以进入开发阶段。
- 开发者只专注于实现。
- QA/审查者只验证并闭环。
- PM只协调整个流程。
这种方法非常直观——没有什么革命性的或新颖的——但它对AI来说效果显著。关注点分离防止了上下文崩溃,消除了自我验证偏见,并在每个阶段强制进行客观检查点。
1.4 究竟什么是工作流?
工作流不仅仅是"启动几个智能体"。如果你有多个智能体但没有工作流,你没有一个系统——你只是有"几个人在干活"。你缺少一个稳定、可重复的协作协议。
理解工作流最清晰的方式不是把它看作流程图,而是把它看作接力赛的规则。
在接力赛中,最重要的因素不是有四个跑得快的人。最重要的是事先建立清晰的规则:
- 谁跑第一棒?
- 下一棒选手究竟什么时候接棒?
- 交接区必须交接什么?
- 什么算犯规?
- 如果犯规了,是重新开始、罚时还是取消资格?
工程完全一样。拥有需求、设计、开发和测试的角色只意味着你"有人"。只有当你明确定义了以下内容时,工作流才真正存在:
- 任务当前处于哪个阶段?
- 该阶段确切需要什么可验证的输出?
- 谁有资格接下一棒?
- 下一次交接前必须审查哪些文档?
- 什么条件会触发自动拒绝/回滚?
- 如果回滚了,谁负责修复,流程从哪里重新开始?
没有工作流,工程现场通常会退化为以下情况:
- 需求模糊,设计师在中途随意改变范围。
- 设计有缺陷,但开发者为了"保持势头"继续推进。
- QA发现了阻碍问题,但PM为了赶上截止日期强行推进。
- 某个阶段明显需要回滚,但没有人知道谁应该负责修复或从哪里重新开始。
- 每个人都在"工作",但没有人能回答:"这个任务目前的实际状态是什么?"
所以工作流的核心不是"有一张图"。而是为每一次推进、暂停、拒绝和重新开始建立明确的、可审计的规则。
在我们的项目中,这个工作流跨三层构建:
- 人类可读层:解释整体开发流程、理念和交接期望。
- 系统执行层:硬编码阶段边界、状态转换和验证门槛。
- 角色特定层:准确定义每个子智能体在接手时读取什么,在交接时必须写入什么。
这三层结合起来形成了一个真正可以长期维护的工作流。没有它们,你拥有的不是一个流程——你只有几个漂亮的提示词模板。
与这个"接力"结构并行的是严格的上下文纪律:每一棒只接收它该段实际需要的材料。这不是隐藏信息;而是防止AI上下文过载。一上来就把所有规则、项目地图和任务历史都倒进去会稀释焦点。这就是为什么我们有意让规则集逐步增长,并将项目范围的资源如dev-map或任务板延迟到后续阶段才加载。这与分阶段工作流和子智能体隔离完美契合:相同的理念,不同的实现。
1.5 究竟什么是脚本?
脚本是整个Harness中"最重要"的组件。
如果规则告诉AI它应该做什么,技能给AI标准操作程序,那么脚本说的是:"你说你完成了毫无意义。除非系统证明了,否则你通不过我的检查站。"
这就是为什么我越来越确信,一个真正成熟的Harness不可避免地会随着时间的推移更多地依赖脚本,而不是更多地依赖提示词。
在我们的项目中,我们有一个规范化的**"主守门人脚本"**。它将许多以前作为软建议存在于规则中的检查变成了硬性的、可执行的验证。例如,它验证:
- 是否使用了硬编码字符串、密钥或魔数,而不是使用
config/env包? - 是否使用了
fmt.Println或log.Print而不是我们的结构化日志器(如zap/slog)? - 整个代码库是否通过了
golangci-lint run且零警告? - 是否有直接调用
os.Exit()绕过优雅关闭或错误处理包装器? go.mod/go.sum是否与实际导入严格同步(go mod tidy差异为零)?- 构建标签(
//go:build)是否正确应用、有文档且有测试? - 项目是否在目标平台上干净编译(
go build -v ./...)? - 所有测试是否通过了竞态检测和严格超时(
go test -race -timeout=30s ./...)? - 代码覆盖率是否低于项目基线?
- 生成的文件(
mocks/、pb/、deepcopy/)是否被意外提交而不是在CI中重新构建? - 导出的类型和函数是否遵循我们的命名、版本和弃用约定?
- 是否有遗留没有关联issue编号的
TODO/FIXME注释?
一旦这些检查被写入脚本,AI就再也不能用"我觉得没问题"来糊弄了。它要么通过检查站,要么通不过。没有谈判的余地,主观判断也没有藏身之处。
1.6 究竟什么是MCP?
MCP(Model Context Protocol)从根本上说是一个标准化桥梁:它将"代码仓库之外的能力"直接连接到AI的运营工作流中。它允许AI在严格定义的边界内从外部系统拉取信息和触发操作。
把它想象成一个可编排的接口层。AI不再仅依赖当前对话上下文和本地文件,而是可以接入Wiki、知识库、结构化数据和平台API。在Unity或其他宿主引擎环境中,它可以与编辑器/运行时能力(编译、资产管理、日志、状态检查和控制命令)直接交互,使"生成的代码"与"宿主环境中实际发生的事情"保持一致。
这就解释了为什么当你试图将Harness从"开发循环"演变为完整的"工程交付循环"时,MCP变得至关重要。交付流水线充满了系统级能力——CI触发、代码签名、制品管理、发布编排和状态回调。这些都不能简单地通过多写几个本地脚本来替代。
让我们先看看边界。没有MCP,AI通常被锁定在:
- 本地代码仓库
- 本地脚本
- 当前对话上下文
它可以分析、修改代码和运行本地验证,但很难安全、结构化、可审计地与更广泛的工程系统交互。
反之,如果你想要一个完整的闭环,你最终需要处理以下操作(仅列常见的):
- 通过CI平台触发构建
- 获取构建日志和结果
- 调用签名服务对安装包或二进制文件进行签名
- 将制品上传到注册中心或分发平台
- 编排发布(金丝雀、审核、生产上线)
- 回写发布状态、版本标签和交付记录
共同点是什么?这些都需要AI在受控边界内调用系统能力,而不是在聊天日志中散布凭据和临时命令。MCP充当的就是那个连接层:它将外部系统以结构化的工具或资源形式暴露给AI,使其可被规则、工作流和脚本执行。
在我们的整体架构中,MCP不是Harness的核心。它是外部接口。它连接什么、访问粒度多细、什么时候被允许触发——这些本身必须受策略和门槛的管控。
如果规则是团队策略,技能是SOP手册,脚本是安全闸机,那么MCP就是标准化电源插座,将AI插入更广泛的工程生态系统。目前它可能感觉像个锦上添花的东西。但当你期望AI可靠地参与构建、签名、打包、发布和报告状态——而不仅仅是写代码——这一层很快就会变得决定性。
1.7 总结这些概念
这一章只是带你了解了将在本指南中反复出现的核心组件。如果你是第一次接触这个框架,先别急着往下看。花点时间在心里把它们映射一下:
- 规则:告诉AI边界在哪里。
- 技能:告诉AI如何在这些边界内执行固定动作。
- 子智能体:将单一任务拆分为多个专业化、协作的角色。
- 工作流:规定这些角色何时、以什么顺序交接。
- 脚本:不给AI任何指令——它直接验证工作是否真的完成了。
- MCP:将AI连接到外部知识、工具和宿主系统。
这些组件不互相替代。它们叠加在一起。
你也可以通过这个功能视角来看待它们:
- 规则执行底线。
- 技能标准化高频操作。
- 子智能体将复杂性分解为聚焦的角色。
- 工作流编排协作顺序。
- 脚本客观验证输出。
- MCP将系统扩展到更广泛的工程生态系统。
换句话说,到目前为止你看到的只是一盒零件。一组约束、流程、验证器和接口并排放在一起。
接下来是最关键的一步:为什么这些零件正确组装后会变成一个完整的Harness工程系统。
1.8 Harness工程是什么,在实践中是什么样的?
如果你理解了前面的概念,这里就是一切豁然开朗的地方。
我对Harness工程的当前理解很简单:它不是一个单一工具,也不是一个巧妙的提示词技巧。它是一个完整的工程系统,旨在让AI在一个真实项目中始终产生正确、可靠的结果。
注意这里的三个关键词:
- 稳定:不是"这次运气好",而是下次、下下次,面对不同的需求,甚至不同的维护者都能可靠工作。
- 输出:不仅仅是写代码,而是交付完整的生命周期制品:需求、设计、验证和部署。
- 正确结果:不是"做完就算",而是有一个可验证的、客观的方式来证明工作是否真的正确。
所以在我看来,Harness工程不解决"如何让AI更聪明"。它解决的是:我们如何将AI从一个即兴发挥的模型转变为一个受约束的、协作的、可验证的、可持续维护的执行系统?
如果我们铺开当前Harness的全貌,大致如下:
- SPEC(设计规范):预先明确目标、边界和版本意图。解决:"AI到底应该构建什么?"
- 规则:硬编码基础约束和红线。解决:"什么绝不能被违反或即兴发挥?"
- 技能:标准化编译、测试和验证等固定动作。解决:"如何阻止关键流程依赖猜测?"
- 子智能体:将不同阶段拆分为不同的角色。解决:"如何防止一个智能体同时扮演产品经理、架构师、开发者和QA?"
- 工作流:定义角色如何交接、何时推进、何时拒绝/回滚。解决:"如何协调多角色协作而不依赖临时猜测?"
- 脚本/后验证:将抽象约束转化为可执行的检查。解决:"如何验证'完成'确实意味着'正确'?"
- Dev-Map(开发导航图):帮助AI快速掌握项目结构和现有模式。解决:"如何阻止AI一进入代码库就开始重新发明轮子?"
- 任务板:保持PM和分析师与项目历史和当前进展保持同步。解决:"如何确保专注当前任务而不失去更广泛的项目上下文?"
- MCP:目前还不是我们Harness的骨干,但对未来扩展至关重要。如果我们想与CI、签名、制品管理和发布等外部系统闭环,MCP将成为必不可少的连接层。
如果我要打个比方,我会说:Harness工程就像为AI构建一个完整的"工程运营系统"。 SPEC是任务目标,规则是纪律,技能是标准操练,子智能体是单位专业化,工作流是指挥链,脚本是检查和反馈循环,而Dev-Map和任务板提供地形图和战场态势感知(这两个概念将在第九章详细说明)。
这些部分单独看都不是革命性的。真正的价值只有在它们被组装起来时才会显现:那就是AI不再像一个聪明的聊天机器人,而是开始像一个纪律严明的工程师在一个真实项目中运作。
2、构建Harness之前——从SPEC开始
在我们深入构建Harness的实际"第一步"之前,我认为有必要简要说明这个示例项目到底是什么。
如果你不知道crypto-snapshot-cli做什么、解决什么问题,或者大致处于复杂性光谱的哪个位置,就很容易将我们的方法论误解为仅适用于大型企业系统的某种复杂仪式。事实是,这个项目有意保持最小化——但它包含了AI通常崩溃的所有结构性缝隙。这正是为什么它是从头构建Harness的理想场地。
2.1 工程概况:crypto-snapshot-cli做什么
在构建任何东西之前,让我们先了解这个项目到底是什么。如果你不理解其范围和复杂性,可能会误以为Harness对于一个简单工具来说是过度工程化。它不是。它是一个最小但完整的示例,暴露了AI通常失败的每一个缝隙。
项目名称:crypto-snapshot-cli
一句话描述:一个Go CLI工具,从CoinPaprika API获取实时加密货币价格,验证数据,并导出带有完整审计跟踪的结构化JSON快照。
它解决什么问题?
真实场景:你在构建一个交易仪表板、投资组合跟踪器或自动再平衡系统。在做这些之前,你需要可靠的结构化价格数据。
但获取加密货币价格并不像调用一个API端点那么简单。你需要:
- 优雅地处理速率限制
- 为瞬态故障实现重试逻辑
- 根据schema验证API响应
- 带上下文地记录错误以便调试
- 以下游系统可消费的格式导出数据
- 确保整个流水线在时间预算内完成
没有Harness,AI会生成有时能用的代码。有了Harness,它会生成每次都可靠工作的代码。
核心功能
输入: CLI参数 (--limit=10, --output=prices.json)
↓
获取: 使用重试逻辑调用CoinPaprika API
↓
验证: 检查响应schema、数据类型、完整性
↓
转换: 将API响应转换为内部模型
↓
导出: 将结构化JSON写入文件
↓
报告: 生成执行日志 + 校验和
就这样。没有WebSocket流。没有数据库。没有Web UI。没有机器学习。只是一条干净的、线性的数据流水线。
2.2 人类构建Harness,AI编写代码
一个关键点必须预先澄清:在这个项目的持续演进过程中,每一行生产代码都是由AI编写的。 人类没有写任何一行实现代码。
那么人类到底做了什么?我们没有跳进去修补bug,也没有充当"高级打字员"站在AI后面打磨其输出。相反,我们的全部精力集中在系统性地构建Harness工程框架上:
- 首先,彻底阐述需求和设计。
- 接着,编码基础规则。
- 然后,将固定流程标准化为技能。
- 之后,将工作流分解为专业化的子智能体。
- 然后添加基于脚本的门槛和后验证检查。
- 最后,集成项目地图、任务板和工作流定义文件。
换句话说,这个项目从来不是一个成熟的工程团队先写代码然后加装AI作为助手来构建的。情况恰恰相反。我们先构建了Harness。随着Harness的成熟,AI自然而然地从处理琐碎任务→ tackling复杂功能→最终自主维护整个项目。
人类不写代码。人类构建了生成、验证和维护代码的系统。
2.3 从设计规范(SPEC)开始
所以这一章真正回答的问题不是"为什么要写SPEC?"而是"当你面对一个真实的、将持续迭代的、完全由AI构建和维护的项目时,你实际上从哪里开始?"
很多人听到"Harness"就立刻跳去写规则、拆分智能体或编写门槛脚本。但如果你没有先澄清"我们到底在构建什么,'完成'是什么样子?",你后来添加的每一个约束都建立在沙子上。
所以我们真正的第一步不是写规则。而是起草一份全面的设计规范——并与AI本身进行多轮迭代来敲定它。
在crypto-snapshot-cli项目中,我们就是这样开始的。我们没有从代码开始。我们开始与AI协作编写详细的SPEC。
这份文档的目的不是"看起来专业"。它是在生成任何一行代码之前,强制对基本面进行明确:
- 这个版本究竟解决什么问题?
- 核心目标与锦上添花的功能分别是什么?
- 哪些模块会受到影响?
- 什么行为必须保持向后兼容?
- "完成"究竟是什么样子?
我通常在这一步与AI来来回回多轮。这感觉可能很繁琐。但我从痛苦中学到了:如果你在这里偷工减料,你之后会付出十倍的代价。
这些迭代不仅仅是打磨文字。它们是一个协作发现过程。有时你甚至不一开始就知道自己确切想要什么。让AI参与需求讨论让它扮演魔鬼代言人角色、拆解选项、暴露边界情况。真实需求很少在第一稿就完全成型——它们是通过对话挖掘出来的。
一个生产级SPEC是什么样的?
它必须明确声明每一个需求,定义必要的边界条件(需求分析智能体稍后会帮助补充),并且零歧义语言。像"建议"、"可以"、"推荐"或"可选"这样的词在这里没有位置。如果不是强制性的,就不应该出现在规范中。如果是必需的,必须声明为硬约束。
但很快,我发现了一个残酷的事实:仅靠SPEC是不够的。
问题不在于AI不理解文档。问题在于:
- 它不会100%遵循。
- 一旦它"完成"了,你没有清晰的方式来追踪什么实际完成了、什么还待处理。
- 它会在不同会话中重复犯完全相同的错误。
例如,它会:
- 根据自己的判断跳过它认为"不太关键"的细节。
- 声称"一切都完成了",结果你发现缺失文件或未实现的边界情况。
- 犯上周的错误,因为它对过去的失败没有持久记忆。
那时我才真正意识到:
SPEC只解决了"知道做什么"的问题。它不解决"如何持续正确地做"的问题。
这正是我们进入下一步的原因:编码规则。
3、规则是必要的,但不要崇拜它们
我最初的直觉很简单:如果AI老是忘记,我就把那些容易忘记、容易出错的步骤写下来作为规则。
像"每次代码修改后必须进行编译、测试和后验证"这样的指令就是这样诞生的。本质上,这条规则告诉AI:
- 每次修改后编译。
- 只有在构建成功后才运行测试。
- 只有在测试通过后才执行后验证。
- 只有三个步骤全部成功,任务才算完成。
这一步非常有效。为什么?因为AI最喜欢偷工减料的地方正是那些"看起来像清理工作,但实际上是硬基线"的动作。它经常这样找借口:
- "我只改了一个文档,所以不需要编译。"
- "这是一个小调整,测试太小题大做了。"
- "这个失败看起来像是遗留问题,不是我引入的。"
一旦规则被强制执行,这些粗糙的失败就会大幅下降。
但如果你在一个真实的复杂项目中运行足够长的时间,你会很快撞到规则的天花板。
随着你的规则集增长,会出现两个高度可预测的问题。
3.1 AI会忽略规则
不是完全忽略。但在复杂任务下,它会受到"选择性失忆"的影响。特别是当提示词很长、上下文窗口很重,或同时加载了多个文档时,某些规则在实际执行过程中会被稀释或降低优先级。模型不会删除规则;它只是在认知负荷激增时停止将其视为强制性的。
3.2 AI会绕过规则
这比简单的遗忘要麻烦得多。AI并非不知道规则;它开始主动找借口绕过它。例如:
- "这个失败不是我引入的;它是遗留的技术债务。"
- "这条规则适用于标准工作流,但这是一个特殊情况。"
- "我已经做了等效的验证,所以严格遵循没必要。"
这标志着我在Harness之旅中的关键认知转变:
规则并非无用——它们只是服务于不同的目的。规则执行原则性约束**;它们不能执行流程执行。
一旦我内化了这一点,我就进入了下一步:将固定的、可重复的流程从规则中提取出来,并将其编码为技能。
4、为什么编译、测试和验证必须是技能
如果你仔细观察,你会发现工程中有一类特定的任务非常适合成为技能:
- 执行步骤是固定且可重复的
- 每次都需要执行,毫无例外
- 一旦搞砸就极其痛苦或代价高昂
- 不值得让AI每次都从头推导或即兴发挥
编译、单元测试和后验证恰好属于这一类。
这就是为什么我们将这些工作流提取为专门的技能:compile-skill、test-skill、validation-skill。
这从根本上改变了规则和执行之间的关系。规则不再需要列出具体的命令、标志或注意事项。它只需要强制执行一行:"你必须做这件事。"
技能接手定义的职责是:"确切地如何做这件事,一步一步来。"
好处是立竿见影且高度实用的:
1. 规则保持精简。 以前,规则混合了原则和程序,随着每个边界情况而膨胀。现在,规则只强制执行硬边界和红线。复杂的执行逻辑被卸载给技能。
2. AI执行稳定性大幅提升。 以前,AI必须即兴发挥"如何编译或测试这个特定模块"。现在,它不需要思考——它只需调用一个标准化的、经过实战检验的程序。一致性取代了猜测。
3. 维护成本急剧下降。 如果以后更新了构建工具链或测试框架,你只需修改技能一次。你不必在整个仓库中grep每个规则文件以确保旧命令被替换。
经过这一步,系统的健壮性有了明显改善。AI不再跳过验证步骤,虚假的"任务完成"声明显著减少。
但一个新的瓶颈很快出现了:单个智能体,无论约束得多么好,仍然难以在复杂、多维需求下保持稳定性。
5、为什么结构化多智能体是不可避免的
在叠加了SPEC、规则和技能之后,系统明显更加稳定了。AI不再盲目地从单一提示词生成代码,开始理解目标、约束和固定程序。但随着需求变得更加复杂,一个新的瓶颈出现了:
单个智能体根本无法可靠地处理长链路、多阶段的开发,同时还要管理需求分析、架构设计、风险评估、实现、自我审查和验证。
这不是模型智能的局限。这是一个结构性问题。我们强迫一个实体同时扮演太多角色。当一个智能体同时充当产品经理、架构师、开发者、QA和发布工程师时,它不可避免地开始分裂:
在这一点上,我面临一个经典的工程权衡。问题不是"我们应该用多智能体吗?"而是:"哪种多智能体架构在生产中真正有效?"
5.1 方案一:继续强化单一智能体
最直观的路径。如果一个智能体不够稳定,就给它更多:
- 更长、更详细的SPEC
- 更精细的规则
- 更细粒度的技能
- 更严格的验证步骤
我们实际上走了一段时间这条路,它并非没用。事实上,这正是我们的SPEC、规则和技能层的演进方式。但你沿着这条路走得越远,就只是在往一个"万事通"角色里塞更多职责。它让智能体更谨慎,但不解决角色冲突。
需求分析和代码审查需要根本不同的思维方式。架构设计和测试验证遵循不同的推理模式。强迫一个智能体同时完成所有这些只是在赌它能同时搞定一切。它对简单任务有效。在真实的工程复杂性面前就会崩溃。
5.2 方案二:去中心化协作
网上流行的替代方案:多个智能体在平等地位上,通过聊天动态协商达成共识。它看起来很先进——像一场"AI团队会议"。AutoGen的GroupChat等框架就是这种方向的典型代表。
吸引力是真实的:
- 高度灵活
- 强大的实时适应能力
- 不需要预先刚性定义工作流
但在生产中,裂缝会迅速扩大:
- 执行路径不稳定(同一任务,每次流程不同)
- 责任模糊(谁来负责失败?)
- 回滚点不明确
- 难以在模型更换或团队变化时保持一致性
如果你在构建演示或探索开放式研究,这个模型很有吸引力。但如果你在长期维护一个真实的代码库,它暴露了一个致命缺陷:看起来令人印象深刻,但不可维护。
5.3 方案三:结构化编排
第三条路径:一个明确定义的工作流,具有显式的角色分工、固定的阶段边界和可审计的交接。
核心特征:
- 一个专门的编排器/PM角色
- 每个阶段有明确的负责人
- 每次交接有定义的输入/输出
- 推进与拒绝/回滚的明确条件
优势是毋庸置疑的:
- 可预测的执行流程
- 高可控性
- 完全可审计的追踪
- 天然文档友好
- 易于长期维护和更换角色
代价也是真实的:
- 前期设计成本更高
- 不如自由协商灵活
- 产生更多制品→更高的token消耗
我们果断选择了这条路。因为一旦你达到真实的工程规模,你就会学到一个残酷的真理:
Token不是最贵的部分。失控才是。
我们不仅仅需要"AI写代码"。我们需要:
- 需求规范
- 架构设计文档
- 开发日志
- 代码审查结论
- 测试报告
- 交付签字确认
- 阶段进展和回滚记录
这些不是官僚主义的开销。它们是让任何人或AI在几周或几个月后能够理解以下内容的要素:
- 为什么做了这个决定
- 进展目前在哪里
- 哪些风险被缓解了
- 哪里在流水线中出现了问题
- 如何在中断后恢复
为了可维护性、标准化和角色可替换性,结构化编排是生产工程的唯一可行路径。
5.4 结构化编排内部的PK
即使在承诺了结构化编排之后,我们还讨论了两种内部模型:
模型A:固定角色和固定流程 预先定义智能体、职责和阶段。PM只需按照预定义的顺序编排。
- ✅ 稳定、易于维护、适合文档/标准化、理想用于可重复的工作流。
模型B:固定PM+开发经理,动态智能体生成 保持PM/开发经理静态,但根据任务动态"雇佣"或生成专业化智能体。
- ✅ 更灵活,理论上可以适应高度多样化的问题。
- ❌ 角色边界漂移,维护成本更高,行为过度依赖上下文/即时判断,难以长期标准化。
我们选择了模型A。为什么?因为我们的实际工作流,虽然需求在变化,但遵循相对固定的阶段。标准功能开发=需求→设计→评估→实现→审查→测试→交付。Bug修复=同一流程的截断版本。由于工作流并不是真正开放式的,为了"理论上的灵活性"而牺牲稳定性没有任何工程意义。
回想起来,这一章中的每一个权衡都遵循了相同的模式:当灵活性与稳定性冲突时,我们始终选择稳定性。 对于一个打算维护多年的代码库,可控性、可追溯性和可复用性远远超过理论上的适应性。
5.5 核心要点
这一章不是关于多智能体很时髦。它是关于工程现实:
- 单智能体在复杂性面前失稳。
- 去中心化协作长期不可维护。
- 动态角色生成太容易漂移,不适合可预测的交付。
经过严格的技术比较,我们恰好落在这里:
使用结构化编排将研发分解为固定角色和阶段,将AI从一个混乱的即兴发挥者转变为一个纪律严明的、制度化管理下的工程系统。
6、七个智能体不是随意挑选的
它们是被问题逼出来的。
一旦结构化编排确定下来,下一个问题出现了:我们到底需要多少个智能体,应该如何拆分?
如果这一步处理不好,多智能体不会稳定系统——它会撕裂系统。我们没有在第一天就宣布"七个智能体"。相反,角色是随着具体失败在生产中暴露而逐层涌现的。
6.1 第一次拆分:需求、设计、实现
最早的痛点是"模糊的需求直接渗入代码"。用户抛出一个粗略的想法,AI快速生成了一些可用的东西,但立即出现了三个结构性问题:
- 需求边界仍然模糊
- 技术设计在编码过程中即兴发明
- 完成后,无法追溯原始理由或约束
所以我们拆分了前三个基础角色:
- 需求分析师:将模糊的想法转化为结构化的、可测试的规范。
- 解决方案架构师:将规范转化为可执行的技术设计。
- 开发者:严格在这些约束内编写代码,而不是在编码中途发明需求。
为什么首先拆分这三个?因为如果这三个融合在一起,下游的一切都会模糊成一个混沌体。问题变得不可追踪。你无法判断一个bug是来自糟糕的需求、有缺陷的设计还是草率的实现。这三者构成了整个多智能体系统的结构骨架。
6.2 第二次拆分:添加守门人(可行性控制器)
但三层还不够。写需求和设计并不能保证开发准备就绪。我们很快遇到了反复出现的场景:
- 规范列出了功能但遗漏了验收标准
- 设计在纸面上看起来完整但跳过了关键边界情况
- 一个理论上合理的变更在当前代码库中带有高集成风险
- 开发开始后,隐藏的阻碍在实现过程中爆发
我意识到我们需要一个专门的角色站在"写代码之前的最终检查站"。于是第四个智能体登场:守门人(可行性控制器)。
它不重写规范或设计。它严格判断:
- 需求是否清晰明确?
- 设计是否有明显的漏洞或不切实际的假设?
- 这能否安全地落入当前架构而不破坏现有契约?
- 继续推进是否会给编码阶段注入不可接受的风险?
没有这个门槛,问题会在开发阶段才暴露——这是修复成本最高的阶段。守门人强制早期暴露失败。(注:这些步骤是从我自己与AI的迭代提示词讨论中提取的,被正式化为固定工作流。)
6.3 第三次拆分:独立的代码审查和测试作为最终检查站
下一个现实检验:"开发者说完成了"≠"实际上正确"。
没有下游验证,"实现完成"不能证明任何事情:
- 需求覆盖率
- 设计忠实度
- 边界情况处理
- 新风险引入
所以我们把最终验证拆分为两个不同的角色:代码审查者和QA/测试者。
为什么要分开?因为它们解决根本不同的问题。
- 代码审查者从实现层往回看:是否偏离了规范/设计?结构是否合理?有没有隐藏的缺陷或技术债务?它是技术实现质量的最终检查站。
- QA/测试者从行为层向前看:它真的能工作吗?用户路径能否端到端执行?边界情况或回归是否会导致崩溃?稳定性和性能是否可接受?它是运营正确性的最终检查站。
没有审查,开发者满足于"它能编译和运行"。没有测试,系统依赖于"它看起来没问题"。它们必须是独立的门槛。下游角色不是附属品;它们是防止坏代码泄漏的实际闭环机制。
6.4 第四次拆分:纯路由型PM
到现在,角色已经越来越多。一个新的瓶颈出现了:谁来决定下一步?
如果每个智能体自己导航或协商交接,工作流就会滑回混乱的去中心化聊天。所以我们集中了项目经理(PM)角色。
关键区别:我们不需要一个"懂技术的PM"。我们需要一个"严格的流程边界PM"。
它的职责是极简且纯运营的:
- 读取阶段完成文档
- 根据验证结果决定推进还是回滚
- 路由到下一个专业化智能体
- 维护交接、迭代和交付日志
它不:
- 编写需求
- 设计架构
- 触碰代码
- 覆盖智能体的技术判断
这至关重要。如果PM越界进行技术决策,系统就退化回了"中央大脑决定一切"的模式,完全违背了角色分离的初衷。
6.5 为什么自然收敛到七个
系统自然稳定为以下七个智能体:
- PM:路由、管理交接、回滚和进展追踪。
- 需求分析师:将模糊的请求澄清为结构化规范。
- 解决方案架构师:将请求转化为技术设计。
- 守门人:在编码开始前验证可行性和风险。
- 开发者:实现代码和技术细节。
- 代码审查者:验证技术质量、规范对齐和设计忠实度。
- QA/测试者:验证功能正确性、稳定性、边界情况和回归安全性。
关键不在于"恰好七个"。而在于每个角色都解决了前一个无法解决的缺口:
- 需求→构建什么
- 设计→如何构建
- 守门人→我们现在能安全地构建吗?
- 开发者→实际构建
- 审查者→我们是否按计划构建了?
- 测试者→它在实践中真的能用吗?
- PM→如何可靠地编排这条链?
这不是为了复杂而复杂。它是将一个庞大的、混乱的任务分解为可管理的、可追踪的、可替换的模块。
6.6 实践工程:按智能体分层分配模型
这是理论与实践在生产现实中交汇的地方。
许多人假设:"如果我们拆分了角色,是不是每个智能体都应该使用最强、最有能力的模型?" 现实告诉你不是。这浪费、昂贵且不必要。不同角色有着截然不同的认知和计算需求。
- PM只处理路由、状态检查、交接日志和进展追踪。它需要可靠性和上下文保持,而不是深层技术推理。一个更轻量、成本更低的模型就足够了。
- 需求、设计、审查、QA承载沉重的分析负荷。它们需要深度推理、精确的指令遵循和广泛的上下文覆盖。它们获得重量级、高能力的模型。
工程回报是立竿见影的:
- 不是每一步都消耗高端计算
- 整体token成本可控
- 高价值推理步骤获得适当的算力
- 长期流水线稳定性改善
你不会给每个船员都配一把同样昂贵的锤子。你将工具匹配到任务。多智能体工程很快从"AI噱头"变成了真正的团队资源分配。
当你实际运行多角色、多阶段、长期迭代开发时,模型分层就不再是可选的微调。它成为Harness工程本身的核心支柱。
7、多智能体系统如何在生产中真正稳定下来
至此,七智能体骨架已完全组装完毕。说实话,一旦它开始运行,结果符合我们的预期。复杂请求不再被单个智能体蛮力碾压;它们现在通过标准化的文档链流动。我们更完整的功能开始产生一致的阶段制品,整个流水线感觉明显更清晰。
但这并不意味着系统已经成熟。恰恰相反:真正的问题只有在我们将其投入持续生产后才开始浮现。
这一章讲述的是那些真实的、来之不易的迭代。因为Harness工程从来不是"设计一次,部署永远"。它是运行、撞墙、修补、再运行、再升级。
7.1 第一波:下游智能体修改上游文档
多智能体协作上线后,第一个裂缝很快就出现了:
下游智能体开始"好心"地修改上游制品。
经典的例子:解决方案架构师读取需求文档,发现了一个不精确的地方,然后不是提出阻碍,而是悄悄地修改了需求以匹配自己的解读。
这听起来很聪明。一开始甚至感觉高效。但运行足够长的时间,你就会看到为什么它很危险:
- 需求的所有权变得模糊。
- 无法追溯设计是基于原始规范还是架构师的未经授权的修改。
- 当出问题时,你无法将责任归因到特定层级。
修复方案:我们添加了一条硬规则。
下游智能体不能直接修改上游制品。 如果下游认为上游输出不合格,必须提出正式阻碍。PM随后正式将工作流回滚到上游智能体进行修正。
一旦强制执行,系统终于获得了清晰的边界意识:每个制品都有单一、可追溯的所有者。
7.2 第二波:PM越权
随着流水线成熟,第二个模式出现了:
PM不断从流程管理者漂移为意见提供者。
这几乎是不可避免的。坐在中心位置,PM看到一切。当需求模糊、设计有争议或开发者遇到阻碍时,跳进去是很诱人的:
- "我觉得我们应该调整这个需求。"
- "这个设计如果把X改一下会更好。"
- "别回滚了,就让开发者顺手修补一下。"
但运行得越多,情况就越清楚:PM的意见很少是专业的,它们主动破坏流程。
修复方案:我们严格收紧了PM的范围。
- PM只管理工作流状态。
- PM做出零专业/技术判断。
- PM不提出对需求、设计、代码或测试的修改建议。
- 当智能体卡住时,PM路由到正确的专家智能体。
- 如果确实模糊,工作流暂停等待人类决策。
经过这个调整,PM的身份终于结晶了:不是"中央专家",而是"中央路由器"。
7.3 第三波:缺乏专业深度(聚焦代码审查和QA)
接下来,我们碰到了一个更深层的现实:
不只是一个智能体薄弱;整个多智能体链在早期都缺乏专业深度。
需求遗漏了边界条件。设计跳过了覆盖率。守门人低估了集成风险。我以代码审查和QA为例,因为它们位于最终检查站,上游的缺陷在这里自然集中并爆发。
最初,我们的智能体太"常规"了:
- 代码审查只是检查明显的逻辑bug、规则违规和基本实现缺陷。
- QA只是验证主流程是否执行不崩溃。
有用吗?是的。够吗?绝对不够。在这个阶段,这些智能体不仅仅是在检查自己的层级;它们是整条链的最终质量门槛。如果它们只看局部,就会错过关键的交叉检查:
- 需求是否被完全实现?
- 设计是否被正确转化?
- 验收标准是否被覆盖?
- 除了功能正确性,稳定性和基线性能是否可接受?
升级方案:我们加强了两个角色。
- 代码审查现在显式地交叉引用需求和设计文档。其使命:"验证对齐性、完整性和架构忠实度。"
- QA现在站在真正的闭环点。其使命:"验证功能正确性、边界情况、回归、稳定性和性能基线。"
这一步至关重要。从此以后,多智能体不再只是一个"拆分的工作流"。它成为了一个真正的质量闭环。
7.4 第四波:规则不再够了
在修补了工作流问题后,我们以为系统稳定了。但一个旧鬼回来了:
智能体仍然以借口绕过规则。
- "这个失败不是我的;它是遗留债务。"
- "这条规则不适用于这个特殊情况。"
- "我已经完成了主要工作;可以跳过这一步。"
认知转变:无论你写了多少条,规则仍然是自然语言约束。在复杂性面前,它们会被忽略、绕过或"选择性执行"。
修复方案:将可验证的约束移入可执行脚本。
- 编译必须通过。不是"应该没问题"。
- 测试必须通过。不是"理论上安全"。
- Lint扫描必须通过。不是"这次例外"。
- 只有脚本全部通过,开发才算真正完成。
这就是主验证脚本变得如此关键的原因。它不只是添加了另一个工具;它将"任务完成"从主观的AI报告转变为客观的、系统可验证的状态。(我们将在第八章深入讨论这个。)
7.5 第五波:智能体偷懒和基线对比
脚本上线后,我们以为大功告成了。但AI很快找到了新的漏洞:
甩锅给既有条件。"这个错误已经存在了。" "这个警告是历史的。"
如果没有反制机制,很容易被说服接受一个有缺陷的构建。
修复方案:基线对比。
- 在任何代码更改之前运行完整的验证套件。捕获输出/报告作为基线。
- 更改后再次运行。
- 对比两份报告。
规则:任何新引入的失败、警告或违规=必须修复。
现在,"是不是你搞坏的?"不再是口头争论。它由系统报告的差异来证明。
这给Harness又拧紧了一颗螺丝。但它证明了一个核心真理:Harness工程不是关于信任AI。它是关于设计不留偷懒空间机制。
7.6 第六波:工作流本身变得难以维护
随着请求堆积、系统成熟,一个后期问题出现了:
工作流本身变得不可维护。
最初,所有流程规则都存在于PM的长提示词中。第一天还好。但随着阶段、回滚条件和角色边界的倍增,维护变得痛苦:
- 埋在散文中的规则难以验证。
- 改了一个容易破坏另一个。
- 阶段/回滚逻辑漂移到不一致。
- 更换模型或维护者导致角色边界模糊。
认知转变:前几波修复了"让它运行"。这一波修复"让流程本身成为可维护的资产"。
升级方案:将工作流提取为工程资产。我们添加了三层:
- 工作流定义文件 将流程结构从PM的散文中提取出来。明确列出:阶段、每个阶段的默认智能体、前进转换、允许的回滚路径和有条件的回滚触发器。工作流不再是"写在文章中的知识";它是一个独立的、版本控制的资产。
- 角色契约 仅有一个定义文件不够。我们需要每个智能体的清晰接口边界。每个角色契约指定:
- 必须读取的上游输入
- 必须生成的下游制品
- 提出阻碍的条件
- 升级到PM路由的条件 这将智能体从"长角色提示词"转变为具有严格I/O边界的稳定模块,这对长期维护和模型更换至关重要。
- 工作流验证脚本 我们如何确保定义文件和契约保持同步?我们添加了一个轻量级验证脚本,检查:
- 所有引用的定义文件是否存在?
- 所有智能体契约是否存在?
- 工作流中的角色是否正确映射到契约? 它还不是完整的"工作流编译器",但它能捕获那些悄然腐蚀多智能体流水线的低层同步漂移。
结果:工作流从"被人类记住"演变为"被拆分、维护和验证为工程基础设施"。
7.7 回顾:这段迭代之旅证明了什么
串联第五到第七章揭示了单一叙事:
- 第5章:为什么选择这条架构路线?
- 第6章:如何沿这条路线拆分角色?
- 第7章:拆分后如何通过真实的摩擦稳定系统?
核心要点:Harness工程不是通过预先设计一个完美系统来增长的。它通过从最小开始、运行、遇到真实的生产问题、迭代修补结构、边界、门槛和反馈循环来增长。
如果你在为自己的项目构建Harness,不要试图在第一天就蓝图化最终状态。现实的路径是:
- 找到你最大的痛点。
- 修补最关键的层。
- 让它运行起来。
- 通过现实加强它。
这就是实际部署的样子。
7.8 推荐的最小启动序列(从零开始)
前面的部分涵盖了完整的演进。以下是如何将其压缩为适合你自己项目的实用、逐步路径:
- 首先锻造一个扎实的SPEC。不要急于规则或智能体。与AI迭代直到目标、边界、验收标准和兼容性要求都清晰明了。没有这个,下游的一切都在漂浮。
- 只添加关键规则。聚焦于AI持续失败或偷工减料的底线(如编译→测试→验证)。不要在第一天就写50条规则。
- 将高频固定动作沉淀为技能。当你注意到AI在重复性、易出错步骤上即兴发挥时,将其编码化。编译、测试和验证通常是最先的候选。
- 只有在单智能体失稳时才拆分为多智能体。如果任务简短、链路浅,一个智能体就好。只有当角色开始模糊或自我评估失灵时才拆分为需求、设计、开发、审查和测试。
- 随着复杂性增长添加工作流定义和角色契约。长提示词在早期有效。一旦阶段、回滚和交接倍增,就提取为结构化的、版本控制的资产。
- 在持续迭代期间添加Dev-Map和任务板。这解决了"AI如何理解整个项目,而不仅仅是当前任务?"代码库越大,这一层越关键。
- 只有在向外推送循环时才考虑MCP。先关闭内部开发循环。然后才连接到外部构建、签名、发布和制品系统。不要在第一天就连接整个世界。
演进很简单:告诉AI做什么→告诉AI怎么做→教复杂任务的分工→将工作流本身变为可维护的工程资产。
PM智能体(编排器)按照工作流顺序调用每个子智能体:需求→设计→开发→审查→QA→关闭。
- 左侧面板:时间线追踪哪个智能体被调用、何时完成、哪里发生了回滚/重跑。
- 右侧面板:我与PM的直接对话,镜像左侧的执行步骤。
8、为什么最终落脚于脚本——特别是主验证脚本
第七章已经触及了一个残酷的事实:当规则开始失效、智能体开始找借口、"历史债务"成为方便的借口时,约束不可避免地深入到可执行脚本中。
我不会在这里重述那个演进路径。相反,我将纯粹聚焦于核心论点:为什么主验证脚本成为整个Harness中最关键的基础设施之一。
在我们的项目中,这不是一个礼貌的建议说"请验证你的工作"。它是开发是否真正完成的客观的、不可商量的裁判。
8.1 主验证脚本实际上做什么
它不是一个单一的检查。它是一个统一的后开发验证网关。
把它想象成一个中央裁判,按顺序运行:
- 静态lint和约定检查
- 编译
- 测试套件执行
- 依赖和清单同步
- 项目结构验证
它整合了几十个以前分散在规则中的检查。在实践中,它们分为三个清晰的类别:
类别A:静态规范和约定
- 使用硬编码的密钥/字符串而不是
config/env包 - 使用
fmt.Println而不是结构化日志器(slog/zap) - 缺少错误上下文包装(
fmt.Errorf("...: %w", err)) - 命名不一致或导出API违规
- 缺少
//go:build约束或构建标签文档 - 许可证/头文件合规、文件长度限制、尾随空格
类别B:交付门槛
go build -v ./...必须零错误通过go test -race -timeout=30s ./...必须100%通过- 测试数量不能异常下降(捕获被删除的覆盖率)
- 覆盖率必须达到或超过项目基线
类别C:工程一致性
go.mod/go.sum与实际导入完美同步(go mod tidy差异为零)- 生成的文件(
mocks/、proto/、deepcopy/)未被提交 - 所有新的
.go文件被正确引用在构建目标中 - 没有遗留的测试文件或死代码
单独看,每个检查都很微不足道。合在一起,它们形成一个客观门槛,定义了"这个开发是否真正合格?"
更重要的是,后验证是赋予Harness"结果感知能力"的缺失环节。没有它,许多团队会陷入一个危险的模式:他们构建了自动推进任务的AI工作流,但缺乏坚实的反馈机制。结果是什么?
- AI标记任务"完成"。
- 文档生成了。
- 代码修改了。
- AI甚至声称"我已经在本地验证过了"。
但系统本身对输出是对、是错还是表面完成零感知。
后验证解决了这个问题。它不是让工作流看起来整洁。它是给Harness第一次真正判断结果的能力。从这一步开始,我们的系统不再只是一个"任务推进器",而开始成为一个"结果验证器"。
8.2 为什么这一步对Harness至关重要
因为从这一刻起,AI对"完成"的定义发生了根本转变:
从:"我觉得我完成了。" ✅ 变为:"脚本通过了。因此,我完成了。"
这是一个巨大的质变飞跃。它消除了谈判、找借口和主观解读。完成不再是声明;它是一个系统可验证的状态。
8.3 为什么它成为统一入口
主验证脚本的真正威力不仅仅是"添加另一个工具"。它是将碎片化的检查整合到一个单一的、权威的门槛中。
在此之前,验证到处都是:
- 规则中的一行模糊描述
- 埋在技能中的一个步骤
- 一个智能体的自我报告的关闭消息
- 维护者脑中的隐性知识
一旦所有东西都通过主验证脚本路由,"完成"的定义急剧收紧:
- 不是"我说我完成了"。
- 不是"我通过了某个本地检查"。
- 而是"我通过了统一验证网关"。
这对Harness工程至关重要。只有当"完成"被统一定义时,系统才从"一组松散的约束"转变为"一个有门槛的工程工作流"。
如果我必须挑选整个Harness中最被低估但ROI最高的模块,那就是后验证。它不只是添加了一个步骤;它关闭了整个反馈循环。
在这个循环存在之前,我们经常活在"任务完成幻觉"中:AI修改了代码、移动了卡片、生成了文档,我们潜意识里假定成功了。但进展≠正确性。前进≠闭环。做了≠做好了。
一旦后验证成为硬门槛,Harness发生根本性变化:
- 它不再只是一个驱动AI前进的系统。
- 它成为一个判断结果的系统。
- 它形成了一个完整的、自我纠正的回路:
执行→验证→发现问题→回滚/修复→重新验证。
那才是Harness真正成熟的标志。它不再依赖希望,而是依赖物理法则。
9、如何给AI"项目级记忆"
到目前为止,我们的Harness可以独立处理复杂的多阶段需求。但一旦项目进入持续迭代,一个高度实用的瓶颈就出现了:
PM和各个智能体缺乏对整个项目的全局视图。
如果你只在上下文窗口中输入当前任务规范,两个常见的灾难会迅速随之而来:
- 新实现会默默覆盖或忽略现有架构。
- AI重新发明轮子,完全不知道一个健壮的、经过测试的实现已经存在。
这一章正好解决这个问题。大致来说:我们给AI一个存在于仓库内部的项目级知识索引。关键是,这不是一个"百科全书"——把整个代码库手册倒进上下文窗口。它是一个精确的索引——一张地图,告诉AI在深入实际代码和细节之前应该检查哪些入口点和遵循哪些约定。
维护哲学:我们的目标是AI自维护。谁修改了代码就更新地图;谁管理需求就更新任务板。这消除了"美丽的文档但从来没人更新"的经典陷阱。
在我们的项目中,这转化为两个核心组件:dev-map和任务板。这也与第一章的上下文纪律完美契合:当项目还很小时,不要一开始就倒出完整的地图和任务历史。等到持续迭代开始。那时ROI才会变得明显。
前面的章节构建了流程上下文。这一章构建项目上下文——版本控制的、可见的和持续更新的。
9.1 构建"项目级索引"的常见方式
不同团队使用不同的材料来达成相同的目标。这些并不互斥;它们通常是分层堆叠的。我们使用的dev-map和任务板只是我们的特定实现,不是唯一答案。
9.2 dev-map:开发侧导航图
在主项目下,我们维护一个开发导航图,有一条严格的规则:
在修改代码之前,检查dev-map。在切割之前,根据地图验证功能落点和影响范围。
许多人假设dev-map只是一个"文件列表"。它的价值更广:它是工程导航指南。它回答:
- 某些功能通常在哪里?
- X类型的服务如何集成?
- 配置通常在哪里定义?
- 修改模块Y会影响哪些链路?
- 这里的标准实现模式是什么样的?
核心规则:在编写代码之前先理解现有格局。AI喜欢"重新发明轮子";地图确保它看到这座城市不是一块空地。
维护:由开发智能体在实现期间维护,而不是PM。谁改变了地形谁就更新地图。 这符合我们的AI闭环更新逻辑。
大型仓库的扩展: 当文件倍增时,一个试图列出所有内容的单表就会成为负担并逐渐不同步。实际的妥协方案:保留几个顶级概览页(入口点、主要领域边界)。当深入特定领域时,参考该领域的专属表。具体的类/路径由搜索/LSP处理。dev-map聚焦于结构和约定。将一张巨大的地图拆分成几个聚焦的小册子(每个标注其领域)比强制一本厚目录要现实得多。
9.3 任务板:需求侧概览
另一个关键组件是项目任务板,由PM维护。它不是一个简单的待办清单;它是一个项目级任务注册表,追踪:
- 活跃任务
- 每个任务的当前阶段
- 关联的文档目录
- 已完成任务的结果结论
当一个新的需求智能体加入时,它不是从零开始猜测。它检查任务板来回答:
这是旧需求的延续吗?我们做过类似的吗?文档在哪里?之前的设计决策是什么?
"新需求覆盖旧设计"的风险显著降低。
dev-map处理代码和模块结构的入口点。任务板处理需求和任务历史的入口点。两者都存在于仓库中,由各自的工作流中的智能体更新。这就是这一层保持活力的方式。
9.4 结语
这一章不是关于工具名称。它是关于一种能力:
AI不仅应该完成当前任务,还应该知道如何在仓库内找到"阅读整个项目的钥匙"。
当这种能力锁定时,你的Harness就不再在孤立的冲刺中运行,而是开始像一个有长期记忆的团队一样运作。那时持续迭代才变得可持续。
10、在团队级Harness中,为什么"记忆"退居二线
当你读到第九章时,你已经看到dev-map和任务板如何充当项目的长期记忆。这自然引出了一个问题,在AI智能体圈子里被广泛争论:
如果我们正在构建一个严肃的、多智能体的、团队级的Harness,我们还需要专门的"AI记忆"系统吗?向量数据库?情景回忆?对话历史保留?持久化智能体状态?
简短回答:不需要。在成熟的Harness中,传统AI记忆可以安全地退居二线。
不是因为记忆没用。而是因为一个良好结构的Harness用"记录"的系统替代了AI"记忆"的需求。
10.1 我们所说的"AI记忆"究竟是什么
当业界谈论"AI记忆"时,通常指的是:
- 上下文窗口保持:在会话间保持过去的对话轮次。
- 向量/RAG记忆:存储过去交互的嵌入以供以后检索"相关"历史。
- 智能体记忆模块:情景(发生了什么)、语义(存在什么事实)、程序(如何做事)。
- 持久化状态文件:智能体决策、工具调用或聊天记录的JSON日志。
所有这些都解决了一个真实问题:LLM默认是无状态的。一旦上下文窗口关闭或会话重置,它们就忘记一切。
在单人、实验性或对话式AI设置中,记忆通常是保持连续性的粘合剂。但在团队级工程Harness中,将其作为核心依赖引入的摩擦大于它解决的问题。
10.2 为什么AI记忆在生产中变成负担
简而言之:AI记忆优化的是对话连续性。工程工作流优化的是可审计的、版本化的、可复现的状态。它们是根本不同的目标。
10.3 Harness如何用工程制品替代AI记忆
Harness不让AI记忆。它让项目记忆。以下是映射关系:
转变是微妙但关键的:不是要求AI"记住三个会话前我们讨论了什么",而是要求它"阅读当前的SPEC,检查任务板阶段,加载dev-map入口点,执行工作流定义"。
AI不需要记忆。它需要导航。
10.4 真正的分歧:对话记忆 vs 工作流记忆
这不是说记忆死了。它是说当你从"AI助手"跨越到"工程系统"时,记忆的角色会发生巨大变化。
当你的Harness达到多智能体、多阶段、持续迭代时,如果记忆是主要真相来源,它就变成了负担。无论AI是否"记住"了什么,系统都应该以相同的方式工作。
10.5 核心要点
追逐"AI记忆"作为银弹是一个常见的陷阱。它感觉像是进步,因为它模仿了人类协作:"我们上周讨论过,所以应该从上次停下的地方继续。"
但工程不靠对话运行。它靠记录运行。
成熟的Harness不要求AI记忆。它要求AI:
- 阅读当前的规范
- 遵循工作流定义
- 加载正确的dev-map入口
- 执行验证脚本
- 更新任务板阶段
- 提交并附上清晰的说明
如果AI在会话重启的那一刻忘记了所有东西,Harness仍应完美运作。这就是试金石。
记忆不是基础。制品才是。当你的项目记忆存在于git中,而不是向量数据库或聊天日志中,你就已经从"AI实验"跨越到了"工程系统"。
而这正是Harness工程应该存在的位置。
11、Harness的全貌——四个拼图如何协同工作
这一章纯粹作为一个回顾地图:第三到第七章向你展示了*"如何让AI在边界内工作";第八章涵盖了"谁来评判结果";第九章解释了"如何进入这座工程城市";第十章聚焦于"人类、项目和AI各自站在哪里"*。
11.1 四个拼图与章节映射
这不是唯一的切分方式,但它为我们构建的叙事提供了一个参考地图。
11.2 拼图一:约束与工作流(第三到第七章)
从规则和技能开始,通过多智能体编排、工作流定义文件和角色契约推进,然后进入第七章的迭代式*"撞墙补洞"*循环——整个线索根本性地回答了:AI在工程中按什么节奏和纪律推进?
没有这一层,即使最强的模型也只是在对话中即兴发挥。有了它,复杂需求分解为可重复的接力赛,每一棒都有明确的输入和输出。第七章修补的缝隙(文档边界、回滚机制、维护协议)本质上是工作流本身的硬化:防止协作退化为"口头约定和拍脑袋"。
11.3 拼图二:反馈(第八章)
约束告诉AI*"它应该如何表现"*。反馈回答:"产出是否真的通过了?"
第八章将主验证脚本推到中心舞台,实现了第一章埋下的伏笔:规则是软的、可遗忘的、容易被选择性执行。最终你需要一个机器可强制执行的门槛来做最终裁决。
一旦反馈接入了,Harness首次获得了结果感知能力。仅仅工作流完成还不够;同一个客观门槛适用于每一次交付。第十章后来提到的*"进一步将规则脚本化"和"将反馈循环向外扩展"*就是这块拼图在变得更厚、更有能力。
11.4 拼图三:知识库(第九章)
第九章阐明了项目级上下文:不是让AI阅读的无尽百科全书,而是一个精确的索引。开发通过dev-map进入;需求和任务历史通过任务板进入。在工作流中挥刀的人也在工作流中更新地图。这防止了AI在一座已经建好的城市中反复铺路。
这一块与约束和工作流有具体的关系:
- 工作流规定何时读取地图
- 地图减少在错误位置工作的概率
- 反馈在地图过时或遗漏更新时施加维护压力,利用失败结果强制纠正
11.5 拼图四:演进(第十章)
第十章对记忆的讨论从根本上说是关于划定主场:团队需要对齐的事情最终必须作为可见的、可审计的、可交接的资产落地到仓库中——而不是停留在会话记忆里。它对人类和AI的讨论是关于责任上移的:人类越来越成为系统架构师和最终责任承担者;AI在制度框架内密集执行。Harness本身随着项目变得更难、团队规模扩大而持续演进其结构、添加门槛、扩展链条。
所以演进不是玄学。它是这样的:一旦前三个拼图组装好了,人类和AI在各自边界内协作驱动持续的重构。人类设定方向和门槛;AI在规则内以高密度交付。哪些规则应该变成脚本?哪些地图应该拆得更薄?哪些工作流段应该连接到MCP?这些成为可审计的仓库变更,循环回来提升工作流、反馈和知识库。
11.6 四个拼图如何互锁
四个拼图相互强化。缺少任何一个都会产生明显、可预测的症状:
让我进一步澄清演进:它不是模糊的"项目应该写文档"。它是人类和AI共同驱动Harness自身重构的力量。人类决定"通过"是什么样子、什么可以自动化、什么时候提交到仓库。AI在已建立的工作流和契约内以高密度交付(修改规则、添加验证脚本、拆分dev-map、更新任务板)。这些变更循环回来提升前三个拼图:
- 约束与工作流变得更加贴合现实
- 反馈门槛变得更准确或覆盖更广
- 知识库与最新结构保持同步
缺少这一层,常见的结果是:只有少数人记得为什么做出了某个决定,或者每一轮都依赖临时聊天方向。前三个拼图得不到结构性的向上推力。
11.7 核心愿景
总而言之,Harness工程的核心图景是:
使用工作流和约束将行动置于轨道上。使用反馈确保轨道末端有人评判结果。使用知识库防止AI在城市中盲目横冲直撞。
演进是人类和AI合力将实践和门槛的结论持续注入工作流/约束、反馈和知识库——确保规则、门槛和地图跟上结构变化的步伐。
只有这样,整个系统才能真正与项目共存并共同成长。
12、结束语
这个系列不是关于在第一天构建一个完美系统。它是向你展示演进路径:从最小可行约束开始,遇到真实的生产墙壁,系统性地修补,让Harness通过摩擦有机增长。
如果你只能带走一件事,就让它是这个:
Harness工程不是关于控制AI。它是关于构建一个工程系统,在这个系统中AI成为可预测、可审计和可持续的增效力量。
工具会变。模型会改善。但原则不变:
- 约束先于自由
- 反馈先于信任
- 索引先于百科全书
- 演进先于完美
现在去构建你自己的Harness吧。从小开始。撞墙。补洞。迭代。
原文链接:How To Implement Harness Engineering
汇智网翻译整理,转载请标明出处