NVIDIA公开的SoL-Pi研究,我看了好几遍之后的第一反应不是"又一篇Agent论文",而是"终于有人把Agent Harness自优化这件事当正经课题来做了"。过去一年我见过太多团队在Agent链路上折腾:调Prompt、换底座模型、加工具,结果成功率始终卡在七八成上不去。他们没意识到的是,大部分失败并不发生在模型"懂不懂"的层面,而是发生在外面那层Agent Harness——上下文怎么拼、工具怎么选、重试条件怎么定、轨迹怎么回流——这些框架层的问题,模型再强也救不回来。这篇文章就用工程视角拆解SoL-Pi所回答的四个核心问题,适合正在做Agent平台、智能体框架,或者被Prompt调优折磨到怀疑人生的团队。我尽量把论文思路还原成实际能落地的设计,不堆术语。
1. Harness不是Agent:先把自优化的对象搞清楚
很多团队连口头上都区分不清楚"Agent Harness"和"Agent",更别说在系统设计上把它们当成两个独立层次了。我在不少代码评审里看到的典型结构是:一个Agent类,里面塞了Prompt模板、上下文组装、工具调用、重试逻辑、记忆读写,乱七八糟混成一团。这种代码写出来的时候挺爽,但一旦要优化,根本不知道改哪里。
从概念上理清楚,这三层是不一样的:
- 底座模型:做语义理解和生成,是"大脑"。
- Agent:做任务规划、拆解、决策,决定下一步要调用什么,是"军师"。
- Agent Harness:负责把模型的输入输出、工具调用、外部流程这些内容编排起来,是"操作系统"。
| 层级 | 主要职责 | 典型组件 | 出错表现 |
|---|---|---|---|
| 底座模型 | 语言理解与生成 | LLM/TTS等 | 答非所问、幻觉 |
| Agent | 任务规划与工具决策 | 规划器、工具选择策略 | 路线错误、工具选错 |
| Agent Harness | 执行编排与运行控制 | Prompt模板、上下文窗口管理、重试、日志、记忆读写 | 上下文截断、重试死循环、工具返回不解析 |
SoL-Pi研究的巧妙之处在于,它把Agent Harness当成了可以主动优化的对象,而不是一条写死的执行链路。传统做法是:模型效果不好就换模型,Agent规划不对就改Prompt,但很少有人回过头去改那个承载了Agent的"外壳"——比如上下文修剪策略、工具描述排序、重试开关、甚至整个任务流程的跳转逻辑。
为什么先说这个?因为四个答案里所有的"自优化",优化对象都不是模型参数,而是Harness层的配置和策略。这件事的本质是:模型参数一改,需要全量回归、要重新部署、推理成本可能剧增;但Harness配置是文本、规则、结构化数据,改动成本低、可解释性强、出问题可以秒级回滚。所以自优化的收益和风险边界都被刻意放在了Harness这一层。
SoL-Pi的自优化闭环,大致是这么一条链路:执行并记录轨迹 → 评估成功与失败原因 → 生成Harness的修改建议 → 通过离线回归与影子评估 → 部署到部分流量 → 继续收集数据。这套闭环本身并不新鲜,新鲜的是它把"修改建议"的作用对象从底层模型转移到了Harness。后面四个答案,正好对应这条闭环里最关键的四个环节。
2. 第一个答案:把执行轨迹变成优化信号,而不是只拿来排查故障
几乎每个做Agent的团队都会记录日志,但绝大多数日志只有在线上出了事故才派上用场。SoL-Pi的思路是:执行轨迹是harness自优化最重要的训练材料,别只当故障排查工具用,流量每跑一次都应该让harness变得不那么笨。
具体怎么做?先把一件容易被混淆的事情分开:轨迹成功和任务成功不一定画等号。任务可能最终返回了一个看起来合格的结果,但中间绕了五个工具、重复检索三次,这种轨迹是"结果正确但过程失败"。反过来,任务虽然失败了,中间某几个子步骤的决策可能很清晰,不能全盘丢进负面样本。所以在心态上要接受:轨迹数据是混合矿石,必须经过筛选和提炼。
落到工程上,我建议按下面这套流程处理轨迹:
- 抽取:从harness运行时日志里把每轮对话、每个工具调用、每次重试、每次上下文修剪的节点都标准化成轨迹记录。
- 解析:把轨迹映射成步骤序列,至少包含步骤类型、入参出参、耗时、成本、是否报错、是否重试。
- 过滤:用规则加模型双重判断这个轨迹的"过程质量"。规则负责抓硬问题,比如某个工具调用连续失败三次;模型负责评价软问题,比如"是否走了不必要的步骤"。
- 聚类:将同一类失败的轨迹归组。先看模式再决定怎么改harness,而不是拿到一条失败轨迹就急着改。
- 重写与验证:从成功轨迹里抽取优质片段,作为harness的few-shot示例或工具描述补充;从失败轨迹里提炼反模式,作为后续评估集的负例。
有一个执行轨迹的例子很典型:任务是要查询某个政策条款的最新生效时间。成功轨迹用了两步:先检索政策库,再访问官方公告页确认。失败轨迹却先调用了通用搜索,翻页三次,然后才去政策库,最后还tm因为上下文被搜索页塞爆而发生截断,最终输出幻觉。这种案例我评估的时候几乎天天见——问题根本不在模型能力,而是harness的流程选择没有引导Agent先走高置信度工具。
轨迹要想成为候选优化依据,还需要给轨迹打"版本标签"。我会在每一条日志里记录三个版本号:模型版本、Prompt版本、Harness配置版本。没有版本信息的轨迹,后面做回归集和策略评估时只能当废数据。不少团队踩过这个坑:日志攒了一堆,一提"数据召回"就傻眼,因为不知道某条成功轨迹在哪个配置组合下产出的。
额外提醒一点:别拿失败轨迹直接当负面样本喂给harness做策略调整,原因很简单——LLM生成的失败轨迹往往只是"最终结果不对",但中间一步可能已经把答案推到了正确答案附近。粗暴地给整条轨迹打负分,会把正确的局部决策一起惩罚掉。所以我的习惯是:先把失败轨迹中的局部动作拆出来,再判断哪个环节需要替换。
3. 第二个答案:让Critic模型负责给Harness写"差评",并直接生成修改建议
自优化的核心难点不是"跑",而是"怎么知道哪里该改"。SoL-Pi给出的第二个答案是:引入一个Critic模型,把人工写Prompt优化建议的工作自动化。
LLM-as-a-Judge这个概念大家都不陌生,但很多团队的强应用场景只是给最终回答打个分。SoL-Pi的Critic不一样,它评的不只是最终答案,而是harness执行链路的整体表现。我梳理了一下,至少应该从下面五个维度打分:
- 信息完整性:最终回答是否遗漏了任务要求的关键信息点。
- 工具利用效率:是否调用了不必要工具,是否本可以用更便宜的工具。
- 流程正确性:步骤先后顺序是否合理,是否过早结束导致信息不足。
- 最终答案质量:格式是否规范、推理是否有断点、是否包含幻觉。
- 成本与延迟:总token数、工具调用次数、p95耗时的实际花费。
Critic的输出不能是几百字小作文,而应该是结构化的judgment。最佳实践是固定JSON Schema,至少包含:总体评分、各维度分数、问题定位(具体到第几步)、以及最重要的——harness层面的修改建议。这一步很关键,因为如果Critic只会说"这个回答不好",那它的价值跟一个简单评分器没区别;要让它说"第二步的工具选择不对,应该改为先查询内部知识库;上下文窗口在第三步触发了截断,建议将前置摘要策略提前",这才是harness能执行的优化指令。
实际操作中,我有三点经验:
第一,Critic要跟优化器解耦。Critic只负责评价和给建议,真正动手生成新harness配置的,是另外一个优化器模型。如果Critic同时负责修改,就会陷入自我确认偏误:它已经把链路评坏了,还得靠它改好,很难跳出自己的局限。分开之后,至少可以让不同模型互相制约。
第二,Critic的评价标准要定期人工校准。自优化系统最怕出现feedback loop:Critic发现verbose的回答分高,模型就越写越长,下一个版本Critic继续给长答案高分,最后系统体积膨胀到没人愿意用。我见过一个团队用LLM judge做A/B评估,评估集只有五十条,新配置比旧配置高0.3个百分点就上了生产,结果线上成本翻倍。这种诡异的循环,只能靠人工抽检来打断——我一般要求每周抽五十条Critic判定结果让业务方复核,不一致率超过10%就停用下一轮的自动更新。
第三,Critic使用的评估集要有足够的规模和质量。五十条远远不够,至少要两三百条覆盖典型场景,并且要提前区分Easy/Hard/Normal三档。自优化系统有个隐性惰性:它倾向于把普通的case优化得很漂亮,但在hard case上原地踏步,因为优化hard case太费劲了。如果你不把hard case单独拎出来卡指标,系统就会悄悄退化成"只会做简单任务的高级计算器"。
4. 第三个答案:把工具路由和流程选择做成动态策略,而不是一写定终身
Agent Harness里最容易被忽视的自优化对象,是"任务流程怎么走"这件事。绝大多数团队的Harness里都是写死的:所有请求进来,先做Plan,再一步一步调用工具,最后汇总输出。这种线性结构在Demo里没问题,放到真实业务里就很浪费——简单问题被过度处理,复杂问题处理链路又不够深。
SoL-Pi的第三个答案,是把工具路由和流程选择这个决策本身,变成一个可以持续更新的策略。直白点说,Harness要能在多个候选流程之间自动选路:
- 流程A:直接推理。适合问题简单、答案大概率在模型参数内、不需要外部事实核验的场景。
- 流程B:单次检索增强。适合事实型问题,比如查政策、查价格、查规格,检索一次就够。
- 流程C:多轮检索加反思。适合多跳推理、需要交叉验证的问题,比如对比不同条款、整合多份报告。
为什么要动态选,而不是干脆都用最长的流程C?因为成本和时间不是免费的。所有请求都走流程C,成功率可能确实高那么两个点,但单次推理成本翻三四倍,延迟从两秒变成十秒,落到真实业务里非常难看。所以正确的做法是把"流程选择"当成一个上下文Bandit问题:每次请求进来,系统根据任务特征(问题长度、是否包含数值、涉及领域、用户意图复杂度)和历史成功率,从多个流程里挑一个执行,然后根据执行结果更新策略。
实现的时候,我不建议一开始就上深度强化学习。先从上下文Bandit或者简单的策略树开始,效果足够,解释性还强。特征也不要搞太复杂,就用任务类型、工具类型、上下文窗口用量、历史成功率几项。等积累的数据足够多了,再考虑升级到序列决策模型。
这里有一个特别容易踩的坑:工具列表和流程列表是动态变化的,但策略不能绑定到工具ID上。你今天有五个工具,下个月加了第六个,如果策略学的是"每次必须调用工具A再调工具B",新工具加进来之后策略就失灵了。我的做法是给工具做"能力画像",比如"能不能联网""能不能查数据库""是不是高成本慢工具",让策略基于能力类型而不是具体工具ID做选择。这样工具版本升级、新增替换,都不会让历史学到的策略白废。
另一个实践心得是探索率。上线一个新工具之后,如果自优化策略只按历史成功率选路,新工具永远没有机会被尝试,也就永远不知道它好不好。所以在自优化系统里必须保留一定的探索流量,比如5%的请求允许策略去尝试非最优的流程或新工具。没有这5%的探索,系统优化到最后一定是个局部最优的死胡同。
这个答案对工程架构的直接影响是:Harness不能再是if-else堆出来的代码,而要变成配置驱动的执行引擎。每个候选流程本身是一个可复用的DAG,Harness根据策略选择一个DAG实例来执行。这样策略更新和流程编排才是解耦的,策略说"这次走流程B",Harness就去实例化流程B,而不是修改代码重新发版。
5. 第四个答案:评估门控与自动回滚,给自优化装上安全阀
自优化系统最大的风险,不是优化不动,而是越改越差但没人发现。没有门控的自优化,就是在生产环境做一个没有测试的持续部署,早晚出事故。SoL-Pi第四个答案提到的评估门控与回滚机制,是整条链路里我最看重的部分,因为能不能在一个真实业务里跑起来,取决于这里。
我把门控机制拆成四层,每一层都有明确职责:
- 离线回归集:准备一份固定代表真实业务场景的数据集,大约三百到五百条,覆盖简单、正常、困难三档。任何候选harness配置必须先在这份回归集上跑出不低于当前配置的成绩(成功率、成本上限、延迟p95),否则直接淘汰。
- 影子运行:把新配置部署到影子环境,让它跟线上配置同时处理真实流量,但影子结果不返回用户。通过比较影子结果和线上结果,知道新配置在真实流量上是不是真的更好。这最耗算力,但也是最能避免事故的一层。
- 灰度放量:先放1%流量,观察一小段时间,再逐步放到10%、50%、100%,每个阶段都对照线上基线看指标变化。
- 自动回滚:当指标达到红线的候选配置必须自动回滚,本质上不是修改代码,而是切换配置版本。
关于评估指标,我建议使用一个四指标的融合体系,避免单一指标绑架系统:
| 指标 | 计算方式 | 红线设置建议 |
|---|---|---|
| 任务成功率 | 成功任务数/总任务数 | 低于当前基线2个百分点必须回滚 |
| 工具效率 | 平均每任务工具调用次数 | 高于基线1.5倍需要人工确认 |
| 单任务成本 | 总token成本+API调用成本/任务数 | 高于预算上限直接拦截 |
| P95延迟 | 最长5%请求的耗时 | 超过SLA阈值自动降级 |
这套组合核心考虑了成本和成功率之间的权衡。如果只盯成功率,系统很容易为了"看起来成功"多走几步、多调几个工具,成本悄然升高。只有把成本、延迟也设为硬约束,才不会让自优化变成"花钱买成功率"。
回滚机制有一个细节要在架构上提前考虑:Harness配置必须版本化。每次自优化生成的新配置,都应该像Git提交一样有一个stamped version,包含配置全文、父版本号、上线时间、下线时间、评估报告。我以前见过一个团队,配置存在云数据库里,谁都能改,改完也不留历史,结果某天一个prompt更新导致线上大面积报错,花了整整半天才人工翻出上一版配置。从那之后我强制要求所有Harness配置的修改走版本控制。回滚只是切换版本,不需要重新部署模型或发布服务,这就是把优化对象放在Harness层的巨大红利。
离线回归集还有一点要小心:警惕数据泄漏。如果你的回归集来自历史日志,而这些历史日志是旧Harness跑出来的,那条旧链路里的坏习惯会被新配置学走。最典型的例子是:旧配置遇到复杂问题习惯先问用户澄清,回归集里也就充满了"先澄清再回答"的成功案例,新配置也会倾向多轮澄清而不是自主推理。所以回归集要定期人工审核、加入新发现模式,不能一个集合用半年。
6. 从论文到工程:我落地自优化Harness时会按这个顺序做
如果把SoL-Pi当成一套可以直接抄下来的方案,会摔得很惨。我的判断是,它的价值更多是给出了一个自优化Harness的方向和边界条件,具体到每个团队,还要结合自己的链路情况来设计。但如果让我从零搭建一套类似的系统,我会按下面这个顺序来做。
阶段一:只做可观测性,不碰自优化。先把执行轨迹完整地记录下来。这一步没有技术难度,但要求日志设计得非常细致:每个环节的入参出参、耗时、成本、版本号、重试次数、上下文截断位置。我甚至建议做一个trace viewer,让工程师可以可视化地回放任何一条任务的执行链路。这个阶段预计一到两周,但它决定了后面所有工作的上限。
阶段二:离线闭环。从日志里抽轨迹,建设离线评估集,引入Critic模型,让Critic对历史轨迹批量打分并生成harness修改建议。这个阶段不做线上自动更新,而是人工审核Critic给出的建议,确认能改再手动合入。这样做的好处是,你能在低风险环境下快速观察Critic的建议质量。
阶段三:影子与灰度。离线闭环稳定了再上影子模式,影子跑一到两周,确认新配置与线上基线相比真的有收益,再进入灰度。要不要走到"自动更新"这一步,我建议分团队情况来看:如果你的业务对错误容忍度低(比如金融、医疗),灰度期间人工审核要保留很久;如果你的业务本来就允许带病迭代,可以逐步放开自动更新。
阶段四:策略化流程选择。前三步跑通之后,再尝试把工具路由和流程选择做成动态策略。这里我强烈建议先做"流程级Bandit",就是横向上先支持多功能DAG切换,不要一上来就做动作级的复杂RL。每一步都保持可解释,出问题能说清楚为什么切换到了流程B。
落地过程中,对团队配置的建议是三人最小小组:一个框架工程师负责Harness和日志改造,一个算法工程师负责Critic和策略,一个业务应用owner负责提需求、审核评估集和最终验收。如果只靠一个全栈工程师硬扛,大概率会在影子阶段消耗完热情。
还有一个容易被低估的细节:初始Critic的Prompt要写得挑剔一点。如果你让Critic"从多个维度综合评价",它会倾向于给中等偏上的分数,导致自优化系统提前收敛到平庸状态。我的习惯是让Critic先假定链路有缺陷,先找问题再找亮点,打分分布自然拉开。
另外,数据侧要把合规和脱敏纳入设计。Agent轨迹里经常混着用户对话、业务数据、工具返回内容,直接拿去喂给Critic或训练优化器会有数据安全风险。我见过不止一个团队在推进自优化时忽略这件事,最后法务一票否决。正确做法是在日志入库阶段做字段级脱敏,敏感字段只留存脱敏后的hash值,这样后续做离线优化时心里才踏实。
个人体验是,SoL-Pi这类研究最值得学的不是某个具体模块,而是"先在框架层找收益"的思维方式。很多团队遇到效果问题第一个想到换模型,但从投入产出比看,先优化Agent Harness的门槛更低、反馈更快、回滚风险更小。你在框架层每优化一步,后面换模型、加工具、扩场景时都会跟着受益。这套思路放到任何一个自研Agent系统里,都值得先照着阶段一试一试。