把 Agent 的 Skill 当参数来训:SkillOpt 让一个 Markdown 文件涨 23 个点

最近做 Agent 的人多多少少都碰到过这种局面——你给智能体写了一份"操作守则",结果用着用着发现:要么模型完全不看,要么把守则改飞了,要么改一版好一版烂、根本压不住方差。每次的"经验沉淀",最后都成了一份越来越乱的 prompt。

这篇 SkillOpt(arXiv 2605.23904,Microsoft / 上海交大 / 同济 / 复旦联合出品)干的事很直接:把这份 Markdown 守则当成可训练的"外部参数",按深度学习优化器的纪律去训它

文本空间里跑出来一套 batch、minibatch、learning rate、validation gate、momentum 的完整对应物。最后的产物,就是一份 300–2000 token 的 best_skill.md,部署时模型权重不动、推理时不加任何调用,但在 6 个基准、7 个目标模型、3 种执行框架共 52 个评测格子上,全部拿下最优或并列最优。GPT-5.5 上 direct chat 平均涨了 23.5 分,Codex 涨 24.8 分,Claude Code 涨 19.1 分。


一句话摘要

把 agent 的"自然语言策略文档"当成 frozen agent 的外部状态来训,配一个独立的 optimizer 模型,每一步只允许 add/delete/replace 几条规则,每一次更新都要过 hold-out 验证关,拒绝过的编辑被记下来当负反馈,跨 epoch 还有一个 momentum 风味的慢更新——简而言之,ML 优化器的整套纪律,被原样搬到了文本空间。这套东西不是堆 trick 堆出来的,更像是把 prompt evolution / GEPA / Trace2Skill / EvoSkill 这些前置工作里"少了的那块工程稳定性"补齐了。


论文信息

  • 标题:SkillOpt: Executive Strategy for Self-Evolving Agent Skills
  • 作者:Yifan Yang, Ziyang Gong, Weiquan Huang, Qihao Yang, Ziwei Zhou, Zisu Huang, Yan Li, Xuemei Gao, Qi Dai, Bei Liu, Kai Qiu, Yuqing Yang, Dongdong Chen, Xue Yang, Chong Luo
  • 机构:Microsoft、上海交通大学、同济大学、复旦大学
  • arXiv2605.23904(v2,2026-05-25)
  • 代码:https://aka.ms/SkillOpt

为什么需要这篇论文:现有 skill 学习的几个真实痛点

先说为什么这事值得做。现在大家给 Agent 加"领域能力"的几条路:

  • 改权重:闭源模型不让改、开源模型代价高,对工业部署不现实
  • 手写 prompt / skill:质量靠人,跨场景脆,很难跨模型迁移
  • One-shot 让 LLM 写一份:写得好不好全看运气,不能持续改进
  • GEPA / Trace2Skill / EvoSkill 这一类:会自我演化,但自我演化≠优化——没有"步长"、没有"验证"、没有"拒绝",于是经常一改就崩

我之前在自己项目里也踩过这个坑。给 Agent 写过一版"长期记忆/作业守则",让模型每次失败后自己改一版,刚开始几轮还不错,跑十几轮以后这份文件就开始漂移——加了几条莫名其妙的规则、删掉了一条原本很关键的格式约束,整体表现还不如初版。回头复盘,问题很简单:每次更新没有约束、没有回滚、没有"验证集",跟把 SGD 学习率开到 1e2 一样,能不爆吗?

这正是 SkillOpt 要解决的问题。它的核心论断很有意思:如果 skill 是 adaptation layer,那就该按"训参数"的方式来训它,包括 batch、step size、validation、direction 这一整套


核心思路:把 ML 优化器搬进文本空间

先看 Figure 1,这张图把整篇论文的隐喻讲清楚了:

SkillOpt 概览图:在 skill 空间里做受控的、被验证集 gate 的小步优化

