资讯动态

Agent 总是翻车?让小模型自动修复 harness 代码并迁移到新任务

发布时间:2026/10/26 8:09:53 来源:尧图企业网站定制
很多人调 Agent 调了很久之后都会遇到一个很微妙的感觉模型换到最强的那一档了提示词也反复打磨过了可任务还是会在一些匪夷所思的地方翻车。我去年做浏览器自动化 Agent 时卡了一个星期最后把工具调用循环打出来才发现根源不在模型身上——上一轮工具返回的 JSON 里多了一层嵌套harness 里的解析函数直接抛异常Agent 连错误信息都还没看到就提前终止了。那一刻我就明白了真正决定 Agent 天花板下限的往往是那层没人认真对待的“脚手架”代码。所以当我看到 Johns Hopkins 和 CMU 合作的这篇论文主题是“小模型可以从运行结果学会改进 Agent 的 harness 代码并迁移到新任务”时第一反应是终于有人把这个藏在实践里的痛点系统化了。这篇文章想做的事很直接——既然 harness 代码是 Agent 能不能稳定跑通任务的瓶颈那就让模型自己从失败样本里学会修 harness而且不是硬背某个任务的修法是学到一套可以带到新任务上用的改进模式。对正在做 Agent 工程化、AI 应用落地的人来说这篇东西的启发不止在算法层面更在工程组织方式上。1. 先搞清楚Agent 的 harness 代码到底扮演什么角色1.1 一次工具调用失败暴露出的问题先把场景铺开。假设你写了一个 Agent它能调用一个天气查询工具工具的原始返回长这样{results: {data: [{temp: 21, city: 北京}]}}你的 harness 解析器原本写的是data resp[data]但某个版本工具接口改成了多包一层results于是返回变成{results: {data: [...]}}。解析器抛KeyErrorAgent 进程崩掉任务失败。这种失败有一个共同特征Agent 模型本身的推理没有任何问题它确实选对了工具、给出了正确的参数但 harness 代码没有跟着外部接口的演化走导致整个链路断裂。你去看运行日志会发现错误往往发生在“模型输出之后、环境执行之前”的缓冲区里——也就是说这个错误根本不会成为模型可以观察到的反馈它是系统层面的静默失败。我在实际项目里统计过这类 harness 层错误大概占 Agent 运行失败的 30% 到 40%。剩下的才是模型选错工具、推理不周之类的问题。可大多数人排查时第一反应永远是“提示词不够好”“模型不够聪明”很少人想到去把 harness 的日志打出来看一遍。论文把这个现象点破了也直接解释了为什么很多人换了更大的模型成功率却只涨了几个点——因为瓶颈根本不在推理那一层。1.2 harness 在 Agent 系统里承担的四类职责如果给 harness 下一个工作定义我会说它是连接“模型决策”和“外部世界执行”的所有胶水代码。很多人以为 harness 只是“调 API 的封装”其实远远不止。按我自己的工程习惯它至少要管四类事情协议适配把模型的输出规范成工具可执行的动作再把工具的原始返回规范化成模型能读的上下文。不同工具返回格式千奇百怪这一步是最常出错的。结果解析与错误边界工具可能返回空值、异常、超时、半结构化文本。harness 要在这些情况下给出明确的反馈而不是让进程崩溃。状态管理多轮对话中哪些历史结果要保留、哪些要裁剪上下文窗口怎么分配都归 harness 管。安全与资源限制超时控制、重试策略、并发限制、敏感操作确认。这些不是模型该操心的事是 harness 的职责。这四类职责有一个共同特点它们不需要特别高深的智能但需要极其细致地跟随外部环境变化。也正因为“不需要高深智能”所以长期被当成体力活没人愿意认真维护。可实际上这一层恰恰是 Agent 能否稳定“落地”的关键。1.3 为什么这层代码长期被无视原因说起来有点讽刺harness 代码在项目里往往是最“不性感”的部分。做 Agent 的人天然对模型能力、提示词工程更感兴趣因为那些东西有讨论度、有前沿感而 harness 是纯工程活修一个解析 bug 说出去毫无成就感。再加上很多 Agent 项目是从 PoC 起步的最初只要能跑通一条路径就行harness 写得又急又随意。等到业务量上来各种边界情况冒出来harness 已经变成一个补丁摞补丁的“屎山”。这个时候再去改它成本高、风险大于是大家宁愿继续调提示词、换模型也不愿意动这块代码。论文的价值在于它给出了一个系统性的方案既然 harness 的维护是体力活、是模式化的修补那就让一个小模型专门学这件事。它不是要从零写一个 harness而是基于“当前 harness 代码 失败运行结果”去生成补丁。这个思路绕开了“人工维护成本高”的死结。2. 论文想解决的真实痛点Agent 差“最后一公里”的根源在别处2.1 模型能力的“错觉”换模型解决不了脚手架问题这几年大家有个默认共识Agent 表现不行就换更大的模型。可真换了之后效果往往没那么戏剧性。原因很简单大模型再强也只能在给定的“感知-行动回环”里发挥作用。如果这个回环里有一个环节是坏的——比如工具结果解析错了、历史上下文被截断了、错误反馈没有正确传递——那模型根本没有机会展示它的能力。我打过一个比方模型是车手harness 是赛道。你把车手从普通车手换成 F1 级别的赛道全是坑坑洼洼照样跑不快。论文做的不是换车手而是让一个小模型专门去修赛道。它观察每辆车跑完之后轮胎的磨损、哪段路颠簸得最厉害然后精准地补上那一段路。这个思路的巧妙之处就在于它承认了大模型能力的“错觉”Agent 表现差不等于模型能力差。2.2 手工维护 harness 的隐性成本做 Agent 落地的人都懂harness 的维护成本不在“写”上而在“变”上。一个工具升级了返回结构要改解析换了个数据源要改适配部署到新的运行环境要改路径。每换一次就得把整套链路重新测一遍。这种成本很难量化但真实存在。我见过一个团队花了三个月把一个 Agent 调到 85% 的成功率结果第三方工具一次接口升级成功率直接掉到 60%。他们花了整整两周去定位问题最后发现只是解析器里一个字段名变了。如果当时有一个系统能自动分析失败样本、自动生成解析器的补丁这个两周的工作量可以压缩到几个小时。论文瞄准的正是一个常见的真实场景harness 代码的“维护性修改”是有规律可循的。接口返回结构变了、某个字段不再存在了、错误码多了新类型这些变化往往只涉及代码中很小的局部而且修改方式高度模式化。正因为模式化所以小模型可以学正因为局部化所以小模型的参数量就够用了。2.3 为什么这次的主角是小模型这里有个反直觉的问题既然修 harness 也是写代码为什么不用大模型来做论文选择小模型背后是有考量的。核心原因有三点。成本与速度harness 改进是一个高频迭代过程每次失败样本都要跑一次模型。如果用大模型延迟和费用都扛不住小模型可以在本地、低成本地持续运转。任务的局部性修 harness 通常只需要看“出错的函数 周围的上下文”不需要理解整个项目。任务的理解负担小所以用不到大模型的全局推理能力。安全边界让一个参数量可控、行为可预期的小模型去改执行层代码出问题时的风险比大模型低得多。它是一个“专用施工队”而不是“全能建筑师”。更深一层的原因是数据分布。从运行结果学习改进 harness本质上是学一种“缺陷修复”模式。这个模式在大量任务中是高度重复的——解析失败、超时、空结果、字段缺失、类型不匹配。小模型学这种重复模式信噪比远高于让大模型从零生成整个系统。论文选择小模型是选对了工具。3. 小模型从运行结果中学习改进 harness 的机制拆解3.1 学习闭环运行轨迹与反馈信号如何变成训练数据要理解这个机制先想清楚一个问题模型学什么它学的映射是——给定一段 harness 代码和一次运行失败的痕迹输出一段修补后的 harness 代码。这就需要一个关键设计怎么把“运行失败”编码成模型能理解的输入。论文的做法可以理解为把运行过程“结构化”了。一次 Agent 任务的完整轨迹里重要的不是模型想了几步而是这几样东西模型输出了什么动作调用了哪个工具、传了什么参数工具返回了什么原始返回、异常栈、错误码harness 在哪一步拦截了、抛了什么错最终任务是成功还是失败以及如果失败失败在哪一环把这些信息组装成一个“错误报告”和当前 harness 代码拼在一起作为输入。模型的输出是一个补丁——不是整个文件重写而是针对问题函数的修改。这个设计很关键它把任务从一个“开放式代码生成”问题变成了一个“局部定向修复”问题。为了构建训练数据可以运行一批任务采集成功和失败样本对每一个失败样本人工或半自动地标注出正确的修补方式。论文里的亮点是这个过程可以设计成自动化的让大模型或规则引擎生成“候选修复”再通过重新运行任务验证修复是否有效通过的样本就进训练集。这相当于一个“运行验证”来代替人工校对。3.2 建模方式把 harness 改进当成“代码编辑任务”如果你看过代码大模型的训练方法会发现论文的这个建模思路不算激进它本质上把 harness 改进看作一个代码编辑任务code editing而不是代码生成任务。区别在于代码生成是从无到有写一个新函数代码编辑是在已有代码上精准地做改动。这个区分极其重要。站在 Agent 工程的角度看harness 代码往往是层层迭代出来的系统不可能推倒重来。一个合格的“harness 维护工”需要做到的是“在你现有的代码上用最小改动修掉当前这个 bug”而不是“我给你写一套新的”。所以输出一个“编辑操作序列”比如在 get 前面加一个 fallback 逻辑、修改索引路径、增加 try-except比输出完整代码更符合实际需求。这就带来了训练数据的建模细节样本的“输入”是带错误标记的代码片段和运行日志“输出”是编辑操作描述或 diff。我在工程里接触到的类似场景通常还会让模型输出“修改理由”哪怕只有一句话——这一步看似多余实际对后续调试和训练数据的质量筛选帮助很大。3.3 小模型够用的底气改进通常是局部而模式化的为什么小模型足以胜任我在前面提过“局部性”和“模式化”这里展开说一下。你可以统计一下自己项目里 harness 的错误类型会发现高度同质化工具返回结构变化解析器 KeyError工具输出为空或 None后续逻辑没有判空API 超时没有重试机制多轮上下文过长被截断后字段残缺部分异常没有捕获直接中断这些问题的修复模式说来说去就几十种。它们不依赖高深的语义理解更多是“看到这个错误模式套用对应的修复模板”。小模型在大量这样的样本上训练本质上是把这些修复模板学到了很扎实。模型不需要理解“为什么这个 API 会返回 None”它只需要学会“解析函数拿到 None 时应该返回一个空结构并对外抛一个可读的错误”。我用一个生活中的例子类比这不是培养一名能从原理上设计桥梁的工程师而是培养一名经验丰富的维修工。他见过一百种破裂方式知道每种该怎么补。维修工不需要懂材料力学但他见过的场景足够多下手比桥梁设计师更快更准。harness 维护就是这种“场景经验密集型”的工作正好落到小模型能覆盖的区间。3.4 一个具体案例解析逻辑的自动修复假设当前 harness 里有一段解析工具返回的代码def parse_tool_result(raw): data raw[data] return [item[name] for item in data]某次运行中工具返回变成{status: error, msg: rate limit}harness 直接抛KeyError。采集到的运行结果是tool_execution failed: KeyError(data) traceback: parse_tool_result, line 3 agent_context: tool result contains status:error, no data field小模型拿到这段代码加这份错误报告可能生成的补丁是def parse_tool_result(raw): if data not in raw: return {error: raw.get(msg, unknown), empty: True} data raw[data] return [item[name] for item in data]这个改动非常小但解决了两个问题一是无崩溃二是把错误信息结构化为模型可读的上下文。就这么一个小补丁Agent 后续的决策质量和任务完成率都会明显提升。更重要的是这个修复模式是可迁移的。不管工具是天气 API、数据库接口还是文件系统你都会遇到“返回结构里没有预期字段”的情况。学到这个“加防御性检查”的模式后在新任务上只要看到类似的错误报告小模型就能做出类似的补丁。4. 迁移到新任务什么学到了什么学不到4.1 论文里的迁移设定从任务 A 到任务 B如果说“从运行结果改进 harness”是这个研究的第一个重点那“迁移到新任务”就是第二个更关键的重点。从工程角度想就明白了如果一个模型只能修它训练时见过的那些任务它的价值就大打折扣。真正有用的是——它在任务 A 上学会了“工具返回缺失字段时要加防御性检查”在任务 B 上遇到类似问题时能直接套用这个思路。论文的迁移设定大致是这样的模型先在若干任务比如网页检索、SQL 查询、Python 执行上通过运行结果学习改进各自的 harness然后把它放到一个全新的任务上观察它面对新任务时能不能利用之前学到的通用改进模式。这里的核心判断标准是不重新针对新任务微调模型能直接跑到什么程度。这个设定很像人类工程师的转岗一个维护过电商系统的人去维护金融系统具体业务逻辑完全不懂但“接口防御性编程”“日志结构化”“超时重试”这些工程习惯是直接带得过去的。论文想验证的就是这种“习惯迁移”能否在小模型身上发生。4.2 可迁移的通用模式清单从我对这类研究的理解看可迁移的 harness 改进模式大致可以分为几个家族防御性解析不信任外部输入对缺失字段、空值、类型异常做兜底。无论对接什么工具这一条都成立。错误规范化把千奇百怪的异常KeyError、Timeout、ConnectionError统一包装成“带有分类和可读消息的错误对象”。这个模式在不同任务间完全一致。重试与退避对临时性错误网络抖动、限流增加重试机制并附带退避策略。这是跨领域通用的运维常识。上下文卫生每次工具调用后清理过长或冗余的返回防止多轮历史撑爆上下文。这个逻辑不依赖具体业务。验证与检查在关键步骤之后增加“结果有效性校验”比如检查是否为空列表、是否包含必要字段。相当于给 Agent 加了一道质检工序。这些模式的共性在于它们都是处理“环境不确定性和结构问题”的方法而不是处理“业务内容”的方法。小模型学到的恰恰是前者。这就是迁移能成立的底层原因——确保业务逻辑这些内容层面的东西没有进入学习范围学到的纯工程模式自然就能跨任务使用。4.3 迁移失效的典型场景迁移不是无限的。哪些场景下模型学到的东西带不过去我从工程经验和论文的思路里总结出三类强任务绑定的常量比如某个工具返回中固定字段名为userId另一个工具用account_id。如果模型学到的是“硬编码读取 userId”迁移到新任务就会失效。只有在训练时广泛覆盖“字段名不确定”这类场景模型才会学出“先探测结构再取值”的通用能力。业务语义判断比如判断“这笔交易是否可疑”依赖的是金融领域知识。harness 本身不会涉及这类判断但如果模型被喂了太多带偏置的样本可能会输出带有业务偏见的修复这在迁移时有害无益。环境强相关的路径和配置Windows 路径和 Linux 路径写死或者某个部署目录写死在代码里。这些信息属于具体的运行环境换环境就失效。所以论文探索的重点必然是如何让模型学到更抽象的结构性模式而不是记住某一次修复的“字面内容”。这也给工程上的数据构造提出了要求训练样本要尽量多样化同一个错误模式最好来自不同的工具、不同的字段名、不同的返回结构逼着模型去学“关系”而不是“名字”。4.4 判断迁移是否成立的试金石在我自己判断这类工作是否真正具备迁移能力时有个很简单也很残酷的验证方法给模型一个它从未见过的任务但故意把它上一轮已经修好的 harness 代码清掉看它能不能独立完成修复。如果去掉“曾见过这个任务的记忆”后模型还能靠对类似失败模式的把握给出有效补丁那才是真的迁移。论文里应该也会做类似的消融实验。从公开逻辑推断结论很可能是模型迁移能力取决于训练数据中“错误模式”和“任务类型”的配比。如果训练数据只来自少数几个任务模型容易过拟合到那些任务的字面细节上如果数据覆盖了大量异质的工具、API、返回结构模型就能在更高的抽象层级上形成“工程惯例”。这里也要提醒一句迁移不是“零样本从无到有做对一切”。更稳妥的看法是迁移能力体现在“跑的过的任务数占比”和“修复一次通过率”上。哪怕一开始的修复不完美只要它能基于新的失败结果继续迭代就已经具备实用价值了。5. 这项研究给 Agent 工程带来的三点直接启示5.1 把 harness 当成一等公民来治理论文在认知层面的最大贡献是提醒我们重视 harness 这一层的工程治理。我见过太多 Agent 项目harness 代码写在utils.py里没有测试、没有文档、没有版本管理。项目能把 Demo 跑起来凭的是运气不是工程质量。如果你想把这项研究的思路落地第一步就是改造你的工程习惯把 harness 相关代码和 Agent 的核心逻辑分开独立成模块每个工具接入时为它的解析和适配单独写测试运行失败时harness 的错误信息要能自动归类和统计。这一步做不好后面说的自动化学习、自动修复都无从谈起。数据采集都采不到模型学什么。这不是论文里写的做法而是我从实践中给你的建议在做自动化 harness 修复之前先把 harness 的结构理清楚。你无法管理一个你没有清晰边界的东西对一个散落在各处的“胶水代码”做自动改进等于让模型在垃圾堆里找针。5.2 运行日志的结构化程度决定了模型能学到多少第二点可能更反直觉模型能不能学会修 harness很大程度上不取决于模型而取决于你的日志设计。如果运行日志是一堆无格式的 print 输出模型很难理解失败发生在哪一环如果日志是结构化的、带错误类型标签的、带上下文摘要的模型的学习效率会成倍提高。我在设计 Agent 系统的轨迹日志时至少保留四个字段stage当前处于哪个环节、tool_call调用了什么工具、参数是什么、result工具返回原文的摘要、error错误类型和关键信息。这四个字段拼起来就是一个模型可以读的“病历”。论文的思路本质上就是要给模型建立这样的标准化病历让它能快速诊断问题在哪。从数据角度说日志的字段越规整越容易批量构造训练样本。相反如果日志格式天天变今天有err字段明天改成error_message采集到的数据就很难用。这算是一个工程上的“先付费后回报”前期在日志格式上花的心思后期会在模型的学习效果上成倍还给你的。5.3 小模型管脚手架大模型管推理的协作分工最后一点是架构层面的启发。论文描述的场景如果做成产品会是一个很有意思的“分工协作”模式大模型依然负责任务推理和工具选择这是它擅长的高认知工作同时系统里常驻一个小模型专职监控 harness 层的失败一旦发现某个错误模式多次出现就触发一次“修复任务”生成补丁、跑回归测试、确认无误后合入 harness 代码。这个分工思路放在 Agent 工程里意义很大。顺着它往下想你甚至可以把它做成一个两级系统主链路跑任务时harness 错误会被拦截并进入“维修队列”维修队列里的小模型消化这些错误样本输出补丁到影子环境补丁经过测试后自动上线。这个循环跑起来之后Agent 系统的稳定性会随着运行次数增加而逐渐变好而不是像现在这样上线第一天是表现最好的时候。从我个人的实操体会说最吸引我的就是这一点它让 Agent 系统具备了“自举式修复”的雏形。系统跑得越多积累的失败经验越多harness 越健壮。如果你也想尝试落地我建议不要一上来就训练模型而是先在现有系统上做一个“失败样本→人工修补→回归验证”的半自动循环。跑通了这个循环再逐步把人工替换成小模型路径会顺滑很多。写在最后一个值得试试的方向这篇研究给我的最大触动不是模型参数量多大、实验结果多亮眼而是它提示了一个工程上的心智转变别再默认 Agent 的失败就是模型的锅。先去把你那层没人待见的 harness 代码整理出来给它的错误打上标签把日志结构化然后你才有资格谈“让模型学会修”。对这个方向感兴趣的话我会建议从两个小动作开始第一把你最近一次 Agent 失败的所有日志翻出来数一数有多少失败发生在模型推理之外第二随便挑一个反复出错的解析函数想想如果让一个小模型基于这些日志去改它训练数据你会怎么构造。做完这两件事你应该就能理解这项研究为什么值得关注了。

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

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

免费获取报价 →
↑