news 2026/10/9 11:07:45

Coding Agent 生产级调优:Harness 工程实战与效果提升

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Coding Agent 生产级调优:Harness 工程实战与效果提升

1. 从 Vibe Coding 到生产可用:一个 Coding Agent 调优项目的真实起点

Vibe Coding 这个词这两年被聊得很多,大意就是“凭感觉写代码”——你给 AI 一个模糊的意图,它帮你把代码补全、把功能搭起来,你只需要在关键节点上做判断。听起来很爽,但真把它放到生产环境里,问题就来了:模型生成的代码能跑,但不一定稳;能过编译,但不一定过测试;能过测试,但不一定符合团队的工程规范。这中间的落差,就是所谓的“最后一公里”。

我这次参与的项目,核心目标就一件事:把一个基于华为内部工程体系搭建的 Coding Agent,从“演示能跑”调到“生产敢用”。关键词里出现的 Harness、Agent Harness、Harness 工程,其实指的就是这套东西——它不是模型本身,而是包裹在模型外面的那层“驾驭系统”。你可以把它理解成马具:模型是马,跑得快不快看马,但跑得稳不稳、听不听指挥、会不会跑偏,全看这套马具怎么设计。

为什么这件事值得单独拿出来讲?因为大多数人调 Agent 的注意力都放在提示词上,觉得提示词写好了,Agent 就聪明了。实际做下来你会发现,提示词只占效果影响的两三成,剩下七八成全在 Harness 层:工具怎么定义、上下文怎么裁剪、失败怎么回退、多轮怎么收敛、结果怎么校验。这些东西不解决,你提示词写出花来,Agent 在生产环境里照样翻车。

这篇文章适合三类人看:一是正在做 Coding Agent 落地、被效果问题折磨的工程师;二是想了解 Agent Harness 工程到底在做什么的技术负责人;三是对 Vibe Coding 感兴趣、想知道“感觉写代码”和“生产级代码”之间差在哪的开发者。我会把整个调优过程拆开讲,包括我们踩过的坑、试过的方案、最后留下来的那套配置,尽量做到你读完能直接抄作业。

2. 整体设计思路:为什么 Harness 层才是效果调优的主战场

2.1 先搞清楚 Coding Agent 的能力边界在哪

动手调优之前,我们花了大概一周时间做基线测试,目的不是看 Agent 有多强,而是看它有多弱。具体做法是拿一批真实的历史需求单,让 Agent 从零生成代码,然后统计几个指标:一次通过率、编译通过率、单测通过率、人工 review 打回率。结果挺有意思——一次通过率只有三成出头,但编译通过率能到七成,单测通过率五成左右,人工打回率接近六成。

这组数据说明什么?说明模型本身“会写代码”,但它不知道“写完要自检”。它生成完就交差了,不会主动去跑编译、跑测试、看 lint。这就是 Harness 要补的第一课:把“生成”和“验证”串成一个闭环,让 Agent 自己走完整个流程,而不是生成完就停。

提示:做基线测试时一定要用真实需求,不要用 LeetCode 那种题。真实需求的模糊性、上下文依赖、工程约束,才是暴露问题的关键。

2.2 Harness 层的四个核心模块

我们把 Harness 拆成四块,每一块都对应一类效果问题:

模块解决的问题关键设计点
工具层Agent 能做什么工具粒度、参数校验、返回格式
上下文层Agent 看到什么检索策略、裁剪规则、优先级
控制层Agent 怎么走流程状态机、回退策略、终止条件
校验层Agent 做得对不对编译、测试、lint、规范检查

这四块里,工具层和上下文层决定上限,控制层和校验层决定下限。生产环境里,下限比上限重要得多——你可以接受 Agent 偶尔写不出好代码,但不能接受它写出坏代码还蒙混过关。

2.3 为什么不用“一把梭”的大提示词方案

一开始我们也试过把所有的规则、约束、示例全塞进一个超长提示词里,指望模型自己理解。实测下来问题很明显:提示词超过一定长度后,模型对后半部分的注意力会衰减,规则写了等于没写;而且每次需求变化都要改提示词,维护成本极高,改一处可能影响另一处,根本没法做版本管理。

后来改成“提示词只放角色和总原则,具体规则下沉到 Harness 层”,效果立刻不一样了。比如“生成代码后必须跑单测”这条,写在提示词里模型经常忘,但做成 Harness 的一个强制步骤,模型想跳都跳不过去。这就是把“软约束”变成“硬约束”的价值。

3. 核心细节解析:工具层与上下文层的调优实操

3.1 工具定义:粒度比数量重要

工具层最容易犯的错是“工具越多越好”。我们一开始给 Agent 配了二十多个工具,从读文件、写文件、跑命令到查文档、搜代码,结果 Agent 经常选错工具,或者在一个简单任务上反复横跳。后来砍到八个核心工具,效果反而提升了。