图1:SkillOpt 总览。左边是 skill 空间里的优化轨迹——unbounded 的"ad hoc updates"会做大跳、不稳定;SkillOpt 用 bounded edits + held-out gate,把每一步都压在合理范围内。右上角的对照表是这篇论文最值钱的"心智模型":parameter ↔ skill document、gradient direction ↔ trajectory-derived edit、learning rate ↔ edit budget、validation check ↔ held-out gate

这张图我建议大家盯久一点。它不只是一张装饰图,它就是论文的论点。SkillOpt 最值得借鉴的,不是某个具体模块,而是这套"把 ML 训练直觉一一对应到文本空间"的范式。

具体到流程,看 Figure 2:

SkillOpt Pipeline:rollout → minibatch reflection → bounded edits → validation gate → 可选的 epoch 级 slow/meta update

图2:SkillOpt 完整 pipeline。冻结的 target model 用当前 skill 跑 rollout batch;optimizer 模型把成功/失败轨迹切成 minibatch 做反思,提出 add/delete/replace 三类原子编辑;批级合并去重之后,按 edit budget \(L_t\) 排序裁剪;候选 skill 必须通过 hold-out 验证关才能成为新的 current skill;被拒绝的编辑进 rejected-edit buffer;epoch 级慢更新拿来记住跨批次的稳定模式

我把它的关键几个组件拆开讲——这块是干货。

1. Forward pass:rollout 当 evidence

target model 用当前 skill 在训练集上跑 rollout batch,记录 task metadata、tool call、observation、final answer、verifier feedback。这一批数据就是这一步"梯度"的证据来源。

batch 越小,更新越快但越噪;batch 越大,看得到的"反复出现的失败模式"越扎实。这跟 SGD 里 batch size 的权衡完全一致。

2. Backward pass:minibatch reflection

optimizer 模型——注意,这是另一个独立的 frontier model,不是 target——把 batch 切成 minibatch,先把成功和失败分开。这一步特别关键。

为什么?单条轨迹的反思容易出 anecdotal fix("这次失败是因为 X,加一条规则禁止 X"),但 minibatch 上的反思能暴露反复出现的程序性错误:"agent 总是查错信息源"、"格式规范老忘记"、"调用工具后没核验"。

failure minibatch 提议修正性规则,success minibatch 保留已经 work 的行为。这俩差异处理是个细节,但很合理——你不希望优化器只盯着失败学,把无意中保留下来的好习惯洗掉。

输出:结构化的 add / delete / replace 三类原子编辑(patch 模式),或者一组改写建议(rewrite 模式)。

3. Bounded text updates:文本空间的"学习率"

这是论文最有"工程审美"的一块。

每一步的最大编辑数量 \(L_t\) 就是学习率。merge 之后的编辑池由 optimizer 按预期效用排序,clip 到前 \(L_t\) 个。

支持 constant / linear / cosine / autonomous 四种 schedule,默认 cosine——一开始放开手脚改,后期慢慢收。这跟训神经网络的直觉是一一对应的。

为什么这个设计这么重要?unbounded rewrite 会出现三种灾难:擦掉有用规则、塞入互相冲突的指令、对一次局部失败 overfit。bounded update 强迫每一版只跟前一版相差有限的 token保留连续性,让后面的 optimizer 还能从"哪些改了之后涨/跌"里学到东西

边界细节:step 级 edit 不能覆写"slow update"那一段被保护的字段。也就是说,快慢更新分开管理,避免快更新把跨 epoch 的稳定知识冲掉。

4. Validation gate + rejected-edit buffer

候选 skill 一定要在 \(D_{\text{sel}}\) 上跑一遍,严格涨分才被接受。涨过历史最优,就成为新的 best_skill.md

被拒绝的编辑不会被丢掉——会进一个 epoch-local 的 rejected buffer,连同它造成的分数下跌一起,喂给后续 reflection。这个 buffer 就是 SkillOpt 的"负反馈"。

