Skill1: Unified Evolution of Skill-Augmented Agents via Reinforcement Learning

Paper: arXiv:2605.06130 Code: AlphaLab-USTC/Skill1 Code reference: main @ 95eabbe3 (2026-05-20)

1. Motivation (研究动机)

Skill-augmented agent 的核心承诺是:LLM agent 不必把每个交互 episode 都当成一次性经验,而是把成功轨迹压缩成可复用的自然语言 skill,在之后的任务中检索、调用、再更新。论文把这个生命周期拆成三个互相耦合的能力:selection 负责从 skill library 里找到相关经验,utilization 负责在环境中把经验用好,distillation 负责把新轨迹提炼成未来可复用的 skill。

Figure 1 解读:左侧展示 skill-augmented agent 的闭环:任务进入后先做 skill selection,再在环境里执行,最后把经验 distill 回 skill library。右侧对比 prior paradigms:SkillRL 一类方法只让一部分环节获得 policy gradient,RetroAgent 一类方法把 distillation 交给 external teacher 或独立 reward;Skill1 的目标是让 selection、utilization、distillation 都由同一个 policy agent 产生,并共同服从 task-outcome signal。

现有方法的问题不是“有没有 skill library”,而是 skill lifecycle 的优化被切碎了:一个 policy 可能已经学会如何使用 skill,但如果 selector 总把任务路由到低质量 skill,利用能力会被上游瓶颈锁死;反过来,如果 distillation 只追求某种外部“反思质量”或独立 intrinsic reward,library 可能不断膨胀,却未必增加真正能提高 task success 的策略。

这篇论文要解决的具体问题是:能否只用最终任务成功信号 ,同时给 selection、utilization、distillation 分配可训练的、方向一致的 credit? 这个问题值得研究,因为一旦 skill 选择、执行、沉淀共享同一个 outcome objective,agent 就可以形成跨 episode 的自我改进循环,而不是在每个 episode 内部做短视 RL 或把经验记忆当作静态检索库。

2. Idea (核心思想)

Skill1 的核心 insight 是:同一个 binary/terminal task outcome 可以被拆成两个时间尺度的信号。低频趋势(skill 的长期 utility EMA)更适合给 selection / re-ranking 分配 credit;高频偏差(当前结果相对 library 已覆盖能力边界的超额收益)更适合给 distillation 分配 credit。

关键创新不是新建一个 reward model,而是把 policy 生成的四段内容——query、rank permutation、action trajectory、distilled skill——放进同一次 GRPO-style update,并用 统一优化。这样 query 会因为后续任务成功得到梯度,rerank 会因为 NDCG 对齐长期 skill utility 得到梯度,distilled skill 会因为超过 library 当前最强候选而得到正梯度。

与 RetroAgent 相比,Skill1 不把 skill extraction 主要交给外部 teacher / separate feedback;与 SkillRL 相比,它不只让部分 skill 环节受训,而是让同一个 Qwen2.5-7B policy 覆盖 selection、utilization、distillation 三段生成。根本差异是:prior methods 往往优化“某个环节看起来更好”,Skill1 优化“哪个环节的改变最终能提高 task success”。

3. Method (方法)

3.1 Overall framework:一个 policy 生成完整 skill lifecycle

Figure 2 解读:Skill1 对每个任务 采样 个 rollout。每条轨迹先由 policy 生成自然语言 query ,用 frozen encoder 检索 skill library 的 top- 候选;再由同一 policy 生成 permutation 进行 rerank,选出 top skill ;随后 policy 在环境中执行多轮 action-observation;最后 policy 反思轨迹并生成新 skill 。图中所有 learning signal 都从 terminal outcome 派生。

一条完整 trajectory 写作 Skill 由两部分组成: 描述如何行动, 描述何时适用。利用 skill 时,agent 的动作分布为 直觉上,Skill1 把 skill library 视作 policy 的“外部可塑参数”:参数本身通过 GRPO 更新,library 则通过 admission、utility EMA 和 retirement 更新。二者如果用不同目标优化,就会出现 policy 想要的 skill 和 library 保存的 skill 不一致;Skill1 用同一个 task-outcome 约束两者,让 policy 学会“问什么、选什么、如何用、写回什么”。

3.2 Skill selection:query 检索 + policy rerank