砍的原则是:一个工具只做一件事,且这件事的边界要清晰。比如“读文件”和“搜代码”必须分开,不能让一个工具既读又搜,否则 Agent 不知道该用哪个。再比如“跑命令”这个工具,我们把它拆成了“跑编译”“跑测试”“跑 lint”三个,虽然底层都是执行 shell,但拆开之后 Agent 的选择准确率明显提高。

工具的参数校验也很关键。我们给每个工具加了严格的参数 schema,比如文件路径必须是相对路径、命令必须是白名单内的,这样即使 Agent 生成错误的调用,也会在工具层被拦下来,而不是执行到一半才报错。

3.2 上下文裁剪:让 Agent 看到该看的,而不是全部

上下文层是效果差异最大的地方。同样的模型,上下文给得好不好,效果能差一倍。我们的做法是分三级检索:

  • 第一级是需求相关的文件,直接全文注入,这是必须看到的
  • 第二级是依赖相关的文件,只注入函数签名和关键注释,不注入实现
  • 第三级是参考实现,只注入最相似的代码片段,控制在 200 行以内

这样做的理由是,模型的上下文窗口是有限的,你塞得越多,它越容易迷失。我们实测发现,当上下文超过窗口的 60% 时,模型对关键信息的召回率会明显下降。所以宁可少给,也要给准。

注意:上下文裁剪不是简单的截断,而是要有优先级。我们给每个文件打了相关性分数,按分数排序后从高到低注入,超出预算就丢弃低分文件。

3.3 一个具体的裁剪案例

有个需求是“给订单模块加一个超时自动取消的功能”。如果直接把整个订单模块的代码全注入,大概有三千多行,模型生成出来的代码虽然能跑,但经常忽略已有的状态机约束。后来我们改成只注入状态机定义、订单实体、以及一个类似的超时处理实现,总共不到四百行,模型生成的一次通过率从三成提到了六成多。

这个案例说明,上下文的质量比数量重要得多。你要让 Agent 看到“约束”和“范例”,而不是让它自己去几千行代码里找。

4. 控制层与校验层:让 Agent 自己走完闭环

4.1 状态机设计:把“生成”变成“生成-验证-修复”的循环

控制层的核心是一个状态机,定义了 Agent 在每个阶段该做什么、什么条件下进入下一阶段、什么条件下回退。我们的状态机大概长这样:

  1. 理解需求,输出实现计划
  2. 按计划生成代码
  3. 跑编译,失败则回到步骤 2 修复
  4. 跑单测,失败则回到步骤 2 修复
  5. 跑 lint,失败则回到步骤 2 修复
  6. 输出最终结果

每个步骤都有最大重试次数,超过就终止并报错。这个设计的关键在于,Agent 不再是“生成完就交差”,而是必须走完整个验证流程。实测下来,加了状态机之后,人工打回率从六成降到了三成左右。

4.2 回退策略:不是所有失败都要重来

回退策略是控制层里最容易被忽略的部分。一开始我们的做法是“任何一步失败就全部重来”,结果 Agent 经常在一个小错误上反复重试,浪费大量 token。后来改成分级回退:

  • 编译错误:只回退到生成步骤,保留已有的上下文
  • 单测失败:回退到生成步骤,但注入失败的单测信息
  • lint 失败:只回退到修复步骤,不重新生成

这样改完之后,平均修复轮次从 3.2 降到了 1.8,token 消耗也降了四成。

4.3 校验层的三道关卡

校验层我们设了三道关卡,每道关卡都有明确的通过标准:

关卡检查内容通过标准
编译语法、类型、依赖零错误
单测功能正确性新增代码覆盖率不低于 70%
规范命名、注释、复杂度lint 零警告

这三道关卡里,单测覆盖率是最难达标的。我们的做法是让 Agent 自己生成单测,然后人工 review 单测质量。如果单测本身写得不对,那覆盖率再高也没意义。

提示:不要迷信覆盖率数字,要看单测是否覆盖了边界条件和异常路径。我们后来加了一条规则,要求 Agent 必须为每个新增的 public 方法生成至少一个异常路径的单测。

5. 常见问题与排查技巧实录

5.1 Agent 反复在同一个错误上打转怎么办

这是最常见的问题。Agent 生成代码、编译失败、修复、又失败,来回好几次。排查下来通常是两个原因:一是上下文里缺少关键信息,Agent 不知道正确的写法是什么;二是回退策略太粗,每次都全部重来,导致 Agent 丢失了之前的修复成果。

解决办法是给回退加上“记忆”:每次修复的尝试都记录下来,下次回退时把之前的失败原因一起注入,让 Agent 知道“这条路走过了,别再走”。我们加了这个之后,死循环的情况基本消失了。

5.2 生成的代码能跑但不符合团队规范怎么办

