
过去一段时间里围绕 AI 编程的讨论大多集中在模型能力本身模型能不能理解需求、能不能写出可运行代码、能不能完成复杂重构。这些问题当然重要。但在真实研发场景中另一个问题正在变得更关键当模型已经足够会写代码之后我们如何让它稳定地在工程系统中工作这篇文章讨论的 Harness Engineering正是围绕这个问题展开。它并不是某个具体工具也不是某个固定模板而是一种将 AI 编码能力纳入工程流程的思路通过指令、状态、范围、验证和会话生命周期把模型的输出变得更可控、更可验证也更容易被团队持续使用。从“会写代码”到“可靠交付”为什么需要 Harness近一年来大模型发展迅猛模型能力持续提升已经能够完成日常开发中的相当一部分编码工作。无论是生成业务代码、补充单元测试、解释遗留逻辑还是进行简单重构AI 编码助手都已经进入了真实研发流程。但这是否意味着开发团队的整体效率也会随着模型能力同步快速提升答案未必。尽管模型能力很强但在实际开发中我们仍然会遇到很多问题模型可以每天产出大量代码但其中相当一部分并不能直接上线有些代码无法通过测试有些实现偏离了需求有些改动引入了新的维护成本开发者不得不反复沟通、纠偏、审查和返工。最终结果是看似节省了编码时间实际却把成本转移到了验证、清理和维护阶段。随着高性能模型调用成本上升以及 Agent 模式下 token 消耗快速增加如何更有效地利用模型让模型稳定产出可验证、可维护、可上线的结果正在成为一个越来越重要的工程问题。换句话说今天的问题已经不只是模型会不会写代码而是如何让模型在真实工程环境中可靠地完成任务这正是 Harness 工程化试图解决的问题。Harness 是什么把模型放进可验证的工程轨道Harness 是一种 AI 工程化思想。简单来说模型决定要写什么代码Harness 约束它在什么时候、在哪里、以什么方式写代码。换句话说Harness 不会让模型本身变得更聪明Harness 会让模型的工作过程更可控Harness 会让模型的输出更可靠。它的基本模式大致如下可以看到Harness 不同于简单的提示词工程。提示词工程通常关注“如何把话说清楚”而 Harness 工程化关注的是如何把模型放进一个可执行、可验证、可持续演进的软件开发流程中。在一个完整的软件开发流程中每个关键步骤都应该有对应机制来支撑模型工作例如让模型知道应该先读什么当前任务做到哪里下一步做什么什么算完成如何验证会话结束时如何交接。这些机制不应该只存在于一次性的对话里而应该落地为仓库中的文件、脚本、测试和流程。这样才能约束模型动作降低跑偏概率并让每一次 Agent 会话都能在同一个工程上下文中继续推进。我们真正关心的问题不是模型能不能写代码它们当然能。真正的问题是模型能不能在真实代码仓库中跨多个会话、无需持续人工监督地可靠完成真实工程任务Harness 的价值不在于替代模型能力而在于把模型能力约束到一个稳定的工程轨道中。没有 Harness 时Agent 像一个聪明但健忘、容易越界、缺少自检习惯的新同事。有了 Harness 后Agent 仍然可能犯错但它的错误更容易被发现和定位工作过程也更容易被复现和接续。引入 Harness 后开发流程会发生什么变化在没有 Harness 的情况下很多 AI 编码会话看起来很高效但实际上很难延续。一次会话结束后智能体可能忘记之前的背景下一次开始时又需要重新解释需求、重新判断状态甚至重复已经做过的工作。引入 Harness 后变化不在于模型突然变得完美而在于开发流程开始有了“轨道”。没有 Harness会话 1智能体写代码 → 破坏测试 → 说“完成了” → 你手动修复会话 2智能体从零开始 → 不记得之前的事 → 重复工作或做完全不同的内容 → 你再次修复结果你花在清理残局上的时间比自己做还多有 Harness会话 1智能体读取指令 → 运行init.sh→ 一次只做一个功能 → 验证通过后才声明完成 → 更新进度日志 → 提交干净状态会话 2智能体读取进度日志 → 准确接上上次位置 → 继续未完成功能 → 你负责审查而不是救火结果智能体完成工作你验证结果这也是 Harness 的核心价值它不是替代开发者做判断而是让开发者从“不断救火”转向“审查和决策”。智能体负责在约束内推进任务人负责设定方向、审查结果和维护工程质量。一个典型 Harness 系统由哪些部分组成如果把 Harness 拆开看它通常可以分成五个子系统指令、状态、验证、范围和会话生命周期。子系统包含内容指令系统InstructionsAGENTS.md、AI_GUIDE.md、功能清单、docs/文档目录状态系统Stateprogress.md、功能清单、git 历史、交接记录验证系统Verification测试用例、代码规范检查、类型检查、冒烟测试 / E2E范围控制Scope一次只做一个功能、不越界修改、完成标准明确会话生命周期Session Lifecycle会话开始运行init.sh、结束前执行清理检查、为下一次会话写交接记录、状态安全后再提交代码这五个部分不一定要一次性全部搭建完成但它们代表了让 AI 编码进入工程化流程时最常见的几个控制点。Instructions让智能体知道该如何工作Instructions 用来告诉智能体要做什么按什么顺序做开始之前必须阅读哪些内容遇到不确定情况时应该如何处理。它不应该是一个巨大的单一文件而应该是一套渐进式披露结构。也就是说入口文件保持简短清晰只说明 Agent 必须遵守的核心规则并链接到更细分的文档。Agent 根据当前任务需要再继续读取对应内容。例如AGENTS.md通用 Agent 操作手册AI_GUIDE.md针对具体模型、平台或工具的补充说明docs/architecture.md架构说明docs/testing.md测试策略feature_list.json功能清单和状态。State让工作可以跨会话延续State 用来跟踪已经完成了什么当前正在做什么下一步准备做什么上一次会话留下了哪些问题。状态应该持久化到磁盘而不是只保存在对话上下文里。这样即使上下文窗口耗尽或者下一次开启新会话Agent 也可以通过读取状态文件准确接上之前的工作。常见状态文件包括progress.mdagent-progress.mdfeature_list.jsonDECISIONS.mdgit commit historyVerification把“我完成了”变成“验证通过了”Verification 的原则是只有通过测试和检查才算真正完成。Agent 不能仅仅因为“我已经实现了”就宣布任务完成。它需要提供可运行的证据例如单元测试通过类型检查通过lint 通过冒烟测试通过关键路径手动验证完成E2E pipeline 通过。这一步的作用是把 Agent 的“主观完成”转换成工程上的“客观完成”。Scope限制一次只做一个明确任务Scope 用来限制 Agent 一次只完成一个明确任务。它要求一次只做一个功能不顺手重构无关模块不同时半完成多个功能不通过修改 feature list 来掩盖未完成工作每个任务都要有明确的 Definition of Done。范围控制非常重要。很多 Agent 任务失败并不是因为模型不会写代码而是因为它在执行过程中不断扩展范围最后导致改动过大、验证困难、问题难以定位。Session Lifecycle让每次会话都有开始和收尾Session Lifecycle 约束一次 Agent 会话从开始到结束的完整过程。典型流程包括会话开始时运行init.sh初始化依赖、检查环境、运行基础验证开始前读取说明文档和进度文件工作过程中持续更新进度结束前运行测试和检查清理临时文件和无效改动写下 handoff note只有在状态安全可恢复时才提交代码。这保证了每一次会话结束后仓库都能保持在一个干净、可继续工作的状态。如何在真实项目中落地 Harness理解 Harness 思想之后并不需要一开始就搭建一套复杂平台也不需要马上把它深度接入公司的研发系统。更现实的做法是先从一个真实仓库开始给 AI 编码智能体增加一组结构化文件用来定义它应该如何工作当前项目已经完成了什么接下来应该做什么如何验证工作结果会话结束时如何交接。这些文件放在代码仓库中让每一次 Agent 会话都能从同一个工程状态开始。无论你使用的是商业模型、开源代码模型还是企业内部封装的研发 Agent这套结构都可以复用。一个最小可用结构如下项目根目录 ├ agents.md智能体的通用操作手册 ├ guide.md可选针对具体模型/工具的补充说明 ├ init.sh安装依赖、检查环境、运行验证 ├ feature_list.json功能清单与完成状态 ├ progress.md跨会话进度记录 ├ design.md关键技术决策日志 ├ limitations.md技术限制与约束记录 ├ bugs.md历史问题和避坑记录 └ src/业务代码这个结构并不复杂但它能把很多原本散落在对话里的信息沉淀为项目的一部分。这样做的好处是智能体不再每次都从零开始理解项目而是可以沿着已有状态继续推进。agents.md用来说明项目是什么开始任务前必须读哪些文件修改代码前要遵守哪些规则一次只能处理什么范围完成前必须运行哪些检查不能做哪些危险操作。guide.md用于记录针对具体模型、平台或工具的补充说明。例如某个工具如何启动某类任务应该使用什么命令某些平台环境有什么限制某些模型在当前项目中容易犯什么错误。init.sh用于安装或检查依赖、确认环境、运行基础验证。它应该尽量明确说明在不同任务场景下智能体需要完成哪些准备工作才能开始开发。例如修复 bug 前是否需要构造最小复现用例验证页面效果前需要设置哪些环境变量本地服务应该使用哪个端口是否需要启动 mock server是否需要准备测试数据。feature_list.json这是任务和功能状态的来源。它可以记录当前有哪些功能每个功能的状态每个功能的验收标准哪些功能正在进行哪些功能已经完成哪些功能被阻塞。功能拆解不一定必须是平铺直叙的也可以采用树状结构。对于复杂功能可以继续拆解为多个子功能。progress.md用于记录本次会话做了什么修改了哪些文件运行了哪些验证还剩什么问题下一次会话应该从哪里继续。design.md用于记录关键技术决策和工程约束例如优先使用本项目工具库中已有的方法不要重复造轮子变量命名风格必须和本项目一致重复逻辑必须抽取公共方法某个模块为什么采用当前实现方式哪些方案已经被否决为什么否决。limitations.md用于记录功能开发和迭代过程中遇到的技术限制提示智能体避免进入不可行路径。bugs.md用于记录曾经踩过的坑和历史问题避免智能体在接入新功能时再次引入重复 bug。Harness 如何在实践中演进前面介绍的是 Harness 的基本结构。但在真实项目中Harness 不是靠一次性设计出来的而是在一次次任务、失败、纠偏和复盘中长出来的。下面是几个在实践中比较重要的经验。经验一Agent 规则应该来自真实经验而不是一次性生成所有操作文件应该来自真实项目中的经验总结。不能简单地给 AI 一个指令然后等待它一次性生成一份复杂的 Agent 文件就认为 Harness 搭建完成了。这样的文件往往看起来很完整但很可能无法覆盖真实工作中的关键风险。更合理的做法是先让 Agent 参与真实任务观察它在哪里容易跑偏记录哪些规则能显著减少错误把这些经验逐步沉淀进AGENTS.md定期删除已经过时或无效的规则。AI 可以帮助你编写和整理这些文件但文件背后的判断应该来自现实世界的经验。换句话说不应该完全让 AI 接管 skill 或 Harness 规则的制定。智能体很聪明但它并不天然理解你的业务环境、团队习惯、历史包袱和真实用户需求。人需要把这些经验沉淀下来再让 AI 在这些约束下工作。经验二先由人搭建清晰项目雏形再逐步引入 Harness一个常见误区是以为引入 Harness就是在项目开始时先主观设计出一批 Agent 文件再指望它们自然形成一个完美闭环。实际上Harness 的作用是辅助 AI 进入稳定、可验证的开发流程而不是在一开始就预设出一个完美系统。尤其在复杂项目中不建议直接把系统从零到一完全交给 AI 自由演进。更稳妥的方式是先由人设计并搭建出一个架构清晰、职责明确、边界直观的系统。当系统本身经得起推敲之后再让 AI 在这个架构内逐步扩展功能。原因很简单仅靠一句话让 AI 生成一个复杂应用往往很难把控后续演进方向。即使是人类工程师也不可能在一开始就完全想清楚一个系统最终应该长什么样。很多真实需求都是在投入使用后通过试用反馈逐渐浮现再逐步融入系统架构中。如果复杂系统从一开始就完全由 AI 负责早期可能看起来还比较精简也容易运行。但随着迭代次数增加系统架构很可能逐渐变得松散边界开始模糊重复逻辑增加临时方案变成长期方案最终维护成本越来越高。如果先由人搭建整体架构并建立良好的编码习惯后续 AI 介入时会接收到这些范式从而更容易模仿出好的代码。但即便如此在 AI 迭代过程中仍然会出现跑偏。例如引入不必要的抽象复制已有逻辑而不是复用为了通过测试写出脆弱实现顺手重构无关代码偏离原有架构边界。这时人应该及时介入调整方向。坏的模式如果不及时清理会逐渐扩散并掩盖原本好的设计最终让系统在某一天变得难以维护。经验三不要指望一个 Agent 承担所有职责在 Harness 系统中可以考虑引入多个智能体或者让多个模型/Agent 协同工作并承担不同职责。不要把所有要求都塞进同一个提示词里让一个 Agent 同时负责生成方案编写代码检查质量判断是否完成评价自己的成果。更好的方式是拆分职责生成器 Agent负责方案生成、代码实现、功能构建评估器 Agent负责测试、审查、评分和反馈。二者可以形成这样的协作关系原因在于当要求智能体评估自己产出的工作时它往往会自信地称赞这些成果。即使在人类观察者看来其质量明显普通Agent 也容易给出偏正面的评价。这个问题在设计类、产品类、交互类任务中尤其明显。因为这类任务不像单元测试那样有清晰的二元判断。一个布局是精致还是普通一个页面是否有设计感本质上都包含主观判断。而 Agent 在给自己的作品评分时通常会稳定偏向正面评价。将“执行工作的智能体”和“评判工作的智能体”分离是解决这一问题的有效杠杆。当然单纯分离并不会立刻消除宽松倾向。评估器仍然是 LLM也可能对 LLM 生成的输出更加宽容。但相比让生成器批判自己的作品训练或调教一个独立评估器使其更怀疑、更严格通常更容易。一旦外部反馈存在生成器就有了具体的迭代依据。例如在前端页面生成任务中可以将“页面生成”和“页面评估”分离生成器 Agent 负责实现页面评估器 Agent 根据统一标准检查页面质量并输出可执行的修改建议。随后生成器再根据这些反馈继续迭代。评估标准可以包括以下几个维度。1设计质量Design Quality这个设计是否像一个连贯整体而不是一堆零散部件的集合优秀的设计应该让颜色、字体排版、布局、图像和细节形成统一的情绪和身份感。2原创性Originality是否能看出定制化决策而不是模板布局、组件库默认样式和常见 AI 生成套路人类设计师应该能够识别出有意为之的创意选择。未经修改的现成组件或典型 AI 生成痕迹例如“白色卡片 紫色渐变”在这一项上都应该扣分。3工艺Craft / Technical Execution这一项关注基础执行质量包括字体层级间距一致性色彩协调对比度响应式表现细节完成度。这是能力检查而不是创造力检查。多数合理实现默认都能在这里表现不错如果失败说明基础能力出了问题。4功能性Functionality这一项独立于美学之外关注可用性。用户是否能理解界面在做什么是否能找到主要操作是否无需猜测就能完成任务通过这种方式生成器不再只是“自我感觉良好”而是要面对一个相对独立、可重复使用的评估标准。经验四持续改进 Harness不要指望一次性搭建完美系统Harness 不是一次性工程而是一套需要持续演进的工作系统。有一句话很适合用在日常开发里“以后再清理”就是以后也不会清理。每次使用 AI 后都应该检查它是否引入了无效代码废弃代码重复逻辑临时方案没有使用的抽象只为通过当前测试而写的脆弱实现。这些内容应该及时删除或修正不要等。因为一旦坏模式进入代码库后续 AI 很可能继续模仿它们。同样Harness 和提示词本身也需要持续维护。提示词工程绝对不是越写越多越好。规则越堆越多最终会变得臃肿、冲突甚至连 AI 都难以遵守。更好的做法是定期简化 Harness。Harness 中每个组件的存在通常都源于模型在某个方面还无法稳定独立完成。但随着模型能力演进这些前提会逐渐过时。例如早期模型可能无法自己拆解复杂任务所以需要外部任务拆分机制。但当模型规划能力变强后原来的拆分机制可能反而变成负担。它会增加流程步骤让 Agent 过度依赖外部结构甚至限制模型自身的规划能力。Evaluator 也是类似情况。当任务难度较高、接近模型能力上限时独立 Evaluator 很有价值因为它能发现遗漏、检查质量、提供外部反馈。但如果任务很简单远在模型能力范围内Evaluator 可能就是多余环节。所以要不要保留某个 Harness 组件取决于三个因素任务有多难模型有多强这个组件是否仍然带来净收益。一个推荐做法是每月挑选一个 Harness 组件暂时禁用它跑一遍基准任务。如果结果没有退化就永久移除如果结果退化则恢复该组件或换一个更轻量的替代方案。更深层的原则是随着模型能力提升Harness 中有趣的组合并没有减少而是在发生位移。过去必须依赖 Harness 解决的问题可能会被模型新增能力覆盖。与此同时模型能力提升也会打开新的使用边界暴露出过去触及不到的新问题。因此Harness 不应该是一套固定不变的模板而应该是一套持续演进的工程系统。结语Harness 的本质是把 AI 能力变成工程能力AI 编码真正困难的地方往往不在于“生成一段代码”而在于让这段代码进入真实工程系统并且能够被验证、维护、复用和持续演进。提示词工程解决的是“如何让模型更好地理解这一次请求”。上下文工程解决的是“如何让模型看到更合适的信息”。而 Harness Engineering 进一步关注的是如何让模型在一个可控、可验证、可持续演进的工程流程中工作。它不是某个固定模板也不是一组越写越长的提示词而是一套围绕真实项目持续生长的工程机制。当模型能力越来越强开发者的角色也会发生变化我们不再只是逐行编写代码而是更多地设计约束、维护上下文、定义验证方式并判断系统演进方向。从这个角度看Harness 并不是为了限制 AI而是为了让 AI 的能力真正进入工程生产。只有当模型的输出能够被流程承接、被测试验证、被状态延续、被团队维护时AI 编码才不只是一次漂亮的演示而会成为可靠的软件开发能力。