Query 由 policy 生成:。Frozen encoder 用 query 与 skill description 的 semantic similarity 检索候选: 随后 policy 生成 permutation ,top-ranked skill 被注入 utilization prompt。Query 本身没有独立 reward;它是 action 之前的 prefix,因此通过 utilization objective 接受梯度。Rerank 则需要显式 credit,因为同一任务的不同 rollout 可能检索出不同候选集合,不能直接做组内相对比较。

代码实现里,SkillLibrary.retrieve() 先用 SentenceTransformer / TF-IDF 得到 relevance,再可选加入 UCB-style utility bonus;env_manager.pybuild_rerank_obs() 构造 rerank prompt,compute_rerank_rewards() 用候选的 utility_score 计算 NDCG reward。

import math
import torch
 
 
def select_skill(policy, skill_library, task, top_k=3):
    # policy-generated query; implemented through query-generation observation in env_manager.py
    query = policy.generate_query(task)
 
    # SkillLibrary.retrieve: similarity / UCB retrieval over scenario descriptions
    candidates = skill_library.retrieve(query, top_k=top_k, filter_type="both")
 
    # policy-generated permutation; env_manager.apply_rerank_results parses ranked IDs
    ranked_ids = policy.rerank(task, candidates)
    selected = candidates[ranked_ids[0]] if candidates and ranked_ids else None
    return query, candidates, selected
 
 
def ndcg_rerank_reward(predicted_order, candidate_utilities):
    gains = torch.tensor([candidate_utilities[i] for i in predicted_order], dtype=torch.float32)
    discounts = 1.0 / torch.log2(torch.arange(len(gains), dtype=torch.float32) + 2.0)
    dcg = (gains * discounts).sum()
    ideal = torch.sort(torch.tensor(candidate_utilities, dtype=torch.float32), descending=True).values
    ideal_dcg = (ideal * discounts).sum().clamp_min(1e-8)
    return dcg / ideal_dcg

3.3 Reward assignment:把 task outcome 拆成 trend 与 variation

Utilization 的 reward 直接使用任务结果: Selection 的长期质量由每个 skill 的 utility score 表示。每次 rollout 后,对所有 retrieved candidates 更新 EMA: 论文强调更新所有 retrieved candidates,而不是只更新 selected skill,因为共同被同一个 query 检出的 skill 都提供了任务分布相关证据。Rerank reward 是 policy permutation 与 utility ordering 的 NDCG: Distillation 的问题是:新 skill 是否能改善未来任务,当前训练时不可直接观察。Skill1 用当前 outcome 相对 retrieved library best utility 的偏差近似: 如果当前轨迹超过 library 已有能力边界,,说明这条经验值得被写成新 skill;如果只是重复已有强 skill 能做到的事情,variation 接近 0 或为负,distillation 不应被鼓励。

def assign_skill1_rewards(outcomes, retrieved_candidates, alpha=0.05):
    util_rewards, rerank_rewards, distill_rewards = [], [], []
    for outcome, candidates in zip(outcomes, retrieved_candidates):
        # utilization: terminal success/failure
        util_rewards.append(float(outcome))
 
        utilities = [c.get("utility_score", 0.5) for c in candidates]
        best_u = max(utilities) if utilities else 0.5
 
        # distillation: first-order difference over current library boundary
        distill_rewards.append(float(outcome) - best_u)
 
        # non-parametric library trend update, matching SkillLibrary._ema_update
        for c in candidates:
            old = c.get("utility_score", 0.5)
            c["utility_score"] = (1 - alpha) * old + alpha * float(outcome)
            c["count"] = c.get("count", 1) + 1
 
        # rerank reward is computed elsewhere from predicted order vs utilities
        rerank_rewards.append(utilities)
    return util_rewards, rerank_rewards, distill_rewards

3.4 Joint optimization:四段生成在一次更新中协同训练

每个 rollout 有四段 policy-generated text:query 、rerank permutation 、action sequence 、distilled skill s_{new},i}。Skill1 对 action 与 query 使用 GRPO 组内 advantage,对 rerank 使用 REINFORCE-style NDCG objective,对 distillation 使用独立归一化的 GRPO advantage: J^{distill}(\theta)=J_{GRPO}\left(\theta;\{s_{new},1},\ldots,s_{new},G}\},\{\widehat{A}^{distill}_1,\ldots,\widehat{A}^{distill}_G\}\right), Released code 里 agent_system/multi_turn_rollout/rollout_loop.py 明确把 rerank reward 写入 rerank batch,把 distill reward 乘以 lambda_distill 后叠加到 episode reward,并把 query contrastive reward 乘以 lambda_rerank 注入 query phase。

