XSkill: Continual Learning from Experience and Skills in Multimodal Agents

Paper: arXiv:2603.12056 Code: XSkill-Agent/XSkill Code reference: main @ b6519250 (2026-05-13)

1. Motivation(研究动机)

现有 multimodal agent 已经能调用 code interpreter、web search、image search、visit 等工具解决复杂任务,但多数系统仍然像“无状态执行器”:每个新任务都从零开始规划,过去轨迹中的成功策略、失败模式、视觉预处理经验和工具组合经验没有被稳定复用。对视觉任务而言,这个问题比纯文本 agent 更明显,因为错误常常不是来自缺少知识,而是来自没有把视觉观察和工具动作绑定起来:例如是否需要先旋转/裁剪图像、是否应该用 code 精确采样颜色、何时用 image search 而不是普通 web search。

这篇论文要解决的具体问题是:在不更新模型参数的前提下,让 multimodal tool-use agent 从自己的多条 rollouts 中持续积累两类可复用知识,并在新视觉任务中检索、改写、注入这些知识。作者把知识拆成两层:Skills 是任务级结构化工作流,负责告诉 agent 如何组织计划和工具链;Experiences 是动作级经验条目,负责告诉 agent 在某类视觉上下文中应避免什么错误、选择什么工具、如何修正执行策略。

这个问题值得研究,因为它把 agent 改进从“重新训练一个更强模型”转移到“维护一个可审计、可编辑、可迁移的外部知识库”。如果做成,系统可以在多模型、多 benchmark 之间复用经验:一个强模型积累出的知识可以迁移给另一个模型;人也可以直接检查 Markdown skills 和 JSON experiences,删除偏置或不可靠经验,而不是只能依赖黑盒参数记忆。

Figure 1 解读:左侧 baseline agent 虽然有工具,但轨迹中缺少对视觉失败模式的复盘,因此容易在图像翻转、小目标定位或颜色识别上反复试错;右侧 XSkill 会把历史经验和技能片段召回,先形成视觉接地的执行计划,再把工具调用组织成更稳定的流程。这个例子说明论文关注的不是“有没有工具”,而是“agent 是否知道在当前图像上下文中如何使用工具”。

2. Idea(核心思想)

XSkill 的核心洞见是:multimodal agent 的可迁移经验不能只存成文本提示,也不能只存成完整工作流;它需要同时保留任务级技能动作级经验,并且两者都必须由视觉观察接地。Skills 解决“如何规划任务和组合工具”的问题,Experiences 解决“在具体视觉上下文中如何选择/修正动作”的问题。

关键创新可以概括为三点:第一,XSkill 在 accumulation phase 从同一任务的多条 rollouts 中做 visually grounded summary 和 cross-rollout critique,分别产出 Skill Library 与 Experience Bank ;第二,在 inference phase 先把新任务分解成多个抽象子需求,再检索相关 experiences,并用当前图像上下文重写经验、适配技能;第三,执行时记录实际使用过的 skills/experiences,形成 usage history,回流到后续 accumulation。

与 AWM、Dynamic Cheatsheet、Agent-KB 等 learning-from-experience 方法相比,XSkill 的本质差异在于:它不是把过去轨迹压缩成单一 workflow/cheatsheet,也不是只做文本检索;它显式区分 skill 与 experience 两个粒度,并用图像内容参与 summarization、retrieval decomposition、experience rewrite 和 skill adaptation,从而降低纯文本 query 与视觉需求之间的 semantic gap。

3. Method(方法)

3.1 Overall framework:双流外部知识库 + 两阶段循环

Figure 2 解读:左侧 Phase I 是知识积累:同一训练任务会产生 条 rollouts,系统先做 Rollout Summary,再用 Cross-Rollout Critique 从成功/失败轨迹中抽取经验更新,最后通过层次化合并减少冗余。橙色流表示 task-level Skill Library ,绿色流表示 action-level Experience Bank 。右侧 Phase II 是测试时求解:系统先把当前视觉任务分解成多个抽象子任务,检索 experiences,随后根据当前图像重写经验、适配 skill,并把它们注入 agent prompt 中执行。

