这两年“Vibe Coding”这个词火得不行,很多人已经习惯了在 IDE 里用自然语言描述需求,让 AI 直接把代码嘣出来。但你有没有发现一个现象:个人项目里玩得风生水起的 Coding Agent,一丢进真实的生产项目里,立刻变得“智商掉线”——不是改错文件,就是上下文爆炸,更别提让它自主完成一个跨模块的嵌入式功能开发了。
我最近半年在华为的业务交付场景里,一直在做一件事:把 Coding Agent 从“能写代码的小工具”调优成“能进生产线的组员”。这中间绕了不少弯子,也沉淀了很多书本上不会写的经验。今天这篇就把这“最后一公里”的调优过程完完整整地拆给你看。无论是正在把 AI 编程能力往团队里推的架构师,还是被 Agent 折腾到头秃的研发工程师,这篇文章应该能帮你少踩几个坑。
1. 先搞清楚:Vibe Coding 和生产级 Coding Agent 的差距在哪
1.1 从“生成代码”到“完成项目”,差的不是模型而是工程闭环
很多人以为 Vibe Coding 干的就是“你说一句话,AI 给你一段能跑的代码”。确实,单文件、单函数的生成场景,现在的模型做得已经非常好了。但生产级 Coding Agent 要解决的是另一件事:在真实代码仓库里,完成一个颗粒度更粗的任务。
举个例子,你在开发一个嵌入式数据采集模块,给 Agent 的指令是“新增一个传感器温度超限告警功能”。它需要做的事情包括:先读懂现有驱动层的数据流、找到数据上报的接口、了解告警模块已有的数据结构,再决定新增代码放在哪个目录、函数命名是否符合工程规范、会不会影响原有内存池的分配策略。这一套流程里,代码生成只占不到百分之三十的工作量,剩下的大部分是代码库理解、上下文筛选、方案规划、工具调用和自检修正。
通俗点说,单文件代码生成像是让一个刚毕业的实习生写一个函数,生产级 Agent 则是让同一个实习生独立负责一个小模块,从摸底到交付全包。这两个场景的难度,完全不是一个量级。
所以我在调优过程中,优先解决的从来不是“模型生成代码的能力”,而是“Agent 的工程闭环能力”——它能不能正确地发现文件、规划步骤、执行修改、验证结果,并在出错时自我纠正。模型能力不足的时候我们可以换模型、加示例,但工程闭环不行,它是骨架,骨架歪了,后面全白搭。
1.2 为什么大模型评测分数高,落地却翻车
在开始调优之前,我也被各种后训练版本的 benchmark 分数迷惑过,以为把模型换到高分版本,Agent 表现自然就上去了。真正跑进生产项目才发现,分数高和能用之间,隔着一条很宽的河。
评测集里的任务通常是隔离的,问题描述清晰、上下文文件已经被整理得很干净、期望修改点非常集中。生产环境则完全是另一副面孔:一个任务可能涉及几十个文件,相关的历史决策分散在老旧注释里,项目里还混着三种不同的代码风格,更别说那些“看起来没用但删了就会炸”的隐式依赖。
唯一清醒的认识是:评测分数只能说明模型的天花板,不能说明 Agent 的可用性。可用性取决于我们能不能把生产项目里的信息,有效地塞进模型有限的上下文窗口,并设计出足够可靠的执行闭环。这也是我后来把所有调优重心都押在“上下文管理”和“执行反馈”上的原因。
2. 生产级 Coding Agent 的整体架构与调优思路
2.1 我们选型的架构基础:规划-执行-验证闭环
第一次搭 Coding Agent 的时候,很多人会走上同一条岔路:拿到一个 Agent 框架就开始连线,把大模型 API、代码仓库路径、终端执行权限往上一拼,就迫不及待地让 Agent 跑第一个任务。结果往往是最初几次看着很惊艳,一旦任务复杂度上来,就频繁出现“改不完整”、“改了不验证”、“报错不知道怎么办”的情况。
实际上,一个能扛住生产级任务压力的 Agent,底层逻辑必须是完整的“规划-执行-验证”闭环。我们的做法是拆成四个阶段,每个阶段都有明确的输入输出:
- 任务理解与规划:把自然语言需求拆成可执行步骤,明确哪些文件需要读、哪些接口需要查、修改的影响面有多大。
- 代码库探查与检索:通过代码索引、语义搜索、符号查询等手段,把与任务相关的代码片段、类型定义、函数调用链收集起来。
- 修改执行与工具操作:调用文件编辑工具写入新代码,必要时执行编译、静态检查或跑测试,验证修改结果。
- 结果自检与修正:读取工具输出,判断当前状态是否符合预期,如果不符合则回到前面的阶段重新调整方案。
这个结构听起来好像很平常,难点在于每个阶段之间的衔接。尤其是规划阶段和探查阶段,容易形成相互依赖的死循环:Agent 还没探查清楚就想规划,规划完发现信息不够又回去探查。
为了避免这种情况,我在设计系统提示词的时候,强制要求 Agent 遵循“先探查、再规划、后执行”的顺序,并把探查动作的结果以结构化摘要的形式记录下来,供规划阶段引用。一旦形成这种模式,Agent 的任务完成率就会有明显提升。
2.2 调优优先级:先稳定再变强
面对一个效果不佳的 Agent,新手最容易犯的错是“头疼医头,脚疼医脚”。任务失败了就改提示词,改完还是失败就继续换提示词,搞到最后提示词膨胀得比项目代码还长,效果依然不稳定。
我把调优优先级总结成一句话:先保证已完成的任务可以稳定复现,再去追求难任务的突破。如果同一个简单任务,今天成功明天失败,那么所有复杂任务的成功都只是随机事件。
具体调优顺序我是这样排的:
- 任务可复现性优先:固定输入、固定项目环境下,同一个任务多次执行结果要一致。如果跳跃太大,先查模型参数、随机性、上下文抖动的问题。
- 上下文可控性优先:Agent 拿到的上下文是不是稳定的关键信息的超集?有没有出现无关信息挤占窗口的情况?
- 工具调用稳定性优先:文件读写、命令执行这些基础操作是否可靠,失败后能不能自动重试和恢复?
- 输出质量约束优先:代码风格、注释规范、改动范围控制,这些属于“做人”层面的约束,是比能力更底层的工厂纪律。
- 较难任务的专项迭代:前面四项稳了以后,再针对性地处理复杂任务中的长链路决策问题。
这个顺序帮我避开了很多无效工作。比如最开始我就发现,系统提示词里多了一句与任务无关的背景说明,就会让 Agent 在某些分支场景下行为漂移,偶然性“翻车”的比例明显上升。删掉之后,复现率立刻上了一个台阶。这种问题,如果你一上来就死磕复杂任务,是根本查不出来的。
3. 核心调优实操:上下文管理与提示词工程的三个关键
3.1 系统提示词:先把“游戏规则”写清楚
系统提示词相当于你给 Agent 定的公司章程。写得太简单,Agent 的行为就会跟着用户问题的措辞随意摇摆;写得太复杂,Agent 又会陷入对规则的无休止分析,反而忘了干活。
我测试下来比较顺手的系统提示词结构,包含五个固定部分:
- 角色与目标:一句话说明 Agent 的身份,以及它面对每一轮任务时的最高目标。
- 工作流程指引:规定任务执行的固定顺序,明确每个阶段的产物格式。
- 工具使用规范:说明哪些场景应该用哪个工具、工具输出的解读方式、失败时如何处理。
- 代码约束与工程纪律:包括修改最小化原则、风格匹配要求、禁止大范围重构、注释规范等。
- 输出格式约定:要求 Agent 在关键节点输出结构化摘要,方便外部系统解析和日志追查。
这里有个小提醒:系统提示词里的每条规则都要有明确的“可验证性”。比如“修改代码时遵循最小化原则”,这个表述太空了,Agent 理解不了什么叫“最小化”。换成“单次任务中,已修改文件的 diff 行数不得超过新增功能代码行数的 1.5 倍”就具体多了。我们在调试中发现,越是可量化的规则,模型遵循得越好;越是“要优雅”、“要合理”这种主观描述,模型就越容易放飞。
3.2 代码库上下文:怎么把“该看的代码”喂给 Agent
上下文管理是整个调优过程中最核心也最容易被低估的一环。大模型的上下文窗口虽然越来越大,但你不可能把一个几十万行代码的仓库全塞进去,塞进去不仅慢,而且注意力会被严重稀释。生产级 Agent 的关键竞争力,就在于怎么在恰当的时间,把恰当的代码片段放到模型面前。
我们采用的方案是分层检索:先通过仓库索引做粗筛,再根据任务类型做精排,最后把结果压缩成上下文块。具体来说:
- 索引层:对代码仓库建立符号索引、文件结构索引和语义向量索引。符号索引解决“这个函数在哪里定义、被谁调用”的问题,语义向量索引解决“哪段代码和当前需求相关”的问题。
- 精排层:把候选文件按“改动的可能性”排序。排序规则包括:文件是否在任务描述中被显式提及、相关符号密度、与已知改动点的依赖关系。这个层决定了 Agent 会不会在一个无关的文件里浪费一整段上下文。
- 压缩层:对检索出的文件按需截取。不是把整个文件塞进去,而是提取函数签名、关键类型定义、核心实现片段和调用关系摘要,组织成结构化的上下文卡片。
上下文窗口的资源要精打细算。我们内部有一个大致的 token 预算分配,用下来效果比较稳定:
| 上下文用途 | Token 预算占比 | 说明 |
|---|---|---|
| 系统提示词与工程规范 | 10% - 15% | 保证游戏规则足够清晰 |
| 用户任务描述与约束 | 5% - 10% | 原始需求及补充信息 |
| 代码库检索结果(上下文卡片) | 45% - 55% | 当前任务最相关的代码 |
| 中间推理与规划缓存 | 10% - 15% | Agent 分步思考的记录 |
| 最终代码输出预留 | 20% - 25% | 防止生成中途被截断 |
这个分配不是固定的,但它给你一个控制思路:如果任务频繁出现“改到一半开始胡言乱语”,多半是输出预留被上下文挤占了;如果 Agent 老是忽略关键文件,那多半是上下文卡片里塞了太多无关内容,真正关键的代码被注意力的洪流冲走了。
3.3 工具调用循环:让 Agent 学会“动手并确认结果”
只有对话能力没有工具调用能力的 Agent 是瘫痪的,它只能给你建议,不能帮你落地。生产级 Coding Agent 的另一个核心能力,是把“看代码、改代码、跑测试、看报错”这一整套动作,变成可循环的自主行为。
我们给 Agent 配置的工具集,设计上刻意保持精简,避免太多扩展接口造成决策负担。核心工具就这几个:read_file用于读取指定文件片段,search_code用于按符号名或语义关键词检索代码,write_file用于写入新代码或修改已有文件,run_command用于执行编译、测试、静态检查等命令,list_dir用于查看目录结构。
工具数量少的好处是 Agent 的选择路径清晰,坏处是某些复杂场景需要多次串行调用。比如在嵌入式项目里,读取一个设备树配置可能需要先list_dir找到目录,再用search_code确认宏定义位置,最后用read_file精确读取。这个过程如果每一步的输出都能正确回填到上下文中,Agent 就能像人一样一步步逼近答案。
工具调用循环里最值得调优的是反馈回填机制。代码修改完以后,必须立刻执行编译或测试,并把输出结果回传给 Agent 进行下一步判断。我在大量跑任务时发现一个规律:Agent 的自我修正能力高度依赖反馈质量。如果编译器报错信息模糊,Agent 经常会做出南辕北辙的修改;如果报错信息精准,Agent 甚至能在四五轮迭代内自己把问题修干净。
所以我们在run_command工具里做了专门的输出清洗逻辑:把编译报错里的绝对路径、噪声 warning、无关输出全部过滤掉,只保留文件和行号、错误级别、错误信息摘要。这套清洗让 Agent 的调试效率提升非常明显。
4. 实战参数配置与效果调优记录
4.1 从混乱到稳定:一组关键的运行时参数
模型参数对 Coding Agent 的影响,和普通聊天场景完全不同。聊天时你可以容忍一点随机性,反正多说两句也无所谓。编码任务讲究的是精确、稳定、可预期,参数设置必须往“收敛”的方向压。
我们最终采用的一组参数,是在大量任务对比后确定的:
| 参数 | 设置值 | 调优原因 |
|---|---|---|
| temperature | 0.2(规划与工具选择)/ 0.4(代码生成) | 规划阶段需要低随机性保证稳定,代码生成稍微放宽避免与已有风格冲突过大 |
| top_p | 0.9 | 兼顾候选输出的多样性,又不至于引入过多低概率的古怪写法 |
| max_tokens | 4096(单次输出上限) | 防止 Agent 在一次输出里试图写完整个模块,强制它拆分步骤 |
| max_iterations | 15(单任务最大执行步数) | 阻断死循环,逼 Agent 在方案层面变通 |
| 重试次数 | 2(工具调用失败时) | 容忍偶发失败,同时避免无脑重试浪费资源 |
如果你现在用的是 Vibe Coding 风格的交互界面,这些参数不一定看得到,但很多 Agent 框架在配置文件里是开放这些项的,建议你花时间改一改,观察同一个任务在默认参数和收敛参数下的差异。我踩过一个很典型的坑:把 temperature 调得太低(低于0.1),结果 Agent 在代码生成时陷入顽固的重复输出,一个简单的排序函数,它硬是用三种方式各写了一遍。把温度稍微抬到0.4,这类问题就消失了。
4.2 针对嵌入式场景的专项调优
近年“嵌入式 Vibe Coding”是个很热门的方向。工业软件、物联网设备、车控固件这些领域,代码对资源占用、实时性、可维护性的要求远比互联网应用苛刻。如果直接拿写后端服务的 Agent 配置去跑嵌入式任务,翻车是必然的。
我们在嵌入式任务上做了几个关键约束调整:
- 强制编译验证:嵌入式代码没有编译通过就等于零。我们在 Agent 的工作流程里把“交叉编译”设为修改动作之后的必选步骤,不允许 Agent 提交未经过编译验证的代码。
- 资源敏感约束:在系统提示词里明确写入“新增代码不得使用动态内存分配(malloc/free),必须使用静态缓冲区”等硬性规则。这不是讨论,是纪律。
- 代码规模限制:嵌入式项目里,一个函数超过50行就会引出一堆可维护性的问题。我们要求 Agent 生成新函数时保持短函数风格,复杂的逻辑必须拆分。
- 寄存器与驱动安全:针对 MCU 操作,强制要求读取寄存器前先确认外设时钟是否已使能,这类约束会直接写进代码生成前的检查清单。
不止是嵌入式,每个业务领域都有自己的“隐式规则”。调优生产级 Coding Agent 的重要工作之一,就是把这些散落在老工程师脑子里的规则,显式地编译进 Agent 的工作流。这一步做完,Agent 的产出才真正有可能通过技术评审。
4.3 评测集怎么建:用真实任务代替 benchmark
评测集建设是效果调优最容易被忽视、但又最关键的一环。前面的参数怎么配、提示词怎么写,如果没有一个可靠的评测标准,你永远分不清改动是变好了还是变坏了。
我们建评测集的原则很简单:**绝不从 benchmark 里搬任务,全部用真实仓库的真实历史变更记录。**具体做法是,从过去三个月的代码提交记录里,挑选那些颗粒度适中、修改范围可控的 MR(Merge Request),把 MR 描述和关联需求作为输入任务,把人工完成的最终 diff 作为参考标准。
评测指标用四个维度:
- 任务完成率:Agent 的最终改动是否完成了需求描述的每一项要求。
- 编译通过率:改动后的代码能否在首次检查时通过编译(允许一次修正机会)。
- 测试通过率:相关模块的单元测试与集成测试是否全部通过。
- 人工 review 修改率:工程师 review 之后,需要手动二次修改的代码行数占比。
这四个指标合成一个“生产可用度”评分。我们当时的迭代目标很朴素:生产可用度低于70%的任务不上线,直到调优达到标准为止。评测集规模不用太大,我建议初期用30到50个真实任务,先把基线稳住,再逐步扩容。评测集质量远比数量重要,宁可少而真实,不要多而失真。
5. 常见问题与排查技巧实录
5.1 高频翻车点汇总
调优这大半年,Agent 在我们面前翻过的车可以排成一列。很多问题你第一次遇到会觉得是模型不行,排查到最后才发现是自己设计的问题。我把高频翻车点整理成了速查表,方便你对号入座:
| 常见问题 | 典型现象 | 常见原因 | 排查思路 |
|---|---|---|---|
| 死循环式修码 | Agent 反复改同一个文件,每次只是换个说法,问题不见好转 | 缺少任务完成定义或反馈回路失效 | 检查 max_iterations 配置、确认编译输出清洗是否正确 |
| 上下文被无关代码挤占 | 关键时刻 Agent 反而忽略了最开始分析出的关键文件 | 检索精排层把无关文件排到了前面 | 审查代码库检索的排序规则,给关键符号加权 |
| 代码风格和项目不一致 | 新增代码用了一种项目里根本不存在的缩进格式或命名规范 | 系统提示词里没有明确风格约束 | 把项目的代码风格规则提炼成可执行要点,写进提示词 |
| 编造不存在的 API | Agent 调用了项目里没有定义过的函数或结构体 | 上下文卡片里的类型定义不完整 | 在检索层补充 API 签名查询,确保候选代码覆盖被调用的接口 |
| 无脑跟随过时注释 | 代码按照注释里的旧逻辑实现,跟不上代码实际行为 | 上下文卡片里同时存在新代码和旧注释,模型没做辨别 | 修改代码摘要生成逻辑,对注释与代码不一致的片段做标记 |
| 重复输出同一段代码 | 生成结果里大段重复,浪费输出预算 | 温度过低或 max_tokens 不足导致上下文自激振荡 | 调整 temperature 和 max_tokens,限制单次输出中重复片段占比 |
这个表是我平时排查问题的出发点。遇到 Agent 表现异常,第一步不是改提示词,而是先对照这个表定位问题层——到底是上下文问题、工具问题、还是约束问题。对症下药,才治得好。
5.2 三个独家小技巧
技巧一:给 Agent 明确写出“任务完成定义”。很多任务失败不是因为 Agent 不会做,而是它不知道自己做到什么程度算“做完了”。比如告警功能,完成定义是“新增告警检测逻辑、对外暴露告警状态接口、相关单元测试全部通过、不影响原有数据上报路径”。把这句话写进任务描述里,Agent 的执行命中率能提升一个档次。
技巧二:用日志回放代替现场复现。Agent 执行的长任务经常是不可完全复现的,尤其是涉及多轮工具调用的场景。我们给 Agent 接了一套日志回放系统,把每一轮的输入、工具输出、关键决策以结构化格式记录下来。任务挂掉之后,直接看日志定位,能省掉大量重跑和猜测的时间。这个习惯对复杂度高的任务尤其宝贵。
技巧三:用“diff 归约法”定位上下文污染。有时候 Agent 的修改结果方向是对的,但行为非常散漫,东改一点西改一点。这时候我习惯把 Agent 最终改动和期望改动做 diff,再把 diff 里的无关改动在上下文里反向搜索,看看是哪个文件里的哪一段代码“带偏”了 Agent。把问题定位到具体的上下文片段,比笼统地改提示词高效得多。
5.3 保留人工审查节点的底线思维
生产级 Coding Agent 调优再到位,我依然坚持一个底线:关键路径上必须有全生命周期的人工审查节点。Agent 可以自主完成代码修改、编译、冒烟测试,但进入仓库合入流程之前的最终 review 和审批,一定要有人签字。
这不是不信任 Agent,而是一种工程责任的延续。生产代码是团队的公共资产,任何一次变更都意味着长期维护成本。Agent 可以在效率上十倍百倍地放大产能,但它不能替代工程师对业务场景的理解,更不能替代技术管理者对代码走向的责任承担。把人工审查定位成流程节点,而不是信息中转站,Agent 的产能优势才能最大化,同时又不牺牲代码质量底线。
气氛都到这了,聊点实在的
要说这半年调优下来的最大体会,其实是:生产级 Coding Agent 的调优,拼的不是某个神奇技巧,而是把每一层都做扎实的工程耐力。提示词、上下文、工具调用、输出约束、评测迭代,每一块看起来都不惊人,但它们咬合在一起,才让 Agent 从一个偶尔惊艳但永远不可靠的“玩具”,变成了真正能进生产线干活的“新工程师”。
最后分享一个小技巧作为收尾:如果你现在还在为 Agent 的稳定性头疼,不妨从“任务完成定义”入手改起——把你项目的典型任务,用一两句话把完成标准写清楚。这个动作成本最低,见效却往往出乎意料地快。等你把这一层打磨顺了,后面再追究上下文、参数这些细节,路就好走多了。