我自己之前的版本里就缺这一段,结果同一个失败模式被反复"修"了 N 次(每次提议都很合理但每次都让分数掉),白白浪费了一堆 optimizer call。

5. Epoch 级 slow / meta update:文本空间的 momentum

每 epoch 结束,重新采一批训练样本,分别用上一 epoch 和当前 epoch 的 skill 跑,分成 4 类:improvements、regressions、persistent failures、stable successes。optimizer 据此写一段纵向总结进 protected slow-update field。

这块还是要过验证关。但它和 step 级编辑的分工很清晰:step 级捕捉短期局部修正,slow update 捕捉跨批次的长期模式

还有一个 meta-skill,只在 optimizer 端用,不会跟着 deployed skill 一起部署。它记的是"哪些类型的编辑往往会通过验证、哪些总被拒",相当于优化器的元经验,让训练更稳,但不污染最终 artifact。这个分离很优雅。


训练目标的形式化

为了完整起见,论文的形式化也写一下。给定 train/selection/test 划分 \(D_{\text{tr}}, D_{\text{sel}}, D_{\text{test}}\)

\[s^{\star}_{\text{sel}} = \arg\max_{s \in \mathcal{C}(D_{\text{tr}})} \frac{1}{|D_{\text{sel}}|} \sum_{x \in D_{\text{sel}}} r(s)\]

候选集 \(\mathcal{C}(D_{\text{tr}})\) 由 SkillOpt 在训练集上反复采样、反思、bounded 更新、gate 筛选生成;最终在 \(D_{\text{test}}\) 上汇报:

\[\text{Test}(s^{\star}_{\text{sel}}) = \frac{1}{|D_{\text{test}}|} \sum_{x \in D_{\text{test}}} r(s^{\star}_{\text{sel}})\]

这套写法看起来普普通通,但抠一下细节会发现它强调的是"训练分供 evidence、选择分 gate 更新、测试分只用于最终报告"——非常老派的 ML protocol。在 prompt-evolution 这类工作里,这套划分往往是糊的,导致论文里很多"自我提升"的曲线其实是过拟合 selection set。


实验:6 个基准 × 7 个模型 × 3 个 harness

实验范围说实话挺敢的:

  • 基准:SearchQA、SpreadsheetBench、OfficeQA、DocVQA、LiveMathematicianBench、ALFWorld,覆盖 QA / 表格 / 文档 / 数学 / 具身决策
  • 模型:从 frontier 级 GPT-5.5 一路到小模型 Qwen,共 7 个
  • 执行 harness:direct chat / Codex / Claude Code,三种典型 agent 执行回路
  • 52 个评测格子(model × benchmark × harness 的所有组合)

主表(Table 1)的核心结论:52 个格子上 SkillOpt 全部最优或并列最优,对手包括 No skill、Human skill、One-shot LLM skill、Trace2Skill、TextGrad、GEPA、EvoSkill。

GPT-5.5 + direct chat 上的具体数(这是最干的部分):

Benchmark No skill SkillOpt 增量
SearchQA 77.7 87.3 9.6 个点
SpreadsheetBench 41.8 80.7 38.9 个点
OfficeQA 33.1 72.1 39.0 个点
DocVQA 78.8 91.2 12.4 个点
LiveMathematicianBench 37.6 66.9 29.3 个点
ALFWorld 83.6 95.5 11.9 个点
平均 23.5 个点

SpreadsheetBench 和 OfficeQA 接近 +40 的提升,这种数我看到第一反应是怀疑——是不是 No skill baseline 太弱?但仔细想想又合理:表格类任务对"先读结构再写值"、"输出要 round 到指定精度"、"不要依赖 Excel 重算"这种程序性纪律特别敏感,frontier 模型 zero-shot 不会自动应用这些约束,一旦把规则用 SkillOpt 学进 skill 文档,提升空间确实很大。这点后面 Figure 4 那张"学到了什么规则"的图能进一步印证。