论文把 multimodal tool-use 任务形式化为 POMDP。一个任务实例为 ,其中 是自然语言问题, 是相关图像集合;工具集为 。在每一步 ,agent 根据当前状态 和观察 选择工具动作 ,形成轨迹 并输出答案 。XSkill 要构造外部知识库 使执行模型 在给定任务和知识库时最大化正确概率: 直觉上,XSkill 把“学习”放在外部记忆中,而不是模型参数中。Skills 像一份持续更新的操作手册,记录跨任务可复用的流程模板;Experiences 像一组短小的战术提醒,记录某类图像/工具情境下的具体坑点。两者分开存储是必要的:如果只有 skills,agent 可能有流程但缺少对当前图像细节的 tactical adjustment;如果只有 experiences,agent 会有零散提示但缺少任务级计划结构。

3.2 Phase I:从多路径 rollouts 中积累 skills 与 experiences

Rollout Summary

对每个训练任务 ,执行模型产生 条独立轨迹 知识库模型 接收轨迹集、任务图像、query、ground truth 以及已适配技能,输出 trajectory summary 和 skill fragments: 不是简单摘要,而是压缩关键决策点、工具使用模式、视觉中间结果和失败原因; 则是可追加到 Markdown Skill Library 的流程片段。

Cross-Rollout Critique

随后, 对同一任务的成功与失败轨迹做 contrastive analysis:成功轨迹中哪些工具顺序、视觉处理或验证步骤有效;失败轨迹中哪些动作造成了错误。形式上,给定 summary、ground truth 和当前 rollout 中使用过的 experiences,生成 experience 更新: 更新集合写成 每个操作是 ,其中 add 新增经验,modify 修改已有经验;每条 experience 限制在 words 内,强调要能泛化到相似问题,而不是复述当前样本。

Knowledge Consolidation

经验库如果只追加不整理,会很快变成噪声集合。论文因此加入 hierarchical consolidation:新增 experience 先与已有条目做 embedding similarity 检查,超过阈值的相似条目会合并;如果经验条目数超过 ,系统会进一步压缩。Skill Library 同样会在文档超过 words 时触发 refinement,目的是保留跨任务流程,同时删除样本特定细节。

3.3 Phase II:检索、重写、适配并注入当前任务

Task Decomposition Retrieval

直接用原始 query 检索 experiences 容易失败,因为视觉任务的需求往往隐含在图像中:例如“暗图像处理”“几何比较”“错误恢复”不会总是出现在问题文本里。XSkill 让 根据任务描述和图像把任务分解成 每个 是一个抽象技术需求。然后对每个子任务 query 计算 embedding ,从经验库中召回 top- 条: 论文实验中 retrieval top-,embedding model 为 text-embedding-3-small

Experience Rewrite 与 Skill Adaptation

检索到的 experiences 通常是通用建议,不能直接塞进 prompt。XSkill 会用当前任务和图像把它们重写成可执行提示:例如把“使用视觉处理定位颜色区域”改写成“先裁剪出租车侧面文字附近区域,再用 HSV 而非 RGB 判断颜色”。Skills 也会被适配:基础 Skill 文档与 retrieved experiences、当前 task description、images 一起输入 ,输出 task-specific skill guidance。执行时,adapted experiences 与 adapted skills 一起注入 的 system prompt。

Usage history 回流

推理过程中系统记录实际使用过的知识: 这些 usage history 会回流到下一轮 rollout summary 和 critique 中,让系统知道哪些知识真正被调用、哪些知识可能需要更新。论文当前实验主要展示 single accumulation-then-test cycle,但架构本身支持随着新任务持续迭代。

3.4 Released code 对应实现

