跳到主要内容

Harness 工程

再强的模型,没有合适的工作环境,在真实工程任务上也会失败。问题不在模型,在环境

Harness Engineering 是围绕模型构建完整工作环境的工程实践——让 AI 编码智能体在长周期、复杂任务上稳定产出可运行、可验证、可维护的结果。

The model is smart. The harness makes it reliable.

核心命题

AI 编码智能体的失败模式高度集中——而且几乎都不是模型问题:

  • 任务完成率低:智能体跳过步骤、破坏测试、声称完成但实际不工作
  • 上下文丢失:多会话之间无记忆,每个新会话从零开始
  • 过早宣布胜利:写完代码,单元测试全绿,但集成测试没跑、端到端流程没演练
  • 过度扩展:让智能体"加用户认证",它会顺手改错误处理、改目录结构、引新依赖
  • 不可维护性:临时调试文件没删、测试是红的、构建失败,下个会话花 30 分钟"搞清楚上次到底干什么了"

同一款顶级模型,无 harness 跑出来的产品不工作;配齐 harness 后产出可运行游戏。模型没变,环境变了。

五个子系统

Harness 由五个相互配合的子系统组成。每个子系统解决一组特定的失败模式。

Instructions(指令)

解决:上下文丢失——智能体不靠"读心"理解项目,只能读你给它的文件。

  • AGENTS.md 放在仓库根目录,50-200 行,是 router 不是 encyclopedia——告诉智能体"项目是什么 / 怎么跑 / 硬约束是什么",并指向专题文档
  • 超过 200 行的内容拆到 docs/ 目录,按需加载
  • 硬约束单独列在入口文件首部——LLM 对长文本中间的内容利用率显著低于首尾,重要规则不能埋在中间
  • 每条规则注明来源、适用条件、过期条件,定期审计删除过时约束

反面:把 600 行规则塞进一个 AGENTS.md,安全约束埋在第 300 行被忽略,三条互相矛盾的代码风格规则让智能体随机挑一条执行。

Tools(工具)

解决:工具被过度限制导致智能体什么都干不了。

  • 原则:最小权限,但不是零权限。不要为了"安全"把 shell 关掉——智能体连 pip install 都跑不了,怎么工作
  • 工具配置记录在入口文件:"环境用 npm 而非 yarn"、"用 Makefile 而非 npx 直调"
  • 工具版本固定,让智能体在哪个机器上跑都有相同环境

Environment(环境)

解决:环境不一致是隐性 bug 的最大来源——测试环境里写好代码,到生产环境跑不起来。

  • pyproject.toml / package.json 锁依赖
  • .nvmrc / .python-version 指定运行时版本
  • Docker / devcontainer 让环境完全可复现

State(状态)

解决:长任务一定跨多个会话,跨会话无记忆 = 每次都从零开始。

  • PROGRESS.md:已完成 / 进行中 / 下一步 / 已知阻塞
  • DECISIONS.md:重要设计决策的"为什么",避免下次重做决策
  • 每个逻辑操作 = 一次 git commit,失败用 git stash 回滚(Atomicity)
  • 操作后跑验证,确保系统处于可验证状态(Consistency)
  • 多智能体并发时用独立 progress 文件或 git branch 隔离(Isolation)
  • 关键知识必须落盘到 git 跟踪的文件,只存在脑子里不算(Durability)

文件交接模式

上下文要通过文件流转,而不是靠人脑、聊天历史或复制粘贴维持。 当一个 AI 任务开始跨步骤、跨信源、跨会话时,提示词本身就不再是主要瓶颈。真正的瓶颈变成:上一步产出的信息,能不能以稳定、清晰、可追溯的方式交给下一步。

文件交接模式的基本做法很简单:每一步只做一件事,把结果写入一个明确命名的文件;下一步读取这个文件,而不是要求人把上一轮输出复制到新对话里。这样上下文从“聊天窗口里的临时文本”变成“文件系统里的持久状态”。出问题时,可以直接打开中间文件,沿着链路追溯偏差从哪一步开始。

一个研究类工作流可以这样拆:

  • source-a-findings.md:第一个信源的发现、链接、关键摘录和不确定点。
  • source-b-findings.md:第二个信源的发现、链接、关键摘录和不确定点。
  • source-c-findings.md:第三个信源的发现、链接、关键摘录和不确定点。
  • synthesis.md:只读取前面几个文件,综合出结论、候选方向和待验证问题。

这种结构让每一步拿到的上下文更干净。模型不需要在一段越来越长的对话里寻找关键信息,也不需要依赖人来提醒“第三步需要第一步的什么”。每个文件都是一个稳定接口:前一步负责写清楚,后一步负责读取和继续加工。

Markdown 是最朴素也最可靠的交接格式。它是纯文本,能被 Git 版本管理,能被人直接阅读,也能被 AI 直接读取。复杂系统当然可以使用数据库、队列或状态服务,但很多个人和小团队工作流,先用文件夹加 Markdown 就足够。不要为了“显得工程化”过早引入复杂状态机制。

