【AI 应用】Harness Engineering:不靠玄学 Prompt,让 AI Agent 稳定交付的工程方法(约束+上下文+验证闭环)
前言本文面向的是希望把 AI 用到“可交付”的开发者。核心目标不是追求一次输出多惊艳而是把结果变成可复用、可验证、可迭代。内容来自一次围绕Harness Engineering的讨论整理从概念到落地从 Skill 到自动检测闭环。⚡ 快速参考适用场景LLM/Agent 辅助写代码、写文档、生成页面、对接接口且需要“长期稳定交付”的项目/团队/个人工作流核心结论Harness Engineering不是单一工具而是“围绕模型构建约束、上下文、验证与反馈闭环”的工程体系可靠性主要来自 Harness而非模型本身最简步骤沉淀规范Constraints→ 组织上下文Context→ 上自动检测Validation→ 让错误可回写可修复Feedback→ 全链路留痕Observability必备代码最小校验脚本例如路由与docs/spec一致性检测资源命名/台账检测失败输出可修复指引高危避坑只写“规范文档”但不做自动检测把 Skill 当万能提示词上下文一次性塞爆错误信息不含修复动作导致无法形成闭环 学习目标掌握Harness Engineering的定义、组成与与 Prompt/Context 的边界能独立完成一个“最小 Harness”规范文档 few-shot/检索上下文 自动检测脚本 可修复的失败反馈能说出“自动检测的目的与收益”并能用一个路由案例解释闭环如何工作一、基础概念1.1 Prompt / Context / Harness 三个概念的分工Prompt Engineering把指令写清楚让模型“更懂任务”Context Engineering让模型“看见正确资料”包括文档组织、few-shot 示例、检索上下文RAG等Harness Engineering把 Agent 放进一个“能长期稳定交付”的系统里系统包含约束、上下文、验证、反馈、观测与成本控制1.2 一句话定义 Harness EngineeringHarness Engineering 设计并运行一套“约束 上下文 自动验证 反馈闭环 可观测”的工程系统让 AI Agent 的输出可交付、可回归、可持续。1.3 Skill 属于哪一类以一个真实 Skill用于 uni-app Vue3 小程序交付为例它包含 Hard Rules、流程分阶段、目录契约、交付清单。这种 Skill 更像“结构化操作手册 工作流约束”主要落在Constraints约束层禁止假设跳转逻辑、冲突优先级、重命名先提案后执行、文档分层边界等Orchestration编排层Mode A/B 切换、四阶段执行流程Verification验证层的雏形交付 checklist但多为人工检查结论是Skill 不是一句提示词但 Skill 也不等于完整 Harness。完整 Harness 还需要“可执行的验证脚本 可回写修复的反馈机制 留痕与观测”。1.4 核心概念对比表必须有表格维度Prompt EngineeringContext EngineeringHarness Engineering目标单次输出更像“想要的”让模型“看对资料”让系统“持续产出可交付结果”主要手段指令、格式要求、角色设定文档组织、few-shot、RAG、渐进披露约束验证反馈闭环观测成本/权限失败表现改 prompt 反复试上下文缺失/过载导致跑偏有护栏与回归失败可定位可修复成熟标志靠经验调参有稳定资料入口与索引有自动检测与闭环质量可回归二、原理详解2.1 为什么只靠 Prompt 很难稳定交付LLM 的输出具有概率性。任务一旦变成多步骤读文档→改代码→跑验证→修复→提交失败面会迅速扩大上下文缺失缺页面映射、缺接口字段、缺资源命名规则工具调用失败命令报错、路径不一致、文件没更新质量不可控风格漂移、规范遗忘、文档与代码不同步Prompt 解决“表达”但很难覆盖“长期的工程秩序”。2.2 Harness 的核心把“规范”变成“可执行护栏”Harness 的关键转折点是规范写在文档里→ 仍然需要人工盯规范写成检测脚本/CI→ 系统自动守住边界这一步带来的收益通常是漂移更早发现越早越便宜返工更少错误在合并前被挡住可规模化页面/模块变多时人眼检查会崩机器检查成本几乎不变可形成反馈闭环错误信息包含修复指引Agent 能自修2.3 一个最直观的闭环Mermaid下面这张流程图可以当作本文的“工程主线”通过失败需求/任务输入Context 组装docs/spec few-shot 检索上下文Agent 生成/修改自动检测 Validationlint/test/spec一致性/命名规则交付/合并/发布失败信息含修复指令Feedback 回写上下文留痕与观测变更记录/质量指标/成本2.4 few-shot 检索上下文RAG到底是什么few-shot给模型少量“高质量样例”让输出风格和结构趋于稳定例如文章开头、实战段落、总结段落的范例检索上下文RAG每次任务前从知识库/代码库里“检索相关片段”再喂给模型避免靠记忆和猜测它们偏向 Context Engineering但在 Harness 中通常会被当作“上下文供给系统”的一部分。三、完整实战代码怎么做本节给一个“最小可落地”的示例用路由事实推动docs/spec显式化并用脚本做一致性检测。示例的路由代码原始素材如下import{createRouter,createWebHistory}fromvue-routerimportGenerateResumePagefrom../views/GenerateResumePage.vueimportGreetingPagefrom../views/GreetingPage.vueimportPersonalInfoPagefrom../views/PersonalInfoPage.vueimportProjectsPagefrom../views/ProjectsPage.vueconstroutercreateRouter({history:createWebHistory(),routes:[{path:/,redirect:/personal},{path:/resume,name:resume,component:GenerateResumePage,meta:{keepAlive:true}},{path:/greeting,name:greeting,component:GreetingPage,meta:{keepAlive:true}},{path:/personal,name:personal,component:PersonalInfoPage},{path:/personal/projects,name:projects,component:ProjectsPage}]})exportdefaultrouter3.1 第一步把隐含在代码里的“导航事实”写进 spec例如docs/spec/screens.md示意## 入口 - / - redirect /personal ## 页面清单slug / path - personal: /personal - projects: /personal/projects - greeting: /greeting - resume: /resume ## 约束 - resume.keepAlive true - greeting.keepAlive true3.2 第二步写一个最小校验脚本Node 版目标校验docs/spec/screens.md中声明的 path必须在路由里存在并校验关键约束redirect、keepAlive。// scripts/validate-routes.mjsimportfsfromnode:fsconstrouterFileprocess.argv[2]||src/router/index.tsconstscreensFileprocess.argv[3]||docs/spec/screens.mdfunctionfail(msg){console.error([VALIDATE_FAIL]${msg})process.exit(1)}if(!fs.existsSync(routerFile))fail(router file not found:${routerFile})if(!fs.existsSync(screensFile))fail(screens file not found:${screensFile})constrouterTextfs.readFileSync(routerFile,utf8)constscreensTextfs.readFileSync(screensFile,utf8)// 1) 从 screens.md 抽取 path非常简化版匹配 : /xxxconstdeclaredPathsArray.from(screensText.matchAll(/:\s*(\/[a-zA-Z0-9/_-])/g)).map(mm[1])if(declaredPaths.length0)fail(no declared paths found in${screensFile})// 2) 在 router 文件中检查 path 是否存在constmissingdeclaredPaths.filter(p!routerText.includes(path: ${p})!routerText.includes(path: ${p}))if(missing.length){fail(routes missing in router:${missing.join(, )}. Fix: add routes or update${screensFile})}// 3) 检查入口 redirect 约束if(!(routerText.includes({ path: /, redirect: /personal })||routerText.includes(path: /)routerText.includes(redirect: /personal))){fail(root redirect constraint violated. Expect / redirect to /personal. Fix router or update spec.)}// 4) 检查 keepAlive 约束示例要求 resume/greeting keepAlive truefor(constnameof[resume,greeting]){constokrouterText.includes(name: ${name})routerText.includes(keepAlive: true)if(!ok)fail(${name}.keepAlive constraint violated. Fix: set meta.keepAlivetrue for route ${name}.)}console.log([VALIDATE_OK] routes/spec constraints satisfied)3.3 第三步本地一键验证示例命令nodescripts/validate-routes.mjs src/router/index.ts docs/spec/screens.md3.4 这段“自动检测”的目的是什么让docs/spec不再靠人工维护让“路由变化”会强制触发“spec 更新”避免文档失真让失败信息携带修复动作便于下一轮 Agent 直接按报错修到通过让交付结果可回归同一套检测在未来迭代继续有效四、场景应用固定2个真实场景场景1AI 帮写页面如何避免“跳转逻辑瞎编”需求页面按原型实现跳转/参数/返回刷新策略必须真实可追溯方案用 Skill 约束“无交互定义不假设”把页面映射与跳转写进文档中并用脚本校验路由与 spec是否一致收益交互逻辑从“口头约定”变成“可验证事实”减少联调返工与口径不一致场景2AI 写技术博文如何避免“风格漂移、结构散、空话多”需求长期持续输出同一风格的高质量文章结构稳定、内容可复现方案few-shot 固化“开头/实战/总结”段落范式检索上下文素材库提供真实依据引入发布前自检脚本/清单例如标题层级、必备模块是否齐全、是否包含对比表格与流程图收益从“灵感驱动”升级为“流程驱动”质量波动更小复用成本更低五、开发避坑总结问题规范写得很完整但交付还是不稳定原因规范停留在文档层缺少可执行验证解决把关键规范变成脚本/CI 校验失败信息包含修复指令形成闭环问题Skill 越写越长反而不好用原因上下文一次性塞爆任务信息被挤掉且规则很难验证解决Skill 保持“入口索引 核心 Hard Rules”细节拆到docs/并建立目录契约校验“文档存在性/一致性”而不是堆文字问题检索RAG做了但效果不稳定原因检索出来的片段不具备“可执行事实”或者缺少 few-shot 对输出结构的约束解决RAG 提供事实材料few-shot 提供结构范式验证层负责兜底一致性与格式要求六、面试考点Q1Harness Engineering 和 Prompt Engineering 的区别是什么APrompt 关注“单次指令与输出”Harness 关注“围绕模型的系统”约束、上下文组织、工具编排、自动验证、反馈闭环与观测。Prompt 是输入之一Harness 是让系统可靠的主体。Q2为什么说 Harness 比换模型更重要A模型提升通常影响“单次输出质量”而 Harness 影响“端到端稳定性与可回归能力”能把失败变成可定位可修复的问题并让质量在迭代中不漂移。Q3自动检测Validation的工程价值是什么A把“人脑记住的规范”变成“系统自动守住的护栏”更早发现漂移减少返工并让 Agent 能根据失败信息自动修复形成闭环。追问1few-shot 和 RAG 各解决什么问题Afew-shot 固化输出结构与风格RAG 提供任务所需事实资料。两者配合再由验证层兜底。追问2Skill 在 Harness 中扮演什么角色ASkill 多数属于约束层与编排层规定边界与流程要成为完整 Harness 仍需接入验证、反馈与观测。七、总结复盘下一步本文把Harness Engineering从“概念”落到“工程动作”规则与流程属于约束/编排层few-shot 与检索上下文属于上下文工程自动检测与可修复失败信息是闭环的关键留痕与观测让系统可持续迭代而不漂移下一步的落地路径通常是先做一个最小校验脚本把最痛的漂移点路由/spec、资源命名/台账、接口字段对齐、文章结构自检先变成“红线”。本文为MY_TRUCK原创实战学习笔记持续更新Java后端与AI应用领域干货问题欢迎评论区交流。