Code reference: main @ b6519250 (2026-05-13) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
主入口与 rollout 执行eval/infer_api.pyargument parser, rollout orchestration, --rollouts-per-sample
Prompt 注入、experience retrieval、skill inferenceeval/infer_api_utils.pyretrieve_experiences_for_sample, _process_skill, execute_pipeline_parallel_processing
Rollout Summaryeval/exskill/trajectory_summary.pysummarize_rollouts
Cross-Rollout Critiqueeval/exskill/experience_critique.pyintra_sample_experiences
Experience merge / pruningeval/exskill/experience_manager.pybatch_merge, _process_add_with_merge, _reduce_experiences_to_limit
Experience retrieval / decomposition / rewriteeval/exskill/experience_retriever.pyExperienceRetriever.retrieve, retrieve_with_decomposition, rewrite_experiences_for_task
Skill generation / merge / adaptationeval/exskill/skill_builder.pygenerate_skill_for_sample, merge_skills, adapt_skill_for_task, refine_skill_document
Reference scriptseval/run_exskill_train.sh, eval/run_exskill_inference.shCLI flags for Phase I / Phase II

论文公式与 released code 实现差异:论文实验报告 rollouts、Max Operations per Sample = 4、Max Turns = 20;eval/infer_api.py 的 parser default 确实给出 --rollouts-per-sample=4,但 eval/run_exskill_train.sh 这个发布版参考脚本设置 ROLLOUTS_PER_SAMPLE=2EXPERIENCE_MAX_OPS=3MAX_SAMPLES="16",且 REASONING_MODEL_NAME / EXPERIENCE_MODEL_NAME 留空。因此仓库脚本更像可运行 demo/template,不是完整复现 Table 2 的实验配置;笔记中的实验超参数以论文 Table 8 为准,并单独记录 released script 的覆盖值。

Pseudocode:rollout summarization

def summarize_rollouts_for_task(traj_paths, sample_dir, llm_kb):
    traj_paths = normalize_traj_paths(traj_paths)
    metadata = load_sample_metadata(sample_dir)
    all_images = scan_images(sample_dir)
    image_captions = describe_original_and_tool_images(all_images, llm_kb)
 
    summaries = {}
    for rollout_id, path in traj_paths.items():
        jsonl = read_jsonl(path)
        visualized_trace = replace_image_refs(jsonl, image_captions)
        prompt = build_rollout_summary_prompt(
            question=metadata["question"],
            ground_truth=metadata.get("ground_truth"),
            trajectory=visualized_trace,
        )
        summaries[rollout_id] = llm_kb.generate(prompt)
    return summaries

Pseudocode:cross-rollout critique and experience updates

def critique_experiences(question, ground_truth, summaries, llm_kb, used_experiences, max_ops=3):
    formatted = []
    for i, (rollout_id, summary) in enumerate(summaries.items(), start=1):
        formatted.append(f"Trajectory {i} ({rollout_id}):\n{summary}")
 
    prompt = build_cross_rollout_critique_prompt(
        question=question,
        ground_truth=ground_truth,
        trajectory_summaries="\n\n".join(formatted),
        used_experiences=used_experiences,
        max_ops=max_ops,
    )
    raw_updates = llm_kb.generate(prompt)
    updates = parse_json_operations(raw_updates)
    return [op for op in updates if op["option"] in {"add", "modify"}]

Pseudocode:experience consolidation

def batch_merge_experiences(existing, updates, retriever, llm_kb, threshold=0.70, limit=120):
    provider = ExperienceMemoryProvider(existing, retriever)
    to_modify = []
 
    for op in updates:
        if op["option"] == "modify" and op.get("modified_from") in provider.experiences:
            to_modify.append(op)
            continue
 
        new_text = op["experience"].strip()
        similar = provider.search_similar(new_text, top_k=3, similarity_threshold=threshold)
        if similar:
            merged = llm_kb.generate(build_merge_prompt([new_text, *similar.values()]))
            provider.modify_experience(next(iter(similar.keys())), merged)
        else:
            provider.add_experience(next_exp_id(provider), new_text)
 
    for op in to_modify:
        provider.modify_experience(op["modified_from"], op["experience"])
 
    if len(provider.experiences) > limit:
        provider.experiences = reduce_experiences_to_limit(provider.experiences, limit, llm_kb)
    return provider.to_dict()

Pseudocode:decomposition-based retrieval and rewrite