文件交接还有一个隐藏价值:它逼迫每一步定义清楚输入和输出。只要某一步说不清自己读什么、写什么,它就还不是一个稳定的工作流节点。Harness 的状态系统,本质上就是把“我记得我做过什么”改造成“系统能读到我做过什么”。

交接文件要能支持追溯。文件名最好直接表达步骤和内容,例如 reddit-findings.mdnews-findings.mdarxiv-findings.mdidea-angles.md,不要用 result.mdfinal.md 这类含混名称。每个文件至少写清楚来源、任务、关键发现、不确定点和下一步可用信息。终稿看起来不对时,可以沿着这些文件往回找:是哪一步漏了来源,哪一步把弱证据当成强结论,哪一步开始偏离目标。

格式可以朴素,但接口要稳定。一个步骤如果承诺输出“来源、摘要、相关度、风险”,下一步就应该依赖这些字段,而不是依赖上一轮聊天里的自由发挥。工作流真正稳定后,提示词可以很普通,因为上下文是干净的;反过来,再好的提示词放在臃肿混乱的长对话里,也会产出平庸结果。

Trace 化工作流

AI 使用能力拉开差距的地方,通常不在“装了多少工具”,而在能不能持续改进自己使用工具的流程。工具会很快变成基准线:别人也能开会员、装插件、调用模型。真正能复利的是工作流本身能被记录、分析、修改、复跑和升级。

传统 PDCA 在 AI 工作流里最容易断在记录。一次和 Agent 协作跑通了开源项目调研、简历修改、广告分析、漏洞扫描或 bug 修复,当时感觉很顺,过几天只剩一段聊天记录。没有步骤文件、输入输出、依赖关系和验证结果,就无法知道哪一步有效、哪一步只是碰巧成功,也无法把这次经验迁移到下一个任务。

Trace 化工作流就是把一次成功或失败的 AI 协作变成可复跑的过程资产。它不只保存最终结果,还保存节点、输入、输出、依赖、来源、验证和历史:

  • 节点:这一步做什么,读什么,写什么。
  • 输入:用户提供的目标、文件、链接、代码、数据或上一步产物。
  • 输出:结构化文件,而不是只停在聊天消息里。
  • 依赖:下一步依赖哪些上游节点,改动某一步时哪些后续节点需要重跑。
  • 来源:每个关键结论能回到原始文件、网页、代码或数据。
  • 验证:这一步是否达标,用什么命令、规则或人工检查点判断。
  • 历史:每次复跑和修改都进入版本记录,方便比较和回滚。

这样 PDCA 才能真正发生:

Plan:把任务拆成节点和验收标准
Do:按节点执行,每步产出文件
Check:查看 trace、diff、验证结果和失败节点
Act:只修改有问题的节点,保留有效部分,再换输入复跑

Trace 的价值在复用时最明显。比如第一次调研一个开源项目时,流程可能只看 README、文档、示例和竞品;换第二个项目复跑,才发现缺少项目健康度检查:维护频率、issue 积压、release 节奏、社区活跃度、依赖风险。把这个节点补进 trace 后,第三次调研就不再靠临时想起。流程被改进了,而不是人靠记忆变勤奋了。

Trace 化工作流适合几类任务:步骤相对固定、会反复出现、每次输入不同、结果需要可信来源、失败后能定位到具体环节。研究、尽调、代码审查、开源项目评估、安全扫描、内容生产、广告复盘、简历优化都符合这个特征。一次性闲聊、纯创意发散、极短小的临时脚本,则不必做成 trace。

落地时要避免把 trace 做成漂亮流程图。图只是阅读界面,真正重要的是文件和依赖是否可靠。一个好 trace 应该能做到:人可以打开任意节点看输入输出;Agent 可以从中断处继续;修改一个节点后,只重跑受影响的下游;换一组输入后,整条流程能复用;发现失败后,能把经验沉淀回 Skill、检查清单或验证命令。

Feedback(反馈)

解决:置信度偏差是客观存在——LLM 系统性地比实际能力更自信,智能体说"完成了"不能算数。

  • 列出三层验证命令——语法/静态分析、运行时行为、端到端系统级,缺一不可
  • 错误消息告诉智能体怎么修:不要说"Test failed",说"POST /api/reset-password returned 500. Check that the email service config exists in environment variables."

这是回报最高的子系统——投入最低、效果最显著。

核心文件

文件用途
AGENTS.md / CLAUDE.md入口文件,承载 Instructions 子系统的核心指令 + 路由到专题文档
feature_list.json机器可读的功能列表:每个条目是 (行为描述, 验证命令, 当前状态) 三元组
init.sh初始化脚本:环境安装、依赖验证、健康检查
PROGRESS.md跨会话进度持久化
DECISIONS.md重要设计决策的"为什么"
docs/专题文档目录,按需加载
git log变更记录 + 回滚点

核心架构模式

用 Skill 和插件补齐模型差距

模型能力决定上限,Harness 决定真实可用性。一个开箱体验很强的模型,通常已经内置了大量隐性工作流:什么时候该问人、什么时候该直接做、怎么调用工具、怎么组织输出、怎么从失败中恢复。一个基础模型即使参数能力接近,如果缺少这些外部结构,使用体验也会显得笨、啰嗦、犹豫和不稳定。