跟最强逐格子 baseline 比(不是平均最强,而是每个 cell 上最强的那一个 baseline)——SkillOpt 还能再涨 +5.4 分。这才是真正残酷的对比,因为对手是"per-cell oracle"。

Codex harness 上 +24.8 vs no skill,超 EvoSkill +14.0;Claude Code harness 上 +19.1 vs no skill,超 EvoSkill +3.2。Claude Code 这个 +3.2 不算大,但要知道 EvoSkill 是 2026 同期的强 baseline,能稳定打过它已经能说明问题。


训练曲线:稳定性才是真亮点

三个基准上的训练动态:train rollout / selection best / unseen test 三条线随 epoch 演化

图3:SpreadsheetBench、SearchQA、LiveMath 三个基准上的训练曲线。蓝线是当前 epoch 的 rollout 训练表现,橙色虚线是被验证关接受的最优 skill 在 selection 上的表现(也就是 best_skill.md 的真实分数),绿线是它在 unseen test 上的泛化

这张图挺关键。我要专门点一下 SpreadsheetBench 子图(图3a):

注意 epoch 1 的时候,"Selection best"(橙色虚线)是 0.37 左右,比 Train rollout(0.87)和 Unseen test(0.51)都低。这是为什么?

因为初始 skill 在 selection 集上其实表现还行(baseline 没特别差),但是 epoch 1 的第一个候选 edit 没通过 gate——所以 best_skill.md 还停留在初始状态、被一个保守的下界 reflect 出来。等到 epoch 2 一旦有几个被 gate 接受的 edit,selection best 立刻拉到 0.80 并且之后再没掉过

这就是 validation gate 的价值——它抬地板。整个训练过程中 selection best 是单调非减的(gate 保证了这一点),unseen test 也跟着稳定上升。换成无 gate 的 prompt evolution,曲线绝不会这么干净。

(b) SearchQA 是 headroom 已经不多的任务,最终从 0.83 起步,optimal 区间收敛到 0.86 左右,幅度不大但很稳。(c) LiveMath 上 selection best 一路 0.76+,但 train rollout 反而在 0.55–0.65 震荡——这个 gap 其实暗示训练分布和测试分布不完全对齐,是个值得追踪的点,论文里没深入展开。


消融:每个组件都不是花拳绣腿

Table 2 + Table 3 是 GPT-5.5 自训自测的超参数 + 组件消融。我挑几个我觉得有信息量的(数值都来自原文):