def retrieve_and_rewrite_experiences(sample, retriever, llm_kb, top_k=3, min_similarity=0.0):
    task = sample.get("problem", sample.get("question", ""))
    images = load_images_for_retrieval(sample)
 
    subtasks = llm_kb.generate_json(
        build_task_decomposition_prompt(task_description=task),
        images=images,
    )
    retrieved = {}
    for subtask in subtasks:
        query = subtask["query"]
        hits = retriever.retrieve(query=query, top_k=top_k, min_similarity=min_similarity)
        retrieved.update(hits)
 
    if not retrieved:
        return {}, ""
 
    rewritten = llm_kb.generate(
        build_experience_rewrite_prompt(task_description=task, experiences=retrieved),
        images=images,
    )
    return retrieved, rewritten

Pseudocode:skill adaptation and prompt injection

def build_xskill_system_prompt(sample, base_prompt, skill_library, retrieved_exps, llm_kb):
    task = sample.get("problem", sample.get("question", ""))
    images = load_images_for_retrieval(sample)
 
    adapted_skill = adapt_skill_for_task(
        base_skill=read_text(skill_library),
        experiences=retrieved_exps,
        task_description=task,
        llm=llm_kb,
        images=images,
    )
 
    prompt = base_prompt
    if adapted_skill:
        prompt += "\n\n# Relevant Skill Guidance\n" + adapted_skill
    if retrieved_exps:
        prompt += "\n\n# Relevant Experience Tips\n" + format_experiences(retrieved_exps)
    return prompt

4. Experimental Setup(实验设置)

Datasets and splits

DatasetDomainTotalTrainTestPartition
VisualToolBenchHybrid Tool Reasoning1,191100214只保留 single-turn hybrid tasks
TIR-BenchTool-Integrated Reasoning1,215100200过滤出 5 类,共 430 samples
MMSearch-PlusMultimodal Search311100211random sampling
MMBrowseCompMultimodal Browsing130-130全部用于 OOD testing
AgentVistaUltra-challenging Tasks209100109random sampling

TIR-Bench 过滤后的类别分布为:refcoco train/test = 27/60,maze = 27/51,instrument = 22/39,ocr = 15/28,contrast = 9/22。

Tool sets

DatasetCodeWeb SearchImage SearchVisit
VisualToolBench-
TIR-Bench---
MMSearch-Plus
MMBrowseComp
AgentVista

工具定义:code interpreter 负责 Python 图像处理/计算/分析;web search 做文本查询;image search 做 reverse image search;visit 访问指定网页并抽取内容。

Baselines and metrics

Baselines 包括:No Tools、w/ Tools、Agent Workflow Memory (AWM)、Dynamic CheatSheet (DC)、Agent-KB。主指标为 Success Rate,论文对每个任务做 independent rollouts,并报告:Average@4(4 次 rollout 平均成功率,衡量可靠性)和 Pass@4(至少一次成功的任务比例,衡量探索上界)。开源模型附录还报告 Avg Turns,即每个任务平均工具调用次数。

Models and hyperparameters

主实验使用 Gemini-2.5-Pro、Gemini-3-Flash、GPT-5-mini、o4-mini;开源模型补充实验使用 Qwen3-VL-235B-Instruct 与 Qwen3-VL-32B-Instruct。Gemini-2.5-Pro 和 Gemini-3-Flash 用自己的轨迹积累知识;GPT-5-mini、o4-mini 直接使用 Gemini-3-Flash 积累的知识来测试 cross-model transfer。硬件方面论文未给出本地 GPU,因为执行与知识库操作主要依赖 API MLLM;released repo 的模型名和 endpoint 也留作环境变量。

关键配置(论文 Table 8):

  • General inference:temperature ,top-,max tokens per turn = 8192,max turns = 20,max images = 100,rollouts per sample
  • Phase I Rollout Summary:summarization temperature = 0.6,max tokens = 12288;image summary max tokens = 2048。
  • Phase I Cross-Rollout Critique:critique temperature = 0.6,max tokens = 12288;max experience length words;max operations per sample = 4。
  • Knowledge Consolidation:merge threshold ;max experience items ;max skill document length words;embedding model = text-embedding-3-small
  • Phase II Retrieval / Adaptation:decomposition temperature = 0.3,decomposition max tokens = 2048,retrieval top-,minimum similarity ;experience rewrite 和 skill adaptation temperature 均为 0.3、max tokens 均为 8192。