这也是 Skill 和插件的价值。Skill 承载专业经验,告诉 Agent 做某类任务时该按什么流程走、检查什么、输出什么、不做什么;插件承载外部能力,让 Agent 可以连接会议转写、Slack、Notion、CLI、代码仓库、数据库和各种 API。模型负责理解和生成,Skill 负责流程和判断标准,插件负责真实世界的动作入口,Harness 负责把三者放在可验证、可回滚、可审计的环境里。

评价一个模型能不能承担真实工作,不能只看 benchmark 或单轮回答质量。更有意义的问题是:把它放进同一套 Harness、给同一份 Skill、接同一组插件、跑同一个任务,它能不能稳定完成。很多看起来是“模型不够聪明”的问题,实际是任务没有结构化:步骤没有写清楚,工具没有封装好,失败没有反馈,输出没有验收标准,关键动作没有决策门。

一个轻量实践路径可以这样走:

  1. 选一个反复发生、价值明确、风险可控的任务。
  2. 先用人类自己的做法写第一版 SKILL.md:输入是什么、步骤是什么、什么时候需要问人、输出格式是什么、验收标准是什么。
  3. 判断这件事需要哪些外部动作。能靠现有工具完成就配置工具;需要稳定复用的能力,就封装成插件或 CLI。
  4. 用强模型打磨 Skill,把模糊表达改成可执行规则,把容易漏掉的边界补进去。
  5. 切换到目标模型,用同一份 Skill 和插件跑同一任务,记录它在哪一步啰嗦、犹豫、误判、遗漏或越界。
  6. 把失败反馈回 Skill、插件和验证规则,而不是只在下一轮对话里口头提醒。
  7. 跑到稳定后,再把这套能力迁移到下一个相邻任务。

比如,一个个人助手要从会议里自动捕捉待办,不能只给它一句“帮我看会议纪要”。更稳定的做法是:会议结束后自动读取转写文本;判断是否出现明确指派、承诺、问题或跟进事项;低置信度事项放入待确认列表;高置信度事项生成 Notion 页面或任务草稿;需要人答复的内容按轻重缓急推送到消息工具;所有对外动作停在 held draft 或 approval gate 前。这个能力看起来像“助手更聪明了”,实际是 Skill、插件、触发器、状态和权限一起工作。

再比如,让 Agent 成为 CLI 工具专家,也不应该每次从零提示“请帮我写一个 CLI”。应该沉淀一个 meta-skill:如何选择命令结构、如何处理认证、如何设计配置文件、如何写错误消息、如何生成 README、如何补测试、如何发布。第一次做的是一个具体 CLI,第二次沉淀的是“以后如何做 CLI”的流程资产。下一次再建类似工具时,Agent 读取的是稳定流程,而不是重新消耗大量上下文去猜最佳实践。

主动型助手同样依赖外部结构。一个定时脚本只会按时间触发,一个可协作的助手需要消息分级:静默记录、普通知会、需要回答、紧急处理。没有这层路由,Agent 要么不停打扰人,要么把重要事项埋在日志里。消息分级本质上是把人的注意力也纳入 Harness:哪些信息只存档,哪些信息进入 inbox,哪些信息需要立即推送,哪些动作必须等人批准。

这套方法的关键判断是:不要把所有差距都归因给模型。模型当然重要,但真实工作里的体验差距,往往来自模型周围有没有专业经验、外部工具、状态管理和验证反馈。便宜模型加好 Harness,可能胜过昂贵模型加松散提示词;强模型加好 Harness,才会真正接近可交付系统。

从 Prompt 到 Workflow

当你开始手工协调 AI 的多个输出时,就应该从 Prompt 转向 Workflow。 单次对话适合探索问题、生成初稿、做一次性分析;重复任务、长链任务和多信源任务,更适合被拆成工作流。继续优化提示词,只是在错误层面上做局部改良。

识别工作流候选,可以看几个信号:

  • 你需要在多个聊天窗口之间复制粘贴。
  • 你需要反复提醒 AI 之前的目标、约束和中间结论。
  • 你因为上下文污染而主动开新会话。
  • 每一步输出单看都不错,合成后的结果却很一般。
  • 你需要记住后续步骤依赖前面哪一段信息。
  • 你每次做同类任务,都在重复同样的搬运、整理、合并和检查。

这些信号说明你正在做人和 AI 之间的中间件。AI 能完成每个局部步骤,但你在承担流程编排、上下文传递和结果合成。这个时候要优化的是任务结构:把大对话拆成多个小节点,让每个节点有清晰输入、清晰输出和明确边界。

长对话里的“接缝”就是工作流的切分点。每次你说“接下来做 X”、把前面某段复制到新请求里、开一个新会话避免上下文污染、提醒 AI 第一阶段发生过什么,都是接缝。接缝处最容易发生 scope creep:任务目标悄悄换了,前一步的重要信息被忘了,后一阶段依赖了未经确认的假设。把这些接缝显式写成节点,工作流才开始稳定。