学习率(每步最大 edit 数 \(L_t\)

lr SearchQA Spreadsheet LiveMath
1 85.5 77.5 62.1
2 86.7 77.5 60.5
4(默认) 86.5 78.2 56.5
8 87.0 73.6 66.9
16 86.8 78.2 65.3

很有意思——没有一个 lr 在三个任务上同时最优。LiveMath 偏好大步长(lr=8 时 66.9),Spreadsheet 偏好中等(lr=4 或 16 都不错),SearchQA 几乎不敏感。这跟 NN 训练里"不同任务最佳学习率不同"的直觉完全一致。我倾向于把这点解读为:SkillOpt 的"文本学习率"不是噱头,它真的有 NN learning rate 的特性。

LR scheduler:constant、cosine、linear 各有胜场。SearchQA 和 Spreadsheet 上 constant 反而最优(87.3 / 80.7),LiveMath 上 linear 最优(62.9)。论文默认 cosine 主要是因为它在多任务上较稳,但单任务最优往往是 constant。这点也挺真实。

Mini-batch size:从 1 → 32 扫描,最佳点不一致。Spreadsheet 上 batch=4–16 都不错,LiveMath 上 batch=4 最优(64.5)。一个反直觉的发现是:mini-batch 太大反而掉分——这跟 NN 的批训练略有不同。可能的解释是反思 minibatch 越大,optimizer 越倾向给"概括性的高层规则",但 skill 优化恰恰需要相对具体的 bounded edit。我自己的猜测,论文里没明确论证。

组件消融(Table 3):默认配置(lr=4 + 有 rejected buffer + 有 slow/meta)vs 各种去掉某一项的版本——每一项都对至少一个基准有 1.5–3 分的影响。最稳定的"必带"项:rejected buffer(去掉后 SearchQA 掉 1.5 分、Spreadsheet 掉 2.5 分)和 slow/meta update(这点训练曲线 Figure 3 也印证了)。


Transfer 实验:训一次,多处用

这是我觉得最具工程价值的一段,因为决定了 SkillOpt 这套东西能不能成为大家工具箱里的常驻物。Table 4 跑了三种迁移:

Cross-model(同模型族不同尺寸迁移):在 GPT-5.4 上训出来的 SpreadsheetBench skill,搬到所有更小的 GPT 变体上全部正提升——这意味着可以用一个强模型(也是更贵的 optimizer)训一次 skill,然后部署到便宜小模型上。对成本控制是直接利好。

Cross-harness(跨执行框架迁移):Codex 训出的 Spreadsheet skill 搬到 Claude Code 上,提升达 59.7 个点(GPT-5.5)。这个数我看到的时候愣了一下——这个幅度其实暗示"agentic harness 自身的 zero-shot 能力之间差距很大,但 skill 文档能填平这种差距"。你想想看,对于在做 multi-harness 部署的团队,这套机制可能比"为每个 harness 各自调一遍 prompt"省心得多。

Cross-benchmark(跨基准迁移):在 OlympiadBench 上训的 skill 搬到 Omni-MATH 上,跨 3 个目标模型都正提升。这点幅度没那么夸张,但说明学到的不是基准特定的"刷分技巧",而是有一定泛化的"程序性纪律"。

每一行都是正迁移(原文:"no row falls below the target's no-skill baseline"),这在 transfer 实验里其实挺难得。


学到的"技能"长啥样:Table 6 + Figure 4

最后这块特别有"读后感"。Table 6 显示,最终 best_skill.md 长度从 379 token(LiveMath)到 1995 token(Spreadsheet),中位数约 920 token,accepted edits 数量只有 1–4 次。也就是说,整个训练过程其实只发生了几次"被验证集接受"的更新,但效果显著。

Figure 4 抽了几条学到的规则原文(论文 Figure 4 是文字框,不是图片,我直接引):

  • SpreadsheetBench"先检查工作簿的结构和公式,然后在请求的整个目标范围内写入已计算的静态值,而不是依赖 Excel 重算。"
  • OfficeQA"把 oracle 解析出的页面作为主要证据,锁定表格/日期/单位上下文,按要求 round 后输出值,不加额外标签。"
  • DocVQA"对表格、表单、图表、图例,先把问题绑到具体的 visual 行/表头/字段,然后只复制对齐的答案 span。"
  • LiveMathematicianBench"在'最强陈述'类 MCQ 中,按定理强度排序选项,倾向选有依据的更强结果而非真但弱的推论。"
  • ALFWorld"维护一个 horizon-aware 的 visited/frontier 账本,在同类失败重复后多样化搜索,没拿到目标前别折返目的地。"
  • SearchQA"使用规范实体名(canonical entity choice)。"

我读完这堆规则的第一反应是:这就是一个有耐心的领域工程师做完一天 benchmark 后会写下来的笔记。它们都是程序性的(procedural),不是 instance-specific 的"记住某道题答案"。这点很重要——它意味着 SkillOpt 学到的不是 reward hacking,而是真正的"领域适配"。

更细一点:每条规则都对应frontier 模型 zero-shot 缺失的某种 discipline——OfficeQA 是输出格式纪律、DocVQA 是 evidence binding、ALFWorld 是搜索前沿管理、LiveMath 是 MCQ 中的强陈述偏好。这些 discipline 不是模型不知道,而是它不会自动应用。Skill 文档干的就是把这些隐性纪律显性化、固化下来。


我的判断:这篇论文真正值钱的地方在哪

聊完了,说点主观的。

亮点: 1. 范式价值大于具体方法。把 ML 优化器搬进文本空间,这个对应表(参数↔skill / 学习率↔edit budget / validation↔gate)一旦建立,整套设计就变得"有据可依"——你知道往哪个方向加 trick,知道哪些组件不能拆。这比"提了个新 prompt 演化算法"格局大很多。 2. 工程稳定性确实是这一类方法长期以来缺的一块。Validation gate 抬地板、bounded edit 防漂移、rejected buffer 利用负反馈、slow update 跨 epoch 沉淀——四件事缺一不可,论文用消融逐一验证了。 3. 最终 artifact 是可读、可审、可迁移的 Markdown。这对于实际生产部署友好得多——出问题能直接打开看、可以人工编辑、可以版本管理。比"改了一组隐藏 embedding"在工程上靠谱得多。

疑虑 / 还没解决的问题: 1. Optimizer 模型的成本没被 zero out。论文反复强调"deployment 时 zero inference cost",这个没错。但训练阶段需要一个 GPT-5.5 级别的 frontier 优化器,每个 epoch 跑 N 个 minibatch reflection,token 消耗其实不小。Table 6 的 cost-per-point 数据论文给了,但跨任务对比时 SpreadsheetBench 这种涨幅大的看着划算,SearchQA 这种 headroom 小的就没那么有性价比。 2. 跟 EvoSkill 在 Claude Code 上只赢 +3.2 分,这个 gap 其实不大。同期工作没有被一击即溃。说明 skill 学习的"代际间差距"已经在缩小,SkillOpt 的整体打分优势主要来自 direct chat 和 Codex 这两个 harness。 3. 没有讨论 skill 的"老化"问题。当 target model 升级(比如从 GPT-5.4 升到 GPT-5.5),原来训练的 skill 是不是还成立?论文里 cross-model transfer 是从大到小,但模型升级后的"反向"或"代际"迁移没有覆盖。 4. 训练曲线里 LiveMath 那个 train/test gap没有被解释,可能藏着一个值得追的现象。

对工程实践的启发(这块是给做 Agent 的朋友看的): - 如果你正在做 prompt 演化 / skill 沉淀的工作,一定要加 validation gate——这是单一最有价值的 trick,比 momentum、lr schedule 都重要。哪怕只是"接受新版本前在 50 个固定样本上 eval 一下",都能阻止大部分回归。 - Bounded edit 比 free rewrite 安全得多。让 optimizer 一次只能改 1–4 条规则,杜绝整段重写。 - Rejected edit 别扔,把它当负反馈喂给下一轮 reflection,能省一大批冗余 optimizer call。 - 如果资源紧,先实现最小版本:rollout → minibatch reflection → bounded edit → validation gate,剩下的 slow update / meta 都是锦上添花。 - 用一个"贵但聪明"的 optimizer 训一次 skill,然后让小模型部署它——这套范式值得在生产环境里试。


收尾

把这篇论文放回 2026 年这个时间点的语境里看:reward model、prompt evolution、skill library 这些方向并行走了好几年,单独看每个方向都有各自的进展,但都缺一块"工程纪律"。

SkillOpt 不是在某个方向上纵向突破,而是横向把 ML 训练里那一整套已经验证过的纪律,移植到了文本空间的 skill 学习里。我觉得这种"借鉴邻域成熟范式"的工作,在大模型应用层会越来越多——大家终究会意识到,把 prompt 当字符串、把 skill 当随手写的 README,是早期红利期的奢侈,工业化落地需要更扎实的 protocol。

如果你也在做需要"经验沉淀"的 Agent 系统,这篇论文非常值得花一两个小时仔细读。代码已经放出来了:https://aka.ms/SkillOpt


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我