def skill1_train_step(policy, envs, optimizer, lambda_rerank=0.3, lambda_distill=0.3):
    batch = envs.sample_tasks()
 
    query_batch = policy.generate(batch.query_prompts)
    envs.apply_generated_queries(query_batch.text)
 
    rerank_batch = policy.generate(envs.build_rerank_obs()["text"])
    envs.apply_rerank_results(rerank_batch.text)
    rerank_rewards = envs.compute_rerank_rewards() * lambda_rerank
 
    trajectories, task_rewards = policy.rollout(envs)
 
    distill_prompts = envs.distill(trajectories)["text"]
    distilled = policy.generate(distill_prompts)
    _, _, intrinsic, _, infos, _ = envs.step_distill(distilled.text, trajectories)
    distill_rewards = intrinsic * lambda_distill
 
    loss = policy.grpo_loss(trajectories, task_rewards)
    loss += policy.reinforce_loss(rerank_batch, rerank_rewards)
    loss += policy.grpo_loss(distilled, distill_rewards)
 
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    return {"loss": float(loss.detach())}

3.5 Skill library admission、retrieval 与 retirement

新 skill 只有在 task success 时才写入 library。代码中的 SkillLibrary.add() 会把 scenario_descstrategytrajectoryutility_scorecountattempt_type 等字段保存到 JSON memory;若与已有 scenario 高相似(代码阈值约 0.85),则不新增条目而是更新 EMA。容量超过 max_size 时,_retire() 用近似 的 retirement score 保留高 utility 且被多次验证的 skill。

def admit_or_update_skill(skill_library, scenario_desc, strategy, trajectory, success, score):
    if not success:
        return "skip_failed_trajectory"
 
    # SkillLibrary.add: duplicate-like scenario -> EMA update; otherwise append
    skill_library.add(
        scenario_description=scenario_desc,
        strategy_text=strategy,
        trajectory=trajectory,
        initial_score=score,
        attempt_type="success",
    )
 
    # SkillLibrary._retire: keep high-utility, frequently selected skills
    if len(skill_library.data) > skill_library.max_size:
        for item in skill_library.data:
            item["_retirement_score"] = item.get("utility_score", 0.5) * math.log2(item.get("count", 1) + 1)
        skill_library.data.sort(key=lambda x: x["_retirement_score"], reverse=True)
        skill_library.data = skill_library.data[:skill_library.max_size]
    return "admitted"

3.6 论文公式与 released code 实现差异

论文公式与 released code 实现差异:主路径大体一致,但有几处 launch/config 层面的差异会影响复现解读:

  • Group size:Appendix Table 4 写 launch_scripts/alfworld/train_alfworld.shlaunch_scripts/webshop/train_webshop.sh 均设置 group_size=8 并传入 env.rollout.n=$group_size
  • :论文 Table 4 写 re-ranking / distillation loss weight 都是 0.3;ALFWorld script 显式设置 +env.skill_library.lambda_distill=0.3+env.skill_library.lambda_rerank=0.3,但 WebShop script 没有传这两个 override,而 rollout_loop.py 默认值是 1.0。
  • Top- / similarity weight:论文 Table 6 写 Top-K candidates=5w_{sim}=0.6;两个 launch scripts 传 env.skill_library.top_k=3+env.skill_library.relevance_weight=1.0。也就是说 released launch config 更偏向纯 semantic retrieval,再由 rerank 调整。
  • Micro batch:论文 Table 4 写 PPO micro-batch size per GPU=16;ALFWorld script 是 16,WebShop script 是 8。