识别第一个工作流候选时,不要选最复杂、最炫的任务。选一个每周都发生、步骤大致固定、每次都让你复制粘贴到厌烦的任务。它最好只有两三步,能用一个文件夹承载交接物,并且有一个清楚的人工检查点。第一个工作流的目标,是先跑到“无聊但可靠”,架构能力以后再逐步增加。

最小可用工作流只需要四个部分:

  • 输入:这一步读取什么,来自用户、文件、网页、数据库还是上一步结果。
  • 指令:这一步要做什么,边界是什么,不做什么。
  • 输出:这一步必须产出什么文件、字段、列表、判断或报告。
  • 检查点:什么情况下需要人确认,什么情况下可以自动进入下一步。

第一版工作流应该尽量朴素。不要一开始就上复杂框架、可视化编排和多 Agent 调度。先从一个每周反复发生、步骤清楚、手工搬运明显的任务开始,拆成少数几个节点,用文件交接跑通。等这个简单版本稳定后,再考虑并行、路由、评估器和自动调度。

这种迁移的关键心态是:Prompt 解决“这一轮怎么说”,Workflow 解决“这类事以后怎么稳定发生”。前者是一次性表达,后者是可复用系统。

WIP=1

一次只做一件事,做完端到端验证再开下一个。

智能体天然倾向多任务,"也顺便修一下"对模型零成本但对注意力是真实稀释。Little's Law:WIP 越大、Lead Time 越长、完成率越低。

例子:让智能体"加用户注册"。WIP=1 时它只做用户注册,做完跑端到端测试 100% 通过。无约束时它顺手改邮件服务、bcrypt、错误处理——6 步后每个都半成,没有端到端能跑通的。

数据:8 个功能的 REST API 项目,无约束模式 3 个会话后 5/8 完成(37.5%);WIP=1 模式 4 个会话后 7/8 完成(87.5%)。代码总量反而更少(800 行 vs 1200 行)。

双轨开发

AI 编程的瓶颈通常不在实现 Agent 数量,而在规格和验证这两个需要人参与的环节。 同时开十个编码 Agent,看起来并行度很高,但如果人只能一次澄清一个需求、一次 review 一个结果、一次判断一个 UX 取舍,系统吞吐量仍然被人的注意力限制。更稳的结构是两条轨道交替推进:一条规格轨,一条实现轨。

规格轨 负责把模糊想法磨成 Agent 可以独立执行的输入。它从几句话的功能想法开始,经过提问、阅读代码库、澄清用户场景、补齐边界、列出验收标准,最后形成功能规格、技术设计和工程任务拆分。规格轨需要人的持续注意力,因为这里要决定做什么、为什么做、哪些不做、什么算成功。这些判断如果前置不清楚,后面的实现并行越多,返工越多。

实现轨 负责把已经明确的规格落成代码、测试和变更说明。它可以比规格轨更自主,因为输入已经足够完整:目标、范围、设计、任务列表、验证命令和排除项都写清楚了。实现 Agent 在执行时不需要人一直盯着;人可以等一个任务完成后 review,也可以等一组任务完成后统一检查。实现轨跑起来后,人把主要注意力转回下一份规格。

这个循环可以这样运行:

规格 A 澄清 → 实现 A 执行
↘ 人开始规格 B
实现 A 待 review → 人 review / 测试 / 调 UX → 实现 B 启动

双轨的价值来自注意力互补。规格轨高频需要人,难以并行;实现轨拿到清晰输入后可以等待和执行,适合放给 Agent 跑。人不应该同时写两份规格,也不应该在没有足够规格输入时启动一堆实现 Agent。真正的并行,是让机器在执行已经想清楚的工作时,人去想下一件还没想清楚的工作。

这也解释了为什么“更多 Agent”常常没有更快。软件开发不是只有写代码,还包括规格、实现、review、功能测试、UI 打磨和发布判断。实现阶段被 AI 加速后,瓶颈会移动到规格和验证。继续堆实现 Agent,只会制造更多待 review 的代码、更多需要人工测试的分支、更多需要产品判断的 UI 细节。队列越长,人的 review 压力越大,反馈周期反而变慢。

双轨适合长期存在的代码。后台系统、生产功能、持续维护的产品、客户会反复使用的流程,都值得先写规格和实现计划。一次性脚本、丢弃型 demo、探索性原型,不必套完整双轨;这类任务可以用更轻的 vibe coding,重点是快速验证方向。

落地时可以给双轨设置几条规则:

  • 规格轨结束前,不启动实现轨。
  • 每份规格必须包含目标、用户场景、范围、排除项、验收标准和验证命令。
  • 实现轨只能按规格执行,发现规格缺口就停回规格轨补齐。
  • 人的并行上限是一个规格轨加一个实现轨,超过这个数量通常只是制造队列。
  • 面向用户的 UX 判断必须回到人,Agent 可以实现界面,但不能替人决定产品品味。

双轨开发和 WIP=1 不冲突。WIP=1 控制每个轨道里的进行中任务,双轨控制人的注意力在“澄清下一件事”和“验收上一件事”之间流动。它让人集中出现在规格、验证和品味这些高价值节点上。