Released code 中 eval/run_exskill_train.sh 的可运行模板覆盖了部分值:MAX_TOTAL_TOKENS=32768MAX_TURNS=20MAX_IMAGES=100TEMPERATURE=0.6TOP_P=1.0EXPERIENCE_MAX_OPS=3EXPERIENCE_MAX_ITEMS=120EXPERIENCE_RETRIEVAL_TOP_K=3SKILL_MAX_LENGTH=1000ROLLOUTS_PER_SAMPLE=2MAX_SAMPLES="16"。因此复现实验时不能直接把该 shell script 当作论文主表配置,需要把 rollout 数和样本范围调回论文设置。

5. Experimental Results(实验结果)

Main in-distribution results

论文主表在 VisualToolBench、TIR-Bench、MMSearch-Plus、AgentVista 四个 in-distribution benchmarks 上报告 Average@4 / Pass@4。XSkill 的平均结果如下:

ModelXSkill Avg Average@4XSkill Avg Pass@4w/ Tools Avg Average@4w/ Tools Avg Pass@4Agent-KB Avg Average@4Agent-KB Avg Pass@4
Gemini-2.5-Pro28.6345.9223.8741.0424.9941.37
Gemini-3-Flash40.3458.9533.6353.0634.8853.71
GPT-5-mini23.1938.9020.6136.1320.8736.52
o4-mini23.7239.0719.5633.6920.5535.25

最强提升出现在 Gemini-3-Flash:Average@4 从 w/ Tools 的 33.63 提升到 40.34(+6.71),Pass@4 从 53.06 提升到 58.95(+5.89)。Gemini-2.5-Pro 上,XSkill 相比 w/ Tools 的 Average@4 提升 4.76,相比 Agent-KB 提升 3.64。GPT-5-mini 和 o4-mini 不参与自身积累,而是使用 Gemini-3-Flash 的知识,仍有平均提升,说明知识库有一定 cross-model transferability。

更细粒度看,Gemini-3-Flash + XSkill 在 TIR-Bench 达到 47.75 / 75.00,相比 w/ Tools 的 32.37 / 58.50 提升很大;在 VisualToolBench 达到 46.50 / 64.02,相比 w/ Tools 的 41.94 / 60.75 也有提升。Gemini-2.5-Pro + XSkill 在 VisualToolBench 为 30.49 / 46.73,在 MMSearch-Plus 为 27.96 / 44.08,均超过 AWM、DC、Agent-KB。

Ablation:两个知识流和两个阶段都必要

SettingAverage@4Pass@4Δ Avg@4
Ours - Full Pipeline30.4946.73-
w/o Experience27.4542.52-3.04
w/o Skill26.6441.12-3.85
w/o Experience Manager26.4042.06-4.09
w/o Skill Manager26.8742.99-3.62
w/o Task Decomposition29.2144.86-1.28
w/o Task Adaptation28.9744.39-1.52
w/ Tools25.3540.65-5.14
No Tools20.9128.97-9.58

Ablation 说明 Phase I 的知识质量比 Phase II 的检索机制更关键:移除 Experience Manager 和 Skill Manager 分别带来 -4.09 与 -3.62 的 Average@4 下降;但移除 task decomposition / adaptation 也会下降 -1.28 / -1.52,说明检索覆盖和上下文改写不是可有可无的 prompt trick。

Behavior analysis:skills 降低执行错误,experiences 改变工具分布

Figure 3 解读:该图比较 VisualToolBench 上 w/ Tools、Skill Only、Skill & Exp 的错误类型。Skills 明显减少 syntax / runtime 等工具执行错误,说明 task-level workflow 能让 agent 更规范地组织代码和工具调用;Experiences 的作用更偏 tactical,不一定直接减少所有执行错误,但会改变何时调用哪类工具。

工具分布证据如下:

Dataset / SettingCodeSearch-WSearch-IVisit
VisualToolBench w/ Tools66.6331.70-1.66
VisualToolBench Skill Only65.9631.10-2.82
VisualToolBench Exp Only74.4922.03-2.56
VisualToolBench Skill & Exp76.9721.12-1.58
MMSearch-Plus w/ Tools6.1871.0715.437.32
MMSearch-Plus Skill Only7.9467.0717.877.12
MMSearch-Plus Exp Only13.2156.1224.636.04
MMSearch-Plus Skill & Exp14.3755.0823.895.66

