资讯动态

Agentic Harness Workflow:构建AI Coding的工程化流水线

发布时间:2026/10/14 23:04:40 来源:尧图企业网站定制
1. 为什么我们需要一个 Agentic Harness Workflow1.1 从“对话式写代码”到“工程化流水线”的认知转变过去一年多我身边不少开发者对 AI Coding 的态度经历了三个阶段最开始是“哇它居然能补全一整段函数”然后是“它写的代码我得逐行 review比自己写还累”最后变成“算了还是自己来吧”。这个曲线背后其实藏着一个很朴素的事实——把 AI 当成一个更聪明的自动补全工具收益是有天花板的。真正让效率产生质变的是把 AI 从“对话框里的助手”重新定位成“流水线上的一个工位”。这个工位有明确的输入、明确的输出、明确的验收标准还有明确的失败重试机制。Agentic Harness Workflow 这个框架本质上就是给 AI Coding 搭一套“工装夹具”harness 这个词在工程语境里就是夹具、测试台架的意思让它在一个受控的、可观测的、可复现的环境里干活而不是每次都在一个空白对话框里即兴发挥。我最初接触这套思路是在做一个内部工具链重构的时候。当时的需求很典型把一个老模块的几十个接口逐个迁移到新架构上每个接口的逻辑都不复杂但数量多、模式重复、验收标准清晰。如果纯手工做大概要两周如果纯靠对话式 AI每次都要重新贴上下文、重新解释规范、重新检查它有没有跑偏实际省下来的时间可能只有三成。后来我把整个流程拆成了“任务定义 → 上下文装配 → 执行 → 自动校验 → 失败回炉”几个环节用脚本把它们串起来AI 只在“执行”这个环节里干活其余环节全部由工程化的代码控制。结果那批接口迁移的实际耗时压到了三天而且返工率极低。这就是 Agentic Harness Workflow 的核心价值它不追求让 AI 一次做对而是让 AI 在一个能自动发现错误、自动纠正错误的闭环里持续工作。1.2 这套框架到底解决什么问题我把实际踩过的痛点列一下你看看有没有共鸣上下文漂移同一个任务你分三次跟 AI 说它三次给出的实现风格可能都不一样变量命名、错误处理方式、目录结构全在飘。验收靠人眼AI 写完一段代码你得自己跑一遍、自己看 diff、自己判断对不对这个环节完全没法自动化。失败无记录某次 AI 写错了你纠正了它但下次遇到同类问题它还会犯因为纠正的过程没有被沉淀成规则。任务粒度失控一个“帮我重构这个模块”的大任务丢给 AI它要么做一半卡住要么自作主张改了一堆不该改的地方。无法并行多个独立的小任务本来可以同时推进但因为都挤在同一个对话框里只能串行等待。Agentic Harness Workflow 的思路是把这些问题逐个拆解用结构化的任务描述解决上下文漂移用自动化校验脚本解决验收问题用规则库和失败案例库解决经验沉淀问题用任务分解器控制粒度用多实例调度实现并行。1.3 适合谁来用这套东西说实话这套框架不是给“我就想让 AI 帮我写个正则表达式”这种场景准备的。它适合的是手上有批量、重复、模式化的编码任务比如接口迁移、测试用例补全、日志埋点注入、配置项批量修改。团队里已经有一定工程化基础能写脚本、能跑 CI、有代码规范约束。愿意花一两天时间搭基础设施换取后续几周甚至几个月的效率提升。如果你符合上面任意两条那这套东西的投入产出比会非常可观。下面我按实际搭建的顺序把每个环节拆开讲。2. 框架整体设计与核心模块拆解2.1 整体架构五个环节串成一条流水线我把整个 Harness 分成五个核心模块它们之间的关系是流水线式的但每个模块内部都可以独立替换和升级模块职责输入输出任务定义器把大需求拆成原子任务需求描述、规范文档结构化任务清单上下文装配器为每个任务准备精准上下文任务清单、代码库索引上下文包执行器调用 AI 完成单个任务上下文包代码变更校验器自动验证变更是否符合预期代码变更、校验规则通过/失败报告回炉器失败任务自动重试或升级失败报告修正后的任务或人工介入请求这个设计的精髓在于AI 只在执行器里出现其余四个模块全是确定性代码。这意味着整个流程的稳定性不依赖于 AI 的“心情”而依赖于你写的工程逻辑。AI 发挥不稳定的时候校验器会拦住它AI 发挥超常的时候校验器也会确认它的输出确实符合规范。2.2 为什么要把任务拆得这么细我一开始也想过偷懒直接让 AI 处理“把 user 模块的所有接口迁移到新架构”这种大任务。实测下来问题很多它会漏掉一些接口会对某些接口做出超出预期的改动会在中途“忘记”前面定好的规范。后来我把任务粒度降到“单个接口的迁移”每个任务只涉及一个文件、一个函数、一组明确的输入输出成功率立刻上了一个台阶。这里有个经验值可以参考单个任务的预期代码变更量控制在 50 到 200 行之间。低于 50 行任务拆得太碎调度开销占比过高高于 200 行AI 出错的概率显著上升而且出错后定位问题的时间成本也会增加。任务定义器的输出格式我建议用结构化的 YAML 或 JSON而不是自然语言。比如task_id: migrate_user_get_profile type: interface_migration source_file: legacy/user_api.py target_file: new/user_api.py function_name: get_user_profile input_schema: user_id: string output_schema: name: string email: string created_at: timestamp constraints: - 保持原有错误码不变 - 使用新的日志组件 - 不允许引入新的外部依赖这种结构化描述的好处是后续的上下文装配器和校验器都可以直接读取这些字段不需要再去解析自然语言。2.3 上下文装配给 AI 的信息要“刚刚好”上下文给少了AI 会瞎猜给多了它会迷失在无关信息里。我的做法是分三层装配上下文第一层任务本身的信息就是上面那个结构化描述。第二层相关代码片段包括源文件的相关部分、目标文件的现有结构、被依赖的公共模块的接口定义。第三层规范和示例包括团队的代码规范摘要、一个已经完成的同类任务的正确示例。第三层特别关键。我发现给 AI 一个“已经做对的样板”比给它十条文字规范都管用。样板要选那种结构清晰、没有特殊情况的典型案例让 AI 有样学样。上下文装配器还需要做一个重要的事情控制总 token 量。我的经验是单个任务的上下文控制在模型上下文窗口的 30% 到 50% 之间比较合适留出足够的空间给 AI 生成输出。如果上下文超了就要做优先级裁剪优先保留任务描述和样板示例代码片段可以只保留函数签名和关键逻辑。2.4 校验器整个框架的“守门人”校验器是我花时间最多的模块因为它直接决定了整个流程能不能自动跑起来。校验分几个层次语法层代码能不能通过编译或解析这个用现成的 linter 就行。结构层函数签名、参数类型、返回值结构是否符合任务描述里的 schema。行为层跑单元测试看功能是否正确。规范层命名风格、注释格式、日志调用方式是否符合团队规范。前两层是必须的成本低、收益高。行为层需要你有现成的测试用例如果原来没有可以借这个机会让 AI 顺便把测试补上——但要注意AI 写的测试不能直接用来验收 AI 写的代码否则就是自己批改自己的作业。我的做法是行为层的测试用例由人工编写或审核确保测试本身是可信的。规范层可以用正则表达式或 AST 分析来做比如检查所有日志调用是否都用了新的 logger 对象检查所有函数是否都有类型注解。2.5 回炉器让失败变成资产回炉器的逻辑是这样的校验失败的任务先自动重试一次重试时把失败原因作为额外上下文喂给 AI。如果第二次还失败就把任务标记为“需要人工介入”同时把失败案例存入案例库。这个案例库后面会变成上下文装配器的一个数据源。当新任务和某个历史失败案例相似时装配器会主动把“这个坑别踩”的提示加进上下文里。这就实现了经验的自动沉淀——每一次失败都不会白费它会变成后续任务的护栏。3. 核心环节的实操细节与参数选择3.1 任务定义器的实现要点任务定义器我建议做成半自动的先用脚本从代码库里提取出所有待迁移的接口清单生成一个初始的任务列表然后人工过一遍补充每个任务的约束条件和验收标准。全自动生成任务列表容易漏掉隐含约束比如某个接口有特殊的错误处理逻辑或者某个接口被外部系统依赖不能改签名。提取接口清单的脚本逻辑大概是解析源文件找到所有目标函数的定义提取函数名、参数列表、返回类型、docstring。这部分用 AST 解析比正则表达式靠谱得多Python 用ast模块JavaScript 用babel/parserJava 用 JavaParser。人工补充约束的时候我习惯用一个检查清单来确保不遗漏这个接口有没有特殊的错误码有没有外部系统依赖它的签名有没有性能敏感的逻辑需要保留有没有需要同步更新的文档或配置3.2 上下文装配的 token 预算计算假设你用的模型上下文窗口是 128K token单个任务的预算可以这样分配内容类型预算占比说明任务描述5%结构化 YAML通常很短代码片段40%源文件相关部分 目标文件结构规范与示例30%代码规范摘要 一个完整样板失败案例提示10%相似历史失败的避坑提示预留输出空间15%给 AI 生成代码留的余量这个分配不是死的如果某个任务特别复杂代码片段占比可以上调但预留输出空间不能低于 10%否则 AI 生成的代码容易被截断。3.3 执行器的调用策略执行器调用 AI 的时候有几个参数需要仔细调温度temperature代码生成任务建议设低一点0.1 到 0.3 之间。太高了 AI 会“创意发挥”写出一堆你没要求的抽象层太低了又可能过于死板遇到需要变通的地方卡住。最大输出长度根据任务预期代码量设置一般留出预期量的 1.5 倍余量。停止序列如果 AI 的输出有固定格式比如先输出代码再输出解释可以设置停止序列让它在代码结束后就停避免生成一堆无关的解释文字。我实测下来把“只输出代码不要解释”写进系统提示里配合低温度输出的稳定性最好。如果确实需要 AI 解释它的思路可以单独开一个“解释任务”让它对已经生成的代码做说明而不是在执行任务里混着做。3.4 校验规则的编写技巧校验规则我建议用“规则即代码”的方式管理每条规则是一个独立的函数输入是代码变更输出是布尔值和失败原因。这样规则可以单独测试、单独启用禁用、单独统计触发率。几条我常用的规则示例检查所有新增函数是否有类型注解用 AST 遍历函数定义节点。检查所有日志调用是否使用了统一的 logger 对象正则匹配logging.或console.log等。检查是否有硬编码的配置值匹配常见的 IP、端口、URL 模式。检查函数复杂度是否超标用 cyclomatic complexity 工具。规则的误报率要控制住。如果一条规则经常误报要么修正规则要么把它降级为“警告”而不是“失败”。误报太多的规则会让整个校验环节失去可信度最后大家都不看校验报告了。3.5 回炉重试的提示词设计重试时的提示词和首次执行不一样需要把失败原因明确地告诉 AI。我的模板大概是你上次生成的代码没有通过校验失败原因如下 [具体的失败信息] 请针对上述问题修正代码。注意 1. 只修改与失败原因相关的部分不要改动其他逻辑。 2. 修正后重新输出完整代码。 3. 如果你认为校验规则本身有问题请在代码后用注释说明。最后一条很重要。有时候确实是校验规则太严了AI 的写法是合理的。让 AI 有机会“申诉”可以帮你发现规则里的问题。当然申诉是否采纳还是由人工决定。4. 完整实操流程从零搭一个最小可用版本4.1 环境准备与目录结构先说一下最小可用版本需要什么。你不需要一上来就搞得很复杂一个 Python 脚本加几个配置文件就能跑起来。目录结构建议这样harness/ tasks/ # 任务定义文件 context/ # 上下文装配的中间产物 outputs/ # AI 生成的代码 reports/ # 校验报告 rules/ # 校验规则 cases/ # 失败案例库 config.yaml # 全局配置 run.py # 主流程脚本config.yaml里放模型调用的配置、token 预算、重试次数等全局参数。任务定义文件放在tasks/下一个任务一个文件用任务 ID 命名。4.2 第一步写一个任务定义文件拿一个具体的例子来说。假设你要把一个旧接口迁移到新架构任务定义文件tasks/migrate_user_get_profile.yaml内容如下task_id: migrate_user_get_profile type: interface_migration source_file: legacy/user_api.py target_file: new/user_api.py function_name: get_user_profile input_schema: user_id: string output_schema: name: string email: string created_at: timestamp constraints: - 保持原有错误码不变 - 使用新的日志组件 logger - 不允许引入新的外部依赖 - 所有函数必须有类型注解 acceptance: - 函数签名与 output_schema 一致 - 通过单元测试 test_get_user_profile - 无硬编码配置值这个文件就是任务定义器的输出也是后续所有环节的输入。4.3 第二步装配上下文上下文装配脚本读取任务定义然后从代码库里提取相关片段。提取逻辑是先找到source_file里function_name对应的函数体再找到target_file里同类函数的现有实现作为结构参考最后从规范库里取一个同类任务的样板。装配完成后生成一个context/migrate_user_get_profile.md文件内容大致是## 任务描述 [任务 YAML 的内容] ## 源函数实现 [从 legacy/user_api.py 提取的函数体] ## 目标文件现有结构 [从 new/user_api.py 提取的同类函数] ## 代码规范摘要 [规范库里的相关条目] ## 参考样板 [一个已完成的同类任务的正确实现]这个文件就是喂给 AI 的完整上下文。4.4 第三步调用 AI 执行执行脚本读取上下文文件拼上系统提示调用模型 API。系统提示我一般这样写你是一个代码迁移助手。你的任务是根据提供的上下文完成指定的代码迁移。 要求 1. 只输出迁移后的完整函数代码不要输出解释。 2. 严格遵守任务描述里的约束条件。 3. 参考样板的结构和风格。 4. 如果上下文信息不足以完成任务输出 INSUFFICIENT_CONTEXT 并说明缺少什么。最后一条是防止 AI 在信息不足时瞎编。实测下来明确告诉它可以“拒绝任务”比让它硬着头皮编要安全得多。4.5 第四步跑校验校验脚本按顺序跑四层校验任何一层失败就记录失败原因并终止后续校验。校验报告写到reports/migrate_user_get_profile.json格式如下{ task_id: migrate_user_get_profile, status: failed, checks: [ {layer: syntax, passed: true}, {layer: structure, passed: true}, {layer: behavior, passed: false, reason: test_get_user_profile 断言失败created_at 格式不正确}, {layer: convention, passed: true} ] }4.6 第五步回炉或通过如果校验通过把生成的代码写入target_file任务标记完成。如果失败进入回炉流程把失败原因拼进上下文重新调用 AI最多重试两次。两次都失败就标记为“需要人工介入”并把失败案例存入cases/。整个流程跑下来一个任务的端到端耗时大概在 30 秒到 2 分钟之间取决于任务复杂度和模型响应速度。相比人工操作单个任务的耗时可能差不多但你可以同时跑几十个任务而且不需要人盯着。5. 常见问题与排查技巧实录5.1 AI 输出格式不稳定怎么办这是最常见的问题。明明说了“只输出代码”它偏要在前面加一段“好的我来帮你迁移这个函数”。解决办法有几个在系统提示里用更强的措辞比如“禁止输出任何解释性文字第一个字符必须是代码”。在输出解析环节做容错用正则提取代码块忽略代码块之外的内容。如果模型支持用结构化输出功能直接约束输出格式。我一般三个方法一起用实测下来输出格式的稳定性可以到 95% 以上。5.2 校验规则误报太多怎么办先统计每条规则的触发率和人工复核后的真实失败率。如果某条规则触发 100 次但只有 5 次是真失败那这条规则要么修正要么降级。修正的方向通常是放宽匹配条件比如原来要求“所有函数必须有 docstring”可以改成“所有公开函数必须有 docstring”把内部辅助函数排除掉。5.3 任务拆分的粒度怎么把握前面说了 50 到 200 行的经验值但更本质的判断标准是这个任务能不能用一句话说清楚它的验收标准。如果验收标准需要写三段话说明任务太大了继续拆。如果验收标准是“代码能跑就行”说明任务太模糊了需要补充约束。5.4 上下文超了怎么办优先裁剪代码片段保留函数签名和关键逻辑去掉大段的注释和无关的辅助函数。如果还是超就把规范摘要压缩成要点列表把样板示例换成更短的版本。实在不行就拆任务把一个任务拆成两个更小的任务每个任务需要的上下文自然就少了。5.5 多个任务之间有依赖怎么办比如任务 B 需要任务 A 的输出作为输入。这种情况我建议串行执行A 完成并通过校验后把 A 的输出加入 B 的上下文再执行 B。不要试图让 AI 同时处理有依赖关系的任务它理不清的。5.6 常见问题速查表问题现象可能原因排查方向AI 输出为空上下文超长被截断检查 token 数裁剪上下文输出格式混乱系统提示不够强加强格式约束加输出解析容错校验大量误报规则太严统计触发率放宽或降级规则任务反复失败任务粒度太大拆分任务降低单任务复杂度生成代码风格不一致样板示例不统一统一样板风格增加规范约束重试后仍然失败失败原因描述不清细化失败信息明确指出期望行为5.7 几个我踩过的坑第一个坑是过度依赖 AI 的自我解释。我一开始会让 AI 在生成代码后附上一段“我这样写的理由”想借此判断它有没有理解任务。后来发现这段解释经常和实际代码对不上AI 会“编造”一个听起来合理的理由但代码本身并不符合。所以现在我只看代码和校验结果不看 AI 的解释。第二个坑是校验规则写得太细。我曾经写过一条规则检查“函数内变量命名必须符合驼峰式”结果 AI 生成的代码里有一堆循环变量叫i、j全部触发失败。后来我把这类规则改成只检查公开接口的命名内部实现不管。第三个坑是没有给 AI 留“拒绝”的出口。早期版本里如果上下文信息不足AI 会硬编一个实现出来看起来像模像样但完全是错的。后来我在系统提示里加了“信息不足时输出 INSUFFICIENT_CONTEXT”这种情况就少多了。让 AI 学会说“我不知道”比让它假装知道要安全得多。6. 框架的扩展方向与个人体会6.1 从单机脚本到团队级服务最小可用版本跑通之后可以考虑把它服务化。比如把任务定义、上下文装配、执行、校验做成独立的微服务用一个调度器来编排。这样多个开发者可以共享同一套规则库和案例库经验沉淀的效率会更高。另一个扩展方向是接入 CI。把 Harness 作为一个 CI 步骤每次有新的迁移任务提交时自动触发。校验通过的代码自动合并失败的代码留在分支上等人工处理。这样整个流程就完全融入现有的工程体系了。6.2 案例库的持续运营案例库是这套框架里最有长期价值的部分。每次人工介入解决的失败案例都值得花几分钟整理成结构化的条目失败现象、根本原因、正确做法、适用的任务类型。积累到几十条之后上下文装配器就能主动预防大部分常见错误。我自己的案例库现在有大概 80 多条记录覆盖了接口迁移、测试补全、配置修改等几类任务。新任务进来时装配器会根据任务类型和关键词匹配相关案例把避坑提示加进上下文。实测下来有案例提示的任务首次通过率比没有提示的高出大概 20 个百分点。6.3 一点个人体会这套东西搭起来之后我最大的感受是AI Coding 的瓶颈从来不在 AI 本身而在我们怎么组织工作流程。同一个模型放在对话框里用和放在 Harness 里用产出效率能差好几倍。差别不在于模型变聪明了而在于我们给它创造了更好的工作条件——清晰的任务、精准的上下文、自动的校验、沉淀的经验。另一个体会是不要追求全自动。人工介入不是失败而是流程的一部分。关键是让人工介入发生在最需要的地方而不是每个环节都要人盯着。我的流程里人工只做三件事定义任务时补充约束、审核行为层测试用例、处理回炉两次仍失败的任务。其余环节全部自动。这样人的精力集中在最有价值的判断上而不是消耗在重复劳动里。最后分享一个小技巧每次调整框架之后拿一批历史任务做回归测试。看看新版本的通过率、平均重试次数、人工介入率有没有变化。没有度量就没有优化这套框架本身也需要持续迭代。我一般每两周做一次回归看看哪些规则需要调整、哪些提示词需要优化。这个过程本身也是在积累对 AI 行为的理解挺有意思的。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