Worker vs Checker 分离

生成者不自评,由独立的"挑剔"评估者打分。

LLM 系统性地比实际能力更自信——同一个模型既生成又评估,会对自己慷慨。

例子:给 app 加暗色模式,三智能体架构(planner + generator + evaluator)用 Playwright MCP 真实点击测试。evaluator 给出"按钮对比度 2.1:1 不达 WCAG AA 4.5:1 标准"——这种具体可执行的反馈,单智能体永远给不出。

数据:单智能体 $9/20 分钟产出不工作;三智能体 $200/6 小时产出可运行游戏。多花 20 倍钱、多花 18 倍时间,结果从"不可用"变"可交付"。

Feature List as Primitive

功能列表是给调度器/验证器/交接报告用的数据结构,不是给人看的备忘。

调度器要读它挑下一个任务、验证器要读它跑对应的验证命令、交接报告要读它生成状态摘要——三个组件都依赖同一个真相源。

每个条目是三元组(行为描述, 验证命令, 当前状态)。状态由 harness 控制迁移——智能体不能自说自话标"完成",只有验证命令跑过才能从 active 升到 passing。

3-Layer Termination

验证分三层,缺一不可:

层次检查什么例子
1. 语法/静态分析代码写对没mypy --strictruff check
2. 运行时行为能跑没pytest tests/、应用启动 + 关键路径执行
3. 端到端系统级真的对没完整用户流程演练、集成测试

层与层之间不能跳过。单元测试系统性地漏掉组件边界缺陷——接口不匹配、状态传播错误、资源生命周期问题——这些只有端到端测试能发现。

例子:在 Electron app 加文件导出功能。单元测试全过,但点导出按钮时文件路径格式错、进度条不响应、大文件内存泄漏。5 个跨组件缺陷,单元测试一个都没抓到,端到端测试全抓到了。

Review Feedback Promotion

每次重复出现的 code review 评论 → 转成可执行检查。

人工 review 的反馈只在当下有效。如果同一类问题反复出现,每次都要人工重复——harness 应该把这些反馈沉淀下来。

例子:"renderer 不能直接 import fs"在多个项目里反复出现。转成可执行检查:

grep -r "require('fs')" src/renderer/ && exit 1 || echo "OK"

错误消息写具体修复步骤,让智能体能自纠正,不用人工每次提醒。

Sprint Contract

编码前先签"这次做啥 + 验收标准 + 不做什么"三件套。

少了这步,生成者按自己理解实现,评估者按自己理解打分,理解偏差导致大量返工。

# Sprint Contract: 暗色模式支持
## Scope
- 修改主题切换组件
- 更新全局 CSS 变量
- 添加暗色模式测试
## 验收标准
- 每个组件的视觉回归测试通过
- 主流程端到端测试通过
- 无 FOUC
## 排除项
- 不处理 print 样式
- 不处理第三方组件的暗色模式

数据:用 sprint contract 跑同一任务,评估者"感觉不对"的情况大幅减少,迭代次数从 3-4 次降到 1 次,整体时间从 45 分钟降到 15 分钟。

Decision Gates

工作流不需要每一步都人工审核,但必须在真正需要判断的地方停下。

很多人把 AI 工作流做坏,是因为走向两个极端:要么完全自动化,直到错误被放大到不可逆;要么每一步都人工确认,把工作流变成连续打断。更好的做法是设置决策门,只在方向选择、公开发布、外部动作、系统变更、成本支出和不可逆操作前暂停。

决策门检查的核心,是输出是否还符合人的意图。AI 可能生成一份格式漂亮、内容完整、逻辑自洽但方向错误的结果。如果下一步继续基于这个错误方向扩写、执行或发布,后续所有努力都会建立在错误前提上。决策门就是在错误前提继续传播之前,把人类判断插回来。

常见决策门包括:

  • 方向门:多个方案里选择哪一个继续。
  • 信源门:哪些材料可靠,哪些只能作为线索。
  • 发布门:内容、代码、消息、邮件是否可以对外。
  • 权限门:是否允许修改系统、删除数据、调用付费资源。
  • 质量门:输出是否达到当前任务的验收标准。

决策门的数量要克制。每多一道门,就多一次上下文切换;每少一道关键门,就多一层错误放大的风险。Harness 设计的关键,是让 AI 尽可能连续执行,让人只停在真正需要判断的位置。

Clean State 5 条件