在 VisualToolBench 中,Experience Only 把 code interpreter 使用率从 66.63% 提升到 74.49%,full pipeline 达到 76.97%;在 MMSearch-Plus 中,code interpreter 从 6.18% 提升到 14.37%,image search 从 15.43% 提升到 23.89%。这说明 experiences 捕捉到的是“在这种任务里应优先使用哪类工具”的动作级策略。

Figure 4 解读:该图展示 VisualToolBench 上不同 rollout 数量的效果; 对应 w/ Tools baseline,随着 rollouts 增加,XSkill 的性能持续提升。它支持论文的核心假设:多路径尝试提供了足够的成功/失败对比信号,knowledge accumulation 才能提炼出更稳健的经验和技能。

Cross-task / cross-model transfer

Figure 5 解读:OOD 实验把 VisualToolBench 积累的知识迁移到 TIR-Bench,把 MMSearch-Plus 积累的知识迁移到 MMBrowseComp。灰色虚线是 w/ Tools baseline,XSkill 在不同 backbone 上都高于强 baseline,论文文本总结为平均比 Agent-KB 高约 2–3 points。关键原因是 consolidation 去掉了样本特定细节,而 task adaptation 又会把通用知识重新贴合当前视觉任务。

开源模型补充实验显示迁移并非无条件有效:

ModelSettingVTB Avg@4VTB Pass@4VTB TurnsMMS+ Avg@4MMS+ Pass@4MMS+ Turns
Qwen3-VL-235Bw/ Tools11.8019.623.828.7614.693.83
Qwen3-VL-235BAgent-KB12.8520.093.8810.2917.544.71
Qwen3-VL-235BXSkill11.5220.565.1210.4321.804.15
Qwen3-VL-32Bw/ Tools11.0918.692.659.9519.912.88
Qwen3-VL-32BAgent-KB10.2816.822.8811.3722.273.04
Qwen3-VL-32BXSkill10.2819.434.1913.1024.174.18

这里的结论更谨慎:XSkill 在 MMSearch-Plus 上提升 Qwen 模型,但在 VisualToolBench 的 Average@4 上可能低于 w/ Tools;不过 Pass@4 和 Turns 上升,说明外部知识鼓励了更多探索,但较弱模型可能无法稳定执行这些建议。

Case study and qualitative evidence

Figure D.1 解读:附录 case study 的输入图像是一辆出租车侧面带有文字 “GOOD GIFTING GOOD VALUES” 的街景。该例强调 XSkill 不是只做文本检索,而是要把图像中的局部区域、颜色、文字和工具生成的中间图像纳入经验总结。

Figure D.2 解读:这个 tool image 来自 rollout 中的局部视觉处理。附录描述了 agent 先定义 bounding box、采样 RGB 后发现结果不确定,再切换到 HSV 做更鲁棒的颜色识别。它展示了 experience 的粒度:不是“看图回答”,而是把具体工具操作中的失败与修正沉淀成以后可召回的 action-level tip。

Limitations and takeaways

作者明确承认当前实验展示的是 single accumulation-then-test cycle,而不是长期在线部署中的多轮持续学习;因此“continual”更多体现为架构兼容和一轮训练/测试验证,长期知识漂移、冲突经验管理和持续人类审计仍需要后续工作。Impact Statement 还指出,更强 agent 可能被用于敏感视觉数据上的恶意自动化;如果过去轨迹包含偏见,accumulation loop 也可能继承并放大偏见,且 cross-model transfer 会把这些偏置信息迁移给其他模型。

总体结论:XSkill 的实验证明,在 multimodal agents 中,把知识拆成 visually grounded Skills 与 Experiences,并通过 decomposition retrieval + context-aware adaptation 注入执行 prompt,可以在不更新参数的情况下显著提升工具使用可靠性、策略灵活性和跨任务迁移能力;但 released code 的默认脚本是 demo/template,复现实验时需要按论文 Table 8 和 benchmark split 重新配置。