Code reference: main @ 95eabbe3 (2026-05-20) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
训练入口与真实 launch hyperparameterslaunch_scripts/alfworld/train_alfworld.sh, launch_scripts/webshop/train_webshop.shpython3 -m verl.trainer.main_ppo command; env.skill_library.*; actor_rollout_ref.*; trainer.*
ALFWorld / WebShop environment bridgeagent_system/environments/env_manager.pyAlfWorldEnvironmentManager, WebshopEnvironmentManager
Query generation 与 rerank promptagent_system/environments/env_manager.pybuild_query_generation_obs, apply_generated_queries, build_rerank_obs, apply_rerank_results
NDCG rerank rewardagent_system/environments/env_manager.pycompute_rerank_rewards, _get_candidate_scores
Distillation prompt 与 skill 写回agent_system/environments/env_manager.pydistill, build_distill_text_obs, step_distill
Skill retrieval / utility EMA / retirementagent_system/memory/memory.pySkillLibrary.retrieve, SkillLibrary.add, SkillLibrary.update_utility, SkillLibrary._retire
Query/rerank/distill reward routingagent_system/multi_turn_rollout/rollout_loop.pylambda_rerank, lambda_distill, compute_rerank_rewards, step_distill reward injection
GRPO trainer backboneverl/trainer/main_ppo.py, verl/trainer/ppo/*VERL PPO/GRPO trainer stack

4. Experimental Setup (实验设置)

4.1 Environments / datasets

  • ALFWorld:text-based household environment,需要多步规划与物体交互;论文报告 test split success rate。论文未详细说明 train/test split 的样本数;released code 期望 data/datasets/alfworld/train_verl.parquettest_verl.parquet
  • WebShop:online-shopping simulator,agent 需要搜索并购买符合用户规格的商品;论文报告 WebShop score 与 success rate。论文未详细说明样本数;released code 期望 data/datasets/webshop/webshop_data

4.2 Baselines

论文把 baseline 分为三组:

  • w/o Training:Zero-Shot, ReAct, Reflexion, Mem0, ExpeL。
  • RL-Trained w/o Skills:PPO, RLOO, GRPO, GiGPO。
  • RL-Trained w/ Skills:EvolveR, Mem0 w/ GRPO, SimpleMem w/ GRPO, SkillRL, RetroAgent。作者复现 RetroAgent official implementation,其他 baseline 数字主要借用 prior work。

4.3 Metrics

  • ALFWorld Success Rate (%):六类任务 Pick / Look / Clean / Heat / Cool / Pick2 的成功率与平均值。
  • WebShop Score:WebShop task 的 continuous score,衡量购买结果与用户规格的匹配程度。
  • WebShop Succ. (%):是否成功购买满足条件商品的 success rate。
  • Capability diagnostics:selection precision / average skill utility 、task-outcome reward 、distillation positive rate(新 rollout 超过 retrieved best baseline 的比例)、task-skill similarity、top-skill utility 、library diversity / high-frequency skill count。

4.4 Training config

论文 Table 4/5/6 与 released launch scripts 共同给出的关键信息如下:

  • Base model:Qwen2.5-7B-Instruct;released scripts 默认 Qwen/Qwen2.5-7B-Instruct
  • Retriever / encoder:paper Table 6 写 all-MiniLM-L6-v2 (384-dim);released SkillLibrary 默认 sentence-transformers/all-MiniLM-L6-v2,也可由 EMBEDDING_MODEL_PATH 覆盖。
  • Optimization:GRPO,learning rate 1e-6,KL loss coefficient 0.01,low-variance KL,PPO mini-batch size 256,gradient checkpointing enabled,max prompt length 16,384,max response length 2,048,vLLM tensor parallelism 4,GPU memory utilization 0.7,validation temperature 0.4
  • Environment / hardware:ALFWorld max steps 50,WebShop max steps 15;computational cost analysis 使用 8 H800 80GB GPUs。Released scripts default n_gpus_per_node=8, trainer.total_epochs=150, save_freq=50, test_freq=20

5. Experimental Results (实验结果)

5.1 Main results:Skill1 在两个环境上都是最强整体结果

MethodALFWorld Avg.WebShop ScoreWebShop Succ.
Zero-Shot14.826.47.8
ReAct31.246.219.5
Reflexion42.758.128.8
PPO80.481.468.7
GRPO77.679.366.1
GiGPO90.884.472.8
SkillRL89.985.272.7
RetroAgent94.988.982.3
Skill197.589.782.9

Skill1 在 ALFWorld 平均 success rate 达到 97.5%,比此前最强 RetroAgent 的 94.9%2.6 points;在六个任务类型中五个第一:Pick 100.0(+2.1)、Look 98.6(+7.7)、Heat 99.2(+6.3)、Cool 96.1(+0.6)、Pick2 96.0(+5.0)。Clean 上 Skill1 是 97.3,略低于 RetroAgent 的 99.2,Appendix D 认为该差异统计上不显著。

5.2 Ablation:library、selection、distillation 都不可单独拿掉

VariantPickLookCleanHeatCoolPick2Avg.
Skill1100.098.697.399.296.196.097.5
w/o Select.96.990.398.090.486.585.391.8
w/o Distill.97.488.598.196.187.689.592.4
w/o Library96.771.594.970.771.565.580.9
w/ 99.580.598.8100.090.684.994.0
w/ 100.085.495.596.491.096.294.9
w/ 98.174.995.695.679.587.290.2

Ablation 的结论很清楚:去掉 library 最大幅下降到 80.9,说明参数内化的 RL 不能替代显式 skill reuse;去掉 distillation 后平均 92.4,说明 raw trajectory 直接堆进 memory 不等于高质量 skill;去掉 selection 后平均 91.8,说明即便 utilization reward 还在,错误路由也会拖垮下游执行。把 单独置零分别降 3.52.6 points;一起置零降到 90.2,说明 trend/variation 两个 credit source 互补。

5.3 Co-evolution dynamics:三个能力不是独立上升,而是串联加速

Figure 3 解读:三条指标分别对应 selection precision、utilization reward、distillation positive rate。Full Skill1 的 selection precision 最先收敛,约在 step 20 达到 0.95;高质量 skill supply 随后推动 utilization 与 distillation,在 step 60 左右都达到 0.8。去掉 selection signal 或同时去掉 selection/distillation signal 后,三个指标都会变慢,说明某一阶段的 credit 缺失会通过 lifecycle 传导到其他阶段。

Figure 4 解读:图中衡量 task-skill similarity。Full Skill1 从 0.51 提升到 0.60,而无 selection signal 的版本提升更慢,无 learned selection 的版本几乎保持在较低水平。它验证了低频 trend 信号确实让 policy 生成更精准的 query,而不是只靠原始 embedding retrieval。

Figure 5 解读: 表示每个任务 retrieved top skill 的 utility ceiling。Full Skill1 在 step 85 达到 0.91,两个 ablation 约低 0.10。这说明 variation signal 不是简单鼓励“多写 skill”,而是在鼓励写出能超过当前 library boundary 的 skill。

5.4 Library diversity 与 computational overhead

Figure 6 解读:T-SNE 图比较 convergence 后的 skill library。Skill1 的高频使用 skill 更分散,top-10% most frequently used skills 覆盖更宽的 strategy space;无 selection/distillation credit 的版本集中在少数 popular skills 上。论文解释为:如果新 skill 只是复制已有高效策略,variation reward 不会给正反馈,因此 policy 被迫覆盖 underserved scenarios。

MethodTime/Step@20Time/Step@60Time/Step@100Library@20Library@60Library@100
GRPO (no library)301.3274.1296.7
SkillRL368.1319.0326.6607183
Skill1386.6444.3493.89153,8995,000
w/o Select.367.4406.7521.88923,6935,000
w/o Distill.508.8750.1738.42,2125,0005,000

Skill1 比 no-library GRPO 慢约 1.3–1.7×,主要来自增长中的 library context;selection 本身开销较小,因为 query / rerank 序列远短于环境交互。无 distillation 的版本 step 60 已到 750.1s/step,比 Skill1 的 444.3s/step 慢约 69%,并更早触及 5,000 skill 上限,说明 distillation 同时是质量控制与成本控制。

5.5 Statistical analysis、case studies 与 limitations

Figure 7 解读:Appendix D 对 RetroAgent 与 Skill1 做 3 seeds mean ± std。Aggregate 上 Skill1 是 97.5±0.6,RetroAgent 是 94.9±0.9;Welch’s t-test 给出 t=4.06, df=3.40, p=0.021,低于 0.05。逐任务显著性最强的是 Heat (p=0.004)、Cool (p=0.005) 与 Look (p=0.020);Clean 上 Skill1 落后 1.9 points,但 p=0.147,不显著。

Case study 进一步展示 skill reuse 的两类机制:其一是 failure avoidance,例如 ALFWorld 中“heat plate and put it in cabinet”任务,Skill1 检索到 microwave 而非 stoveburner 的经验,避免不可见 appliance constraint;其二是 error correction,即借助历史 skill 纠正当前任务中容易重复的错误动作。它们说明 library 不是单纯存储成功文本,而是在 selection 与 distillation 共同进化后形成可路由的策略分布。

作者明确的 limitations 有两点:第一,实验只覆盖两个 text-based agent environments,尚未验证 deep search environments 或 visual-observation agents;第二,library 容量固定为 5,000,任务多样性继续扩大时可能成为瓶颈,需要更复杂的 eviction 或 hierarchical organization。Broader impact 也提醒,自主累积 skill 的 agent 可能出现难以预测的 emergent behaviors,因此实际部署需要监控与约束。