会话结束前必须留干净状态——5 项缺一不算完成:

  1. 构建通过(npm run build
  2. 测试通过(npm test
  3. Feature list 已更新
  4. 无调试代码残留(console.log、debugger、TODO)
  5. 标准启动路径可用(npm run dev

"清晚再清"等于从不清理,熵增是默认状态。Harness 本身也要定期简化——曾经的必要约束可以随模型升级变成不必要的负担。

Loop 工程:让 Agent 在循环中持续执行

Harness 解决的是"单个 Agent 在合适环境中稳定工作"的问题。但当任务规模和复杂度继续增长,单 Agent Harness 不再足够——需要让多个 Agent 在循环中持续协作的系统

Loop 是 Harness 之上的一层抽象

Harness 是单个 Agent 跑的环境;Loop 是让 Agent 持续运行的编排系统。一次 prompt 只是给 AI 一条指令,AI 回答后停下来等你决定下一步。Loop 则把一份工作交给 AI:目标是什么,怎样判断完成,每一轮失败后怎么修,什么时候必须停止。

这个差异很重要。很多人以为自己在跑 loop,其实只是在手工推动多轮对话:人负责触发、人负责判断、人负责决定下一步。真正的 loop 会把计划、执行、自检、修正和再次执行连成一个闭环。人不需要在每一轮都推一下,但人必须提前定义边界和验收标准。

一个最小 loop 至少包含四件事:

  • 目标:这轮循环要完成什么,不只是"优化一下"这种模糊愿望。
  • 验证:什么结果算通过,由测试、规则、评分表、人工决策门或外部系统给出。
  • 状态:已经尝试过什么、失败在哪里、下一步要做什么,必须能跨轮次保留。
  • 停止条件:成功时停止,达到上限、成本异常、权限越界或连续失败时也要停止。

少了验证,循环只是重复;少了状态,Agent 会反复犯同一种错;少了停止条件,loop 会在人不在场时空转。

五个积木加一个外部记忆

积木作用关键工程问题
Automations定时或事件触发触发频率、异常告警、是否需要人工启动
Worktrees并行隔离防止多 Agent 文件冲突
Skills项目知识沉淀让 Agent 不用每次重新解释项目
Plugins/Connectors外部工具集成让 loop 操作真实环境,而不只给建议
Sub-agentsMaker/Checker 分离让生成、评审和完成判断分属不同角色
Memory(第六件)持久状态文件跨会话保留"做过什么、下一步是什么"

这些部件在 Harness 里已经存在,Loop 让它们进入"持续运行"的状态。 同样的 Skills 在手动调用时是工具,在 Loop 里是被反复执行的程序;同样的测试在手动开发时是检查,在 Loop 里是决定是否继续迭代的 gate。

什么时候值得做 Loop

Loop 工程的诱惑在于:它看起来像把 AI 从"等你推"变成"自己跑"。但并非每个任务都值得进入 loop。一个任务适合 loop,通常要同时满足几个条件:

  • 任务会反复发生。 偶发任务用高质量 prompt 或一次性工作流更合适。搭 loop 的成本需要被多次运行摊薄。
  • 有硬验证或明确评分。 代码测试、构建、linter、schema 校验、固定 rubrics、外部系统状态,都可以把坏结果打回去。没有验证,Agent 只是在给自己批作业。
  • Agent 能端到端行动。 如果每一步都要人复制粘贴、登录、判断或手工搬运,loop 的主体仍然是人,AI 只是局部工具。
  • 完成标准客观。 能用规则、状态、测试或验收清单判断完成,才适合自动迭代。审美、战略、价值取舍这类任务可以让 AI 辅助,但不适合无人值守。
  • 失败有可承受边界。 付费调用、删除数据、对外发送、修改生产系统这些动作必须有权限门和停止条件。

不满足这些条件时,不要急着把事情做成重型 loop。更好的顺序是:先手工跑通一次,再把步骤拆成工作流,接着补验证和状态,最后再考虑自动触发。先证明它能稳定完成,再让它自己跑。

自改进 Loop

Loop 真正有价值的地方,不只是自动重复执行,而是每次执行后让系统留下更好的资产。一次运行结束后,如果只得到一份报告或一段代码,下次仍然从零开始;如果同时留下更清晰的 spec、更稳定的 Skill、更严格的约束和更可靠的验证规则,下一次运行就会站在上一轮之上。

自改进 Loop 可以按这条链路设计:

spec → plan review → parallel run → structured deliverables
→ verify gate → skill promotion → constraints promotion → replay → background agent

第一步写 spec,不写一句话愿望。 Spec 要说明目标、范围、允许来源、禁止来源、输出格式、验收标准、冲突处理和停止条件。对多 Agent 或大规模并行任务来说,一句话 prompt 等于把所有关键判断交给系统猜。Spec 越清楚,后续自动拆解越不容易跑偏。

第二步先审执行计划。 大任务开跑前,应该先看系统如何拆解:多少个子任务、每个子任务做什么、依赖顺序是什么、预算是否合理、最终交付物是否符合需要。计划审查是低成本的方向门。拆解错了再执行,只会把错误放大成大量看似完整的产物。

第三步要求真实交付物。 Loop 的输出不应该只停在聊天窗口里。研究任务要产出报告、数据表、图表、来源清单和不确定项;工程任务要产出代码、测试、变更说明和验证结果;运营任务要产出可执行清单、草稿、通知和审计记录。输出越具体,Agent 越不容易用“综合分析”这类含混结果提前收工。

第四步保留 verify gate。 并行越多,幻觉、漏引、冲突和局部错误越容易混进最终结果。验证者的职责是反驳、挑错、找缺口,而不是再写一遍:哪些结论证据不足,哪些来源互相冲突,哪些格式不符合 spec,哪些动作不能直接沉淀为 Skill。便宜模型适合大规模生成和探索,强验证者适合守住质量门。

第五步把通过验证的流程提升为 Skill。 一次成功运行里真正值钱的,不只是结果,还有“这类任务以后怎么做”。输入格式、拆解方式、输出字段、常见失败、检查清单和决策门,都应该沉淀成 Skill。下次同类任务不再重新设计流程,而是复用已经跑通过的路线。

第六步把验证反馈提升为约束。 验证者指出的问题不能只修当前产物。反复出现的漏引、格式漂移、错误来源、过度推断、权限越界和输出冗余,应该进入项目级 constraints。这样下一轮开始时,系统已经知道上轮踩过哪些坑。

第七步在新输入上 replay。 自改进 Loop 的收益体现在复跑。第一次需要完整 spec、人工计划审查和验证;后续运行应该从 Skill、知识文件、constraints 和历史交付物开始。复跑成本下降,质量上升,才说明 loop 真的在复利。

第八步稳定后再后台化。 当一个 loop 已经有稳定触发条件、可靠输出、明确验证和可控失败边界,才适合变成 background agent。它可以按日程、新文件、竞品页面变化、工单状态或数据异常触发,只把交付物、偏差和需要人判断的问题送进 inbox。

自改进 Loop 的边界也要清楚。这里发生变化的是系统外部记忆,模型权重本身没有被重新训练。Skill、constraints、examples、tests、source lists、decision logs 这些外部记忆,比“模型自己变聪明”更可控,也更容易审计和回滚。

最危险的做法,是把未经验证的一次性经验直接写进 Skill。一次 bad case 可能只是偶发,直接用它改写规则会造成过拟合;一份漂亮但错误的报告如果被提升成模板,会把错误固化到之后每次运行。自改进必须有选择机制:只有通过验证、复跑仍成立、能解释适用边界的经验,才应该进入长期规则。

自改进 Loop 和 Trace 化工作流可以配合使用。Loop 负责自动运行,Trace 负责把运行过程留下来。没有 Trace,Loop 跑完只留下结果,下次仍然难以解释为什么成功或失败;有了 Trace,每一轮都能比较节点输出、定位退化环节、只修改失败节点,并把稳定改进提升为 Skill 或约束。AI 工作流的复利来自这种外部记忆,而不是来自“这次聊得不错”的感觉。

Maker/Checker 分离的延伸

Harness 工程里的 Worker vs Checker 解决的是"生成者不自评"问题。Loop 把这个原则延伸了一步:停止条件也应该由独立模型判断

典型实现:让一个 Agent 写代码,另一个 Agent 评审代码,再让一个独立模型判断"任务是否完成"。写代码的 Agent 不负责评判自己,评判"做完了没"的模型也不读取生成者的自我辩护,而要读取验收标准、测试结果和变更摘要。

这一延伸的关键价值是让 Loop 可以在人不在场时继续运行。如果 Loop 的"完成"判断完全依赖写代码的 Agent,那它会倾向于过早宣布胜利。引入独立的判断者后,Loop 的"做完了"才有意义。

嵌套编排器

当任务步骤变长、工具变多、信源变复杂时,单 Agent 串行执行很容易漏步骤。它会从第一步跑到最后一步,但中途忘记某个工具、跳过某个检查、只读了部分来源,最后输出看起来完整,实际缺了关键材料。研究类任务尤其明显:宏观、行业、公司、产品、技术、舆情、监管这些线索混在一起,单一路径很容易形成早期偏见。

Skill bundling 可以缓解一部分问题:把多个 skill 打包,让子 Agent 批量执行,减少漏工具。但当任务需要多路探索、互相校验和再综合时,更合适的结构是嵌套编排器:

Root Agent
→ Orchestrator A:拆解研究问题、分配子任务、定义输出格式
→ Worker 1:查一类来源
→ Worker 2:查另一类来源
→ Worker 3:做反证或竞品对比
→ Orchestrator A:汇总多路结果,提取共识、分歧、增量和不确定项
→ Checker:根据验收标准判断是否需要补查或交给人决策

这种结构的价值包括并行提速,也包括让不同路径互相校正。一个 worker 可能只看到技术叙事,另一个 worker 可能看到商业约束,第三个 worker 可能发现反例。编排器的任务是比较多份报告:哪些结论互相支持,哪些证据冲突,哪条信息是新增 delta,哪些判断还没有足够依据。

嵌套编排器适合几类任务:

  • 深度研究:多信源、多观点、多阶段综合,单一路径容易偏。
  • 复杂排障:日志、指标、代码、配置、外部依赖需要并行排查。
  • 竞品分析:产品、定价、渠道、用户评价、技术路线要分头读取。
  • 安全研判:情报、资产、漏洞、日志、影响面需要交叉确认。
  • 长链内容生产:资料搜集、事实核查、结构规划、初稿、编辑分属不同角色。

使用嵌套编排器要避免两个误区。第一,不要把所有任务都拆成多 Agent。简单任务拆多层,只会增加成本和合并噪音。第二,不要让编排器只做“汇总者”。真正的编排器要能定义子任务边界、检查 worker 是否按格式交付、识别冲突、要求补查,并把无法判断的问题上交给人。

一个好的 worker 输出应该很克制:

  • 它读了哪些来源。
  • 它发现了什么。
  • 它的置信度和缺口是什么。
  • 哪些内容与其他来源可能冲突。
  • 下一步需要谁继续查。

一个好的 orchestrator 输出应该更像研究备忘录:

  • 多路来源的共同结论。
  • 彼此冲突的地方。
  • 相比已有认知的新 delta。
  • 需要补查的空白。
  • 可以直接进入决策门的问题。

嵌套编排器把“一个 Agent 连续做完所有事”改成“多个角色在同一任务图里协作”。它会增加成本和系统复杂度,但在高价值研究、复杂工程和高风险判断上,质量提升来自这层结构:信息路径更独立,交叉验证更明确,最终综合更有依据。

成本会随轮次增长

Loop 的成本来自每一轮重新读取上下文:目标、代码、上一次结果、失败原因、状态记录和新的修复方案。循环次数增加时,消耗通常不会线性增长,因为上下文也在变长。Maker/Checker 分离能提升质量,同时也意味着更多模型读取同一份材料。

所以 loop 的指标不适合看"跑了多少轮"或"产出了多少东西",更适合看"被采纳的结果花了多少成本"。如果 loop 给出很多看似完整的输出,但大部分被人工丢弃,实际只是把审稿、返工和判断压力转移回人身上。高质量 loop 要减少人的重复判断,避免制造更多待审核材料。

控制成本可以从几个地方入手:限制最大轮次,给每轮设置 token 或预算上限,把简单分类交给便宜模型,把关键判断留给更强模型,把长上下文压缩成结构化状态文件,并且在连续失败时停下来汇报,避免继续尝试。

最危险的失败模式是安静空转:Agent 过早宣布完成,验证又没有能力打回,自动化仍然继续触发。它不会像程序崩溃那样明显报错,只会持续消耗时间、额度和注意力。硬 gate、停止条件和外部监控,就是为这种失败准备的。

Loop 不会让验证消失

Loop 改变工作的形状,不让人从工作中消失。三个问题在 Loop 变好之后反而更尖锐:

验证责任仍在人。 Loop 无人值守运行,也可能无人值守犯错误。Maker/Checker 分离只是让"它做完了"这句话更可信,但"做完了"本身仍是一种声明,不等于证明。上线的代码,必须由人确认它真的能工作。

理解债务会随 Loop 加速累积。 Loop 越快地交付你没写的代码,"项目里有什么"和"你真正理解什么"之间的鸿沟就越大。这种理解债务只能靠主动阅读来偿还,没有自动化方案。

Loop 跑得太顺会让人停止思考。 当 Loop 自动运行时,最舒服的姿态是放弃自己的判断、接受 Loop 给出的任何结果。这种"认知投降"看起来无害,但会让设计 Loop 的人最终变成按按钮的人。Loop 设计是解药还是毒药,取决于设计者是否仍在使用自己的判断。

轻量 Loop:先让日常任务自己跑

并非所有 loop 都要从代码、托管、队列和多 Agent 调度开始。很多个人场景只需要轻量 loop:一个触发条件,一个动作,一条验收规则,一个结果通知。

例如:每天早上汇总固定来源的信息,过滤掉低质量内容后发给你;收到某类邮件时提取事项,生成待办并提醒确认;每周检查项目进度文件,把阻塞、过期 action 和下一步整理成报告。这些任务的价值不在模型多聪明,而在它能按时发生、按规则整理、把结果送到你面前。

轻量 loop 适合用自然语言自动化工具、聊天机器人、日历、邮件、Notion、GitHub Actions 或简单脚本实现。关键在于把触发、动作、状态和停止条件说清楚。先让低风险、重复性的日常任务自己跑起来,再把经验迁移到更重的工程 loop。

Loop 的工具无关性

一个值得注意的现象是:同样的 Loop 在不同的 AI 编码工具上都能工作。Automations、Worktrees、Skills、Sub-agents、Connectors——这五件在不同工具里的名字略有不同,但能力完全对应。

这意味着Loop 设计应该瞄准能力本身,避免绑死在某个具体工具上。一旦把 Loop 绑死在一个工具上,工具迭代时整个 Loop 都要重写。能力是慢变量,工具是快变量,把工程投入到慢变量上回报更高。

与 Prompt Engineering 的差异

维度传统 Prompt EngineeringHarness Engineering
焦点优化提示词内容构建系统环境
持久性每次会话独立,无状态状态持久化到磁盘
范围控制无内置机制通过 feature_list.json 机器可读约束
验证依赖智能体主观判断强制测试套件通过才算完成
会话衔接每次"全新开始"通过 progress 文件连续交接
失败处理人工清理自动化 clean-state 流程

与本站其他内容的关系

类比建筑:ReAct / Plan-and-Execute 是建筑设计,Harness 是施工现场的脚手架、供电、给排水——没有这些,再漂亮的图纸也变不成可入住的房子。

参考

walinglabs/learn-harness-engineering