这个问题要靠校验层解决。我们的做法是把团队的规范写成 lint 规则,让 Agent 在提交前必须过 lint。但 lint 只能查格式,查不了设计。所以后来又加了一层“设计 review”,用另一个 Agent 来检查生成代码的设计是否合理,比如是否引入了不必要的依赖、是否破坏了已有的抽象。

5.3 上下文太长导致效果下降怎么办

前面提过,上下文超过窗口 60% 效果就会下降。我们的做法是动态调整:如果检索到的上下文超过预算,就按相关性分数排序,只保留高分部分。同时给 Agent 一个“主动检索”的工具,让它需要更多信息时自己去查,而不是一次性全塞给它。

5.4 常见问题速查表

问题现象可能原因排查方向解决手段
反复修复同一错误回退策略太粗检查是否丢失修复记忆加入失败原因注入
代码能跑但不规范校验层缺失检查 lint 和设计 review补充校验关卡
效果随上下文增长下降上下文超预算检查注入量占比动态裁剪,按分数排序
工具选择错误工具粒度过粗检查工具定义拆分工具,明确边界
生成结果不稳定提示词过长检查提示词长度规则下沉到 Harness

6. 调优后的效果与可复用的配置建议

6.1 调优前后的数据对比

调优大概持续了六周,前后数据对比还是挺明显的:

指标调优前调优后
一次通过率32%61%
编译通过率71%94%
单测通过率53%82%
人工打回率58%27%
平均修复轮次3.21.8

这些数字不是终点,但至少说明 Harness 层的调优是有效的。而且这些改动都是工程层面的,不依赖模型升级,换一个模型也能复用。

6.2 可以直接抄的配置清单

如果你也在做类似的 Coding Agent 调优,下面这套配置可以直接拿去用:

  • 工具层:控制在 8 到 10 个核心工具,每个工具只做一件事,参数加严格 schema
  • 上下文层:分三级检索,按相关性排序,注入量控制在窗口的 50% 以内
  • 控制层:用状态机定义流程,分级回退,加入失败记忆
  • 校验层:编译、单测、lint 三道关卡,单测要求覆盖异常路径

6.3 一个容易被忽略的细节

最后分享一个我们踩过的坑:Agent 的“终止条件”一定要设清楚。一开始我们没设终止条件,Agent 有时候会一直修复下去,直到 token 耗尽。后来加了最大轮次限制和“无进展检测”——如果连续两轮修复没有改善,就强制终止并报错。这个细节看起来小,但在生产环境里能省下大量成本。

提示:无进展检测的判定标准要明确,比如编译错误数没有减少、单测通过数没有增加,都算无进展。

这套东西调下来,我最大的体会是:Coding Agent 的效果调优,本质上不是调模型,而是调工程。模型的能力是给定的,你能控制的是它看到什么、做什么、怎么验证。把这三件事做好,效果自然就上来了。Vibe Coding 的最后一公里,走的其实就是这段工程路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 11:05:33

OpenWorkMate:开源企业级AI工作伙伴框架,让AI真正能干活

1. 从"只会聊天"到"能干活":企业AI工作伙伴到底缺了什么公司里那套AI工具,我用了快两年,最大的感受就一个字:虚。你问它"帮我写个周报",它能给你整出八百字排比句;你问它&qu…

作者头像 李华
网站建设 2026/10/9 11:05:28

2026软件测试面试MySQL核心考点与避坑指南

MySQL 在软件测试面试里,权重一直不低。不管你是面功能测试还是测开,SQL 基础、索引原理、事务隔离级别、甚至死锁排查,都可能是面试官手里的“常规牌”。尤其这两年行业里卷得厉害,光会 select * from table 已经糊弄不过去了&am…

作者头像 李华
网站建设 2026/10/9 11:05:27

MySQL时间函数匹配实战:从格式化到索引优化避坑指南

做后端开发这些年,凡是涉及统计报表、定时任务、数据对账的话,十有八九都要跟 SQL 时间函数匹配打交道。MySQL 里的日期时间函数不算少,但真正用得上的、也最容易出幺蛾子的,基本上就是那套“格式化、转换、加减、求差、比较”的组…

作者头像 李华
网站建设 2026/10/9 11:04:34

数据透视图实操:从数据规范到切片器联动全指南

做数据分析的人都知道,透视表是查数看数的神器。不过今天我想聊的是它的孪生兄弟——数据透视图。很多人学会了透视表,但做透视图时还是用最土的办法:选中原始数据直接插入图表,结果一刷新新增的数据根本不显示,要么就…

作者头像 李华
网站建设 2026/10/9 11:04:07

Vue 3 只读响应式数据:readonly、shallowReadonly 与 isReadonly 实战指南

1. 为什么需要只读响应式数据1.1 从一次数据被意外篡改说起前阵子帮一个团队排查线上问题,现象很诡异:一个订单详情页,用户明明没有点击任何编辑按钮,但页面上的金额偶尔会自己变。查了两天才定位到根因——某个子组件在初始化时&…

作者头像 李华