借鉴 Externalization in LLM Agents (2026) 对 Agent Memory 的分类方式,根据记忆内容将 Agent Memory 分为以下三块:
一、工作上下文
LLM 的上下文与其表现高度相关,模型表现往往随着上下文长度的增加而下降。因此这一块的核心问题是:怎么让模型只看到信息量最多的那一部分信息。
观察什么:为 Agent 设计状态接口
原始的 bash CLI 指令往往带有大量无关信息,SWE-agent 针对处理 issue 这个场景,设计了一套定制化工具接口,让模型不被噪音塞满上下文。
SWE-agent:Agent-Computer Interface NeurIPS 2024
修 issue 时用定制命令按行读写代码,少往上下文里灌无关输出
SWE-agent 定义了 5 个定制化命令(open / edit / search_file / find_file / scroll),用精细到行级别的代码读取和修改,有效减少了无关上下文的读入。
查看示例:原生 shell vs ACI 定制接口的交互对比
ACI 核心命令接口定义:
open <path> [<line_number>] # 打开文件,显示以 line_number 为中心的 100 行窗口
edit <start>:<end> <<EOF ... EOF # 替换指定行范围,自动触发 linter
search_file <query> [<path>] # 在文件中搜索,返回行号+片段摘要
find_file <name> [<dir>] # 按名查找文件,返回路径列表
scroll_up / scroll_down # 在当前文件中翻页(±100 行)
Before — 原生 shell(无 ACI):
$ cat -n src/utils.py | head -50
[50 行输出淹没上下文,大量 token 浪费在无关代码上...]
$ sed -i '23s/old_code/new_code/' src/utils.py
[无反馈,不知道改对没有,可能引入语法错误]
$ cat -n src/utils.py | sed -n '20,26p'
[再花 token 确认结果,仍无 linter 检查]
After — SWE-agent ACI:
$ open src/utils.py 23
[File: src/utils.py (200 lines total)]
(13 lines above)
23| old_code
24| ...
(177 lines below)
$ edit 23:23
new_code
end_of_edit
[File updated. Linter: No issues.]
[File: src/utils.py (200 lines total)]
23| new_code ← 自动显示更新后内容
历史压缩:上下文线性增长怎么办
上下文窗口是有限的,压缩是所有多轮 Agent 都需要有的设计。这里介绍经典论文 MemGPT 的设计和 Claude Code 的策略。
MemGPT:LLM 自主管理虚拟上下文 arXiv 2023
LLM 自主存、取上下文
- Main Context 三区:System Instructions(固定不驱逐)+ Working Context(可编辑 scratchpad)+ FIFO Queue(先进先出消息队列)。
- External Context 两库:Archival Storage(向量检索的事实库)+ Recall Storage(按时间检索的完整对话历史)。
- 自主 page-in/page-out:LLM 通过 function calls 自行决定何时存档、何时召回,窗口满时自动驱逐 + 递归摘要。
MemGPT 工程细节补充
- archival_memory_search 是向量检索:embedding 使用
text-embedding-ada-002,底层基于 pgvector 做 cosine similarity 搜索,返回最相关的文档片段。 - Archival Storage 写入依赖模型主动调用:LLM 通过
archival_memory_insertfunction call 决定存什么;memory pressure 警告会暗示模型保存信息,但最终是否存档完全由 LLM 自主决策。 - conversation_search 返回原始完整消息:结果是 role + content + timestamp 的原始记录(非摘要),默认返回约 5-10 条匹配消息。
- Recall Storage 支持两种检索模式:原始版本仅支持关键词匹配(substring match on message content);当前版本升级为 hybrid search,结合关键词匹配 + embedding 向量检索。
两个向量库:
- FIFO 压缩并将原文存到向量库 Recall Storage,允许模型通过工具调用复原。
- 模型可主动写入和读取(向量检索)的 Archival Storage。
FIFO Queue 驱逐机制
MemGPT vs Claude Code /compact 对比
| 维度 | MemGPT (Packer 2023) | Claude Code /compact |
|---|---|---|
| 压缩触发 | FIFO 队列达 ~70% 发警告,100% 自动驱逐 | 上下文达 ~83.5% 自动触发;也可手动 /compact |
| 压缩方式 | 驱逐最旧 ~50% 消息 → LLM 递归摘要放在队首 | 分级裁剪:工具输出预算 → Microcompact → Auto-Compact(LLM 摘要) |
| 能否复原 | ✅ 原始消息完整存入 Recall Storage,可按需召回 | ❌ 不可逆,原始 token 丢弃 |
| 召回方式 | LLM 自主调 conversation_search / archival_memory_search | 无主动召回;依赖摘要质量 + CLAUDE.md 手动持久化 |
| 跨会话持久化 | ✅ 两库均跨会话保持 | ❌ 会话结束丢失(除非写入 CLAUDE.md) |
由于 MemGPT 保存了完整的上下文且可以自主召回,因此压缩策略更激进;Claude Code 为了任务完成度保留了很多信息,主要策略是优先丢弃工具返回,保留任务进度和用户意图。
查看对比:同一段对话,两种压缩 prompt 各自要求保留什么
假设原始对话包含:用户说「帮我重构 src/utils.py 的 parse 函数,要求兼容 Python 3.8」→ Agent 读了文件 → 改了代码 → 跑了测试 → 报错 → 修了 bug → 测试通过。
MemGPT 的摘要 prompt(早期 V1 风格):
「请将以下对话压缩为 100 词以内的摘要,保留关键信息。」
→ 输出:「用户要求重构 utils.py 的 parse 函数兼容 3.8。过程中遇到类型注解兼容问题,已修复。测试通过。」
→ 原文全部存入 Recall Storage,随时可通过 conversation_search 按关键词调回。
Claude Code 的摘要 prompt(9 段式结构化):
要求生成的摘要必须覆盖:
1. Intent: 用户要求重构 src/utils.py 的 parse 函数,兼容 Python 3.8
2. Technical: 类型注解语法兼容、Union 替代 | 语法
3. Files: src/utils.py(完整修改后代码片段)、tests/test_parse.py
4. Errors: TypeError on Python 3.8 due to X | Y syntax → 改为 Union[X, Y]
5. Problem Solving: 先尝试 from __future__ 方案失败,最终用 typing.Union
6. User Messages:「帮我重构...兼容 Python 3.8」(逐字保留)
7. Pending: 无
8. Current: 重构已完成,测试通过
9. Next: 可能需要更新 type stubs
→ 原文不保留,摘要本身就是唯一记录。丢失的:中间调试细节、完整错误栈、Agent 的推理过程。
核心差异:MemGPT 的摘要可以很短(反正原文在 Recall Storage 里),Claude Code 的摘要必须足够详细(因为这是唯一的记录,压缩后无法复原)。
Claude Code 压缩管线步进演示
- ✅ System prompt + CLAUDE.md(从磁盘重载,不受压缩影响)
- ✅ 所有用户消息(逐字保留在摘要中)
- ✅ 最近 3 个工具结果(硬保护)
- ✅ 当前任务 + 待办事项
- ❌ 早期工具输出原文(已被占位符替代)
- ❌ 中间推理过程(仅保留结论)
- ❌ 图片/文档原始内容
二、情节经验
模型推理的推理轨迹中往往能得到一些有利于下次推理的经验信息(skill),核心问题是:怎么让模型自动总结并利用这些 skill 让 Agent 下次做得更好?在 Memory 系统方面可以拆为三个维度:存什么(经验以什么形式保留)、怎么更新(新经验如何创建和迭代)、怎么召回(需要时如何加载到上下文)。早期的工作大多在探索要存什么,近期的研究开始聚焦于怎么有效更新、怎么与 RL 训练结合,提高模型的 skill 利用能力。
skill 的表示形式:早期探索
Reflexion:存经验的 naive 实践 NeurIPS 2023
失败后写一段反思文字存起来,下次重试时塞进 prompt 接着用
Reflexion(Shinn et al., 2023)用 Actor → Evaluator → Self-Reflection 构成 执行→评估→反思 闭环:仅在失败时写出自然语言反思,下轮注入 prompt 重试,用语言反馈替代调权重。
Evaluator 在不同场景下的实现方式
Evaluator 的核心职责是把模糊的「做得好不好」转化为二元信号,但在三种场景下实现方式完全不同:
- 推理任务(HotpotQA):精确匹配——答案对了就是成功,二元信号,无歧义
- 决策任务(AlfWorld):启发式规则——环境返回的 reward 信号判断是否达成目标状态
- 编程任务(HumanEval):LLM 自生成单元测试——Agent 先为任务写测试用例,再用测试结果作为评估信号。评估标准本身也由 LLM 生成,是最有意思的设计
- Actor:LLM 策略模型,接收环境观察 + 短期记忆(当前轨迹)+ 长期记忆(历史反思),输出动作。
- Evaluator:将模糊的执行质量转化为二元成功/失败信号。三种场景三种实现:推理任务用精确匹配、决策任务用环境 reward、编程任务用 LLM 自生成的单元测试——评估标准本身也由 LLM 创建。
- Self-Reflection:失败时接收完整轨迹 + 评估信号,生成一段具体的、可操作的反思。比如「应该先找台灯再找杯子」。
- Memory:滑动窗口,仅保留最近 1-3 条反思。最简单的 episodic memory。
- 关键区别于 RL:不产生梯度,而是产出一段语言总结(semantic gradient),通过 in-context injection 影响行为。
三维度定位
ExpeL:跨任务迁移的经验洞察 ICLR 2024
从很多任务的成败轨迹里总结几条通用经验,带到新任务里用
Reflexion 证明了真实推理中获得的经验能被复用到下一次推理中,但单 query 反复推理获得的经验往往泛化性不足。
ExpeL 从多个 query 的成功/失败对比中提炼通用 insights。三个维度的变化:
- 存什么:① 完整的尝试轨迹;② 从轨迹中提炼的跨任务的抽象规则(如「先确认物品位置再行动」)。
- 怎么更新:创建和更新上依赖 GPT-4 做两类分析——(A) 对比同任务的成功/失败轨迹找关键差异;(B) 归纳多个成功轨迹的共性模式。
- 怎么召回:所有 insights 仍全量注入 + 向量检索 top-k 相关成功轨迹作为 few-shot。
- Experience Gathering:对训练集任务用 Reflexion 机制重试,成功/失败轨迹都存入经验池。
- Insight Extraction(核心创新):GPT-4 做两类分析——(A) 对比同任务的成功/失败轨迹,找出关键差异;(B) 归纳多个成功轨迹的共性模式。产出的 insights 经 ADD/UPVOTE/DOWNVOTE 投票机制筛选质量。
- Task Inference:所有 insights 全量注入 prompt + FAISS 检索 top-k 相关成功轨迹作为 few-shot。Agent 一次尝试即可。
- vs Reflexion:单任务重试 → 跨任务迁移;临时反思 → 持久化通用规则。
ExpeL 开始抽取更通用抽象的 insight,保留了未经处理的完整轨迹用于注入,这种粗细结合的方式被后续工作继承。主流的存储方式演变成了 SOP 抽象 + 可执行代码/流程细节。
课程式探索:LLM 自主设计任务
Voyager:可执行的技能库 TMLR 2023
把成功经验写成可运行代码存进技能库,需要时检索几条来用
Voyager 把经验存成执行成功的代码,从文本反思迈向可执行 skill;由 LLM 基于环境反馈提出探索任务 驱动持续练级,验证通过的函数入库后可组合调用。召回侧改为按任务描述做向量检索 top-k,不再把整库反思全量塞进 prompt。
可执行代码更稳定,并且天然可被别的代码复用,由易到难,更容易探索出复杂任务的解决方案。
- 存什么:可执行 JS 函数——验证通过的代码存入向量数据库,新技能可调用已有技能,能力以组合方式指数增长。
- 怎么更新:验证通过即入库(只增不改)——Iterative Prompting 不是整体重试,而是逐步调试:生成代码 → 执行 → 三路反馈(环境状态 diff 告诉「做了什么」/ JS 错误告诉「哪里炸了」/ LLM self-verification 判断「目标达到没」)→ 在上一版代码基础上修改,最多 4 轮。通过即存入 skill library,4 轮都没过就丢弃。
- 怎么召回:向量相似度 top-k——用任务描述 embedding 检索最相关的 5 个技能作为 few-shot,不再全量注入。
- Automatic Curriculum(图 1 左):GPT-4 根据 Agent 当前状态(背包、位置、已完成任务)提出难度递增的目标,即 LLM 基于环境反馈提出探索任务。
- Iterative Prompting(图 1 中):更像开发者调 bug 而非考试重试——GPT-4 生成 JS 代码 → 执行 → 三路反馈同时返回(环境状态 diff / JS 执行错误堆栈 / LLM self-verification 判断目标是否达成)→ 在上一版代码基础上针对性修改,最多 4 轮。
- Skill Library(图 1 右):验证通过的执行成功的代码以描述 embedding 为 key 入库;新任务时检索 top-5 相关技能注入 prompt。
- 入库流程(图 2 上):代码 → GPT-3.5 生成自然语言描述 → text-embedding-ada-002 编码 → 向量数据库。用描述做 key 是因为检索时 query 是自然语言。
- 检索流程(图 2 下):新任务 → GPT-3.5 生成解决建议 → 合并环境反馈作为 query → cosine similarity 检索 top-5 → 注入代码生成 prompt。
- 可组合性:
craftWoodenPlanks()内部调用mineWoodLog(),复杂技能站在简单技能肩膀上。
SkillWeaver:自驱动技能发现与 API 合成 COLM 2025
自己上网练操作,把会用的步骤写成 Python 函数存起来
SkillWeaver(Zheng et al., 2025)跟 Voyager 思路很像——都是让 Agent 自驱动探索环境、把成功经验蒸馏为可执行代码、存入不断增长的技能库。但 SkillWeaver 把这套范式从 Minecraft 搬到了真实网页环境,并在三个地方做了针对性改进:
- 探索更主动:Voyager 靠 Automatic Curriculum 提目标,SkillWeaver 让 LLM 直接扫描网页截图和 accessibility tree 自主提出技能任务,且显式去重保证探索多样性
- 验证更严格:Voyager 的 self-verification 是 LLM 自判,SkillWeaver 额外加了单元测试——合成的 API 必须跑通测试才入库,失败的进入 debug 循环修复
- 技能可跨 Agent 迁移:产出的是标准 Playwright Python API(函数签名 + docstring),强模型合成的 API 直接插给弱模型用,弱模型在 WebArena 上最高获 +133% 相对提升
三阶段流程:Skill Proposal(LLM 扫描网页提出技能任务)→ Skill Synthesis(执行任务 + 成功轨迹蒸馏为 Python 函数)→ Skill Honing(单元测试 + debug 修复)。多轮迭代后会自动涌现组合 API(一个 API 调用多个子 API)。跟 Voyager 一样是只增不改——没有遗忘或迭代更新机制,且技能跟具体网站绑定,换站需要重新探索。
局限:技能跟具体网站绑定,跨网站泛化依赖重新探索;对 accessibility tree 解析失败的网站无能为力。
skill 的原则:粗细结合
AWM:参数化 Workflow 记忆 ICML 2025
把反复成功的操作步骤记下来,下次当参考流程塞进 prompt
AWM(Wang et al., 2024)从 Agent 成功轨迹里提取 SOP——带占位符的步骤流程(如「搜索 {product-name} → 加购 → 结账」),下次放进 prompt 作参考而非机械执行;按网站分组全量注入,可离线批量总结或在线边做边积累。
查看示例:AWM 归纳出的 workflow(来自原论文)
目标:在 Amazon 上搜索商品并按指定方式排序结果(Mind2Web 电商场景)
[textbox] Search Amazon → TYPE: {search-term}
[button] Go → CLICK
[span] Sort by: → CLICK
[option] {sort-option} → CLICK
目标:计算两地之间的出行时间与距离(WebArena 地图场景)
fill('158', '{FROM_LOCATION}')
fill('163', '{TO_LOCATION}')
select_option('166', '{MODE_OF_TRANSPORTATION}')
click('171')
send_msg_to_user('The distance between {FROM_LOCATION} and {TO_LOCATION} is {DISTANCE} and the estimated travel time is {TIME}.')
{search-term}、{FROM_LOCATION})将任务特定值抽象为通用变量,使同一 workflow 可复用于「搜索任意商品」或「查询任意两地距离」等不同具体任务。
- Workflow Induction:从成功轨迹中提取子程序,将任务特定值替换为通用占位符(如 {product-name}),保证可复用性。
- Memory Integration:workflow 集合加入 agent 的 text-based memory,按网站分组。
- Memory Utilization:agent 执行新任务时参考 memory 中的 workflow 作为行动指导,自行决定是否遵循某个 workflow。
- 关键:workflow 作为 context guidance 而非直接执行的 action——动态环境下预定义动作序列太脆弱。
局限:workflow 只增不减,无遗忘机制;全量注入依赖 workflow 数量少的假设;仅验证于网页导航场景。
ASI:可验证的程序化技能归纳 COLM 2025
从成功轨迹里抽出可运行的 Python 技能,跑通验证了再放进动作列表
ASI(Wang et al., 2025)延续 AWM 的在线归纳框架,把技能从文本 workflow 升级为可执行的 Python 程序:能实际跑通验证、能直接注册为 Agent 新动作,而不只是 prompt 里的参考说明。
- 相对 AWM:文本 workflow 只能放进 prompt,Agent 可能不跟、也无法执行验证;程序技能则扩展动作空间,调用一次函数即完成多步 click/fill/scroll。
- ① 归纳:从成功 episode 中由 LM 归纳 Python 函数(如
search_product(name)),封装多步原子操作为高层调用。 - ② 验证(核心):轨迹重写(用技能函数替换原始操作)→ 截断尾部(去掉
send_msg_to_user等直接给答案的步骤,否则重跑会「空过」验证、产生假阳性)→ 重跑检查:任务是否完成、是否真调用了新技能、调用是否引起环境变化。 - ③ 入库:三项全过才写入 skill library,后续可作为 Agent 可调用动作。
- 图中对比:上为文本参考式记忆增强;下为可执行程序式动作空间扩展。
click('[link] Marketing Reviews')
click('[link] Pending Reviews')
fill('[input] Search', term)
click('[button] Search')
可执行 Python 函数——封装多步原子操作为高层 API(如
search_product(name)),直接注册为 Agent 新增动作
三重执行验证——轨迹重写 + 尾部截断 + 重跑检查(任务正确性 × 技能被调用 × 环境变化),全过才入库;按网站分库管理
动作空间直接集成——技能函数注册在 action space 中,Agent 生成动作时直接可选,无需额外检索步骤
局限:验证依赖 LLM-based evaluator 判断正确性(非 ground-truth reward),且技能粒度和稳定性仍需进一步研究。
PolySkill:多态抽象的跨域泛化 ICLR 2026
同一套流程骨架,不同网站各写一版具体实现,方便迁移
技能绑死单一网站是 skill library 的常见瓶颈。PolySkill(Yu et al., 2025)把「购物」流程做功能抽象(search() / add_to_cart() / checkout() 等接口),不同网站,重跑生成可执行代码填入具体实现;组合流程在抽象层定义一次、各站继承复用,形成跨环境的多态。新站按接口清单探索而非盲目试错,技能需用原任务重跑并由 LLM Judge 验证后才入库。
查看示例:PolySkill 的抽象类与具体实现(来自原论文)
抽象类(领域级接口):
class AbstractShoppingSite(ABC):
"""购物网站的通用技能接口"""
@abstractmethod
def search_product(self, query: str, filter: str = None):
"""在网站上搜索商品"""
pass
@abstractmethod
def add_to_cart(self, item: str):
"""将商品加入购物车"""
pass
@abstractmethod
def checkout(self):
"""完成结账流程"""
pass
# 组合技能:在抽象层定义一次,所有子类自动继承
def place_order(self, query: str, filter: str = None):
"""下单 = 搜索 → 加购物车 → 结账"""
item = self.search_product(query, filter)
self.add_to_cart(item)
self.checkout()
具体子类(Amazon 实现):
class AmazonWebsite(AbstractShoppingSite):
"""Amazon 网站的具体技能实现"""
def search_product(self, query, filter=None):
click(id="twotabsearchtextbox")
type(query)
if filter:
click(id="searchDropdownBox")
select(filter)
click(id="nav-search-submit-button")
return get_first_result()
def add_to_cart(self, item):
click(item)
click(id="add-to-cart-button")
def checkout(self):
click(id="nav-cart")
click(id="sc-buy-box-ptc-button") # Proceed to checkout
click(name="placeYourOrder1")
TargetWebsite 子类实现同样的接口,组合流程(如 place_order())自动继承。Skill 库自进化
至此,Skill 的顶层 SOP + 底层代码的范式基本已确定,研究重点转到怎样对现有的 skill 做更新。
Memento-Skills:技能自迭代进化 arXiv 2026
技能写成文件夹,按任务挑对的来用,还能边用边改
Skill 的更新其实是个很难的任务。一方面,实际运行中,让 LLM 去选择创建或者更新旧的 skill,模型往往偏向创建新的 skill,导致 skill 库爆炸;另一方面,skill 更新后往往不经过测试,更新后不能保证原来的 skill 原有功能仍能 work。
- 存什么:结构化 skill 文件夹(SKILL.md + prompts + scripts + tests)——既包含声明式知识(prompts 引导 LLM),又包含程序性知识(scripts 直接执行),还自带质量保证(tests 防退化)。比 Voyager 的纯函数更完整
- 怎么更新:失败归因 + 原地优化/发现——Judge 定位失败归因到具体 skill 后,根据该 skill 的 utility(历史成功率 = 成功次数 / 总使用次数)决定策略:Optimise(utility ≥ δ,说明 skill 整体还行只是本次出错,靶向修补)、Discover(utility < δ,说明 skill 方向本身就不对,新建替代)、Unit Test Gate(门控回滚防退化)
- 怎么召回:行为对齐路由——Memento 用 InfoNCE 对比学习 + 离线 RL 训练 embedding:正样本 = 用了这个 skill 后任务成功的 (task, skill) 对,负样本 = 同领域但行为不匹配的对。这样 embedding 空间优化的是「选了这个 skill 后成功的概率」而非「文本描述相似度」
Memento-Qwen:行为对齐路由器的训练流程
训练一个小模型,按行为相似挑该用哪个技能,不看文字像不像
Skill 召回看似简单(不就是检索吗?),实则很难——skill 之间的语义描述高度相似,但行为完全不同。比如「密码重置」和「退款处理」的文本相似度可达 0.91,但选错一个就是灾难。Memento-Qwen 的训练分三步:
① 爬取种子 skill:从 GitHub 爬取 ~8K 个开源 skill(stars > 500),去重后取 ~3K 作为训练种子。每个 skill 有完整的 SKILL.md 描述。
② 合成对比训练数据:对每个种子 skill,用 LLM 生成两类 query:
- 正样本——「用了这个 skill 后任务能成功」的 (task, skill) 对
- Hard negative——「关键词/术语高度重叠,但实际需要另一个 skill」的 query。LLM Judge 进一步过滤低质量样本
③ InfoNCE 对比训练:基于 Qwen3-Embedding-0.6B 微调。Multi-Positive InfoNCE loss 把成功的 (task, skill) 对在 embedding 空间拉近,hard negative 推远。等价于单步 MDP 的软 Q-function:π(skill|query) ∝ exp(Q(query, skill) / τ)。推理时走 BM25 + dense embedding 双路召回 → Reciprocal Rank Fusion 合并。
| 路由方式 | Recall@1 | Recall@10 | Judge 成功率 |
|---|---|---|---|
| BM25(纯关键词) | 0.32 | — | 0.50 |
| Qwen3-Embedding(通用语义) | 0.54 | — | 0.79 |
| Memento-Qwen(行为对齐) | 0.60 | 0.90 | 0.80 |
Recall@1 从 0.32 到 0.60——翻了近一倍但也才六成,说明从数百个 skill 中精确选出「行为最匹配」的那一个本身就是当前的开放难题。提升幅度虽然不大(0.54→0.60),但结合 Judge 成功率(0.79→0.80)的平稳提升,说明数据和指标是可信的。
每个 Skill 是一个结构化文件夹而非单段代码:
my_skill/
├── SKILL.md # 声明式规范:做什么、何时触发
├── prompts/main.md # 引导 LLM 的提示词
├── scripts/helper.py # 可执行逻辑
└── tests/test.py # 门控回滚的单元测试
Trace2Skill:像人类专家一样写 Skill arXiv 2026
先把大量经验看完,再写成一份总指南,用时整份加载
大部分 skill 更新方式遵守一条轨迹对应一次更新:后面的更新往往优先级更高,容易产生偏差;单条轨迹带来的改动又常让 skill 过度贴合这道题,泛化性不足。
Trace2Skill(Ni et al., 2026)提出拿一批轨迹来更新 skill:每道题独立创建 patch → patch 合并归纳。
Stage 3 Merge 算子 ℳ · system prompt(附录 B.3.1)
You are a skill edit coordinator. You receive multiple independently-proposed
patches that each suggest changes to a skill folder. Your job is to merge them
into one coherent, non-redundant patch.
Guidelines:
1. Deduplicate: same or very similar edits → keep the best version.
2. Resolve conflicts: contradictory edits → stronger justification or synthesize.
3. Preserve unique insights: include all unique, non-redundant edits.
4. Maintain conciseness: merged patch ≤ sum of unique edits; remove redundancy.
5. Ensure independence: no two edits target overlapping lines (parallel apply).
6. Atomic create/link pairs: references/*.md "create" + SKILL.md link → keep both or drop both.
Prevalent pattern bias: when multiple patches independently propose similar edits
for the same failure/success class, treat recurrence as systematic — preserve with
higher priority and express as general principles, not instance-specific fixes.
Output: JSON {"reasoning","edits":[{file,op,...}],"changelog_entries":[...]}
Ops: insert_after | insert_before | append_to_section | replace_in_section |
add_section | delete_section | create | delete_file
每轮 user 消息另附原始 skill 目录全文 + 待合并 patch 列表;论文实验每层 batch=32,官方代码默认 5。
RL 驱动的参数化进化
Skill 库的初始化创建和后续更新都依赖真实 rollout 轨迹;rollout 也是 RL 环节里成本最高的部分。有的工作开始探索这两个环节的融合,以更充分地利用 rollout 轨迹。
SkillRL:RL 驱动的技能递归进化 arXiv 2026
边强化学习边维护技能库,考得不好就补新技能
前述 Voyager/AWM 等把 rollout 经验外化成 skill,但 agent 多半只靠 prompt 注入来用,参数本身不会更会「用 skill」。SkillRL(Xia et al., 2026)用 teacher 把轨迹蒸馏进层次化 SkillBank(通用 skill 全量注入 + 任务 skill 向量 top-K,约 10–20× 压缩),再经 cold-start SFT 与 GRPO 训练;验证失败时 teacher 分析缺口并补 skill——核心是迭代 skill 库并进行 RL,提高模型的 skill 利用能力。
- 经验蒸馏:成功轨迹 → 战略模式(关键决策 + 可泛化规律);失败轨迹 → 反面教训(失败点 + 应做什么 + 预防原则)。10–20× token 压缩。
- SkillBank 层次化组织:General Skills(环境通用策略)+ Task-Specific Skills(按任务类别分组的专属 heuristics),每个 skill 含 name / principle / when_to_apply。
- Cold-start SFT:teacher 生成 skill-augmented reasoning traces,微调 base model 使其学会检索、理解和应用 skill。
- 递归进化循环:GRPO 训练中,每个 validation epoch 对低成功率类别做失败轨迹分析 → teacher 发现 skill 盲区 → 生成新 skill 补入 SkillBank。
局限:技能进化依赖 teacher model 的分析质量;cold-start SFT + RL 训练成本较高(单次实验约 30 小时)。
Skill0:技能内化到模型参数 arXiv 2026
训练时给 skill、推理时归零,用 RL 把能力写进参数
美团的 Skill0(Lu et al., 2026)提出skill 内化:通过课程学习逐步缩小允许召回的 skill 数,让模型在 skill 不再放入上下文之后,仍能保持与载入 skill 时相近的性能。
- (a) Skill0 自身:绿线 w/ skill、紫线 w/o skill。训练前期紫线明显更低;随课程推进紫线追上并在约 120 步后与绿线重合——说明能力已迁入参数,推理时不注入 skill 也接近带 skill 时的表现。
- (b) vs AgentOCR(均无 skill 推理):Skill0(绿)全程高于 AgentOCR(紫),差距随训练拉大,排除「只是训练时多看了 skill 才变强」。
- (c) vs GRPO / SkillRL(均无 skill 推理):GRPO(黄)早期涨得快但后期 plateau;SkillRL(紫)约 60–100 步见顶后撤 skill 性能明显下滑——能力未内化;Skill0(绿)起步慢但持续升至约 150 步,为三者最高。SkillRL 教会用 skill,Skill0 教会替代 skill。
子图 (c) 里有一条值得单独注意的曲线:SkillRL 在长期训练之后,对 skill 的依赖度在逐渐加深,导致训练后期在不载入 skill 的情况下反而出现性能下降。
局限:依赖高质量初始 SkillBank 与帮助性评估(每个 skill 需有/无对照 rollout);实验主要在 ALFWorld、Search-QA,与 Trace2Skill 式「单份综合 SOP」路线互补而非替代。
延伸阅读:Skill0 方法图解
三、个性化记忆
核心问题:用户特定痕迹有不同的保留、检索和隐私规则,不应混入通用知识。跨会话对话记忆是这一层最典型的场景——需要从冗长历史中抽取、合并、检索与用户相关的 salient facts,而不是每次把全文塞进上下文。
Mem0:生产级长期对话记忆 ECAI 2025
每轮对话抽几条要记住的事实,更新记忆库,回答时再捞出来
Mem0(Chhikara et al., 2025)为跨会话对话维护持续更新的外部记忆库:每轮 (mt-1, mt) 触发一次 pipeline——先用 LLM 从当前交换中抽取候选事实(结合全局摘要与近期上下文),再检索库内相似条目并决定 ADD / UPDATE / DELETE / NOOP;答题时只做向量检索注入相关记忆(约 1.7k token,远低于 full-context 的 2.6 万+)。
- 输入流:每轮完整交互单元(用户消息 + 助手回复)触发 pipeline,适合流式对话场景。
- 双源语境(抽取):摘要
S提供全局主题;最近 10 条消息提供细粒度时序细节——二者互补,避免只靠摘要丢细节。 - 异步摘要模块:与主 pipeline 解耦,不阻塞记忆写入,保证抽取时
S尽量新。 - Tool Call 更新:不用单独分类器,由 LLM 根据候选事实与检索到的相似记忆之间的语义关系直接选操作。
- 向量库:dense embedding 支撑更新阶段的相似检索与查询阶段的记忆召回。
- 一句话总结:把「整段对话」压缩成「可维护的事实条目集合」,用显式增删改保持库内一致,而非静态 RAG 切块。
查看示例:记忆更新四操作(Appendix B 逻辑)
对候选事实 f 与已有记忆库 M 的判定逻辑:
- ADD:
f与库中无语义相似条目 → 生成新 ID 写入 - UPDATE:
f可补充已有记忆且信息更丰富 → 替换旧条目 - DELETE:
f与某条已有记忆矛盾 → 删除被否决的旧记忆 - NOOP:已存在或无需改动 → 跳过
实验默认 m=10(近期消息窗)、s=10(相似记忆数),抽取与更新均用 GPT-4o-mini。
IFRAgent:从演示中学习用户习惯 arXiv 2025
先看你做过什么学会流程,再按你的习惯改写成你想看到的指令
IFRAgent(Wu et al., 2025)改写用户 query,注入用户偏好细节:离线从演示轨迹 S(u,q) 并行提取显式 SOP p 与隐式习惯库 hi;在线对新 query RAG 相似历史 SOP,经 ℰ 生成流程、𝒲 将 hi 编入 q改、p改 后交 UI Agent——习惯经 rewriter 间接注入,而非直接塞进执行 prompt。
rewrite 示例
RAG + ℰ 只解决「这类任务大致怎么做」(得到通用 SOP 模板);Rewrite 才解决「这个用户要怎么做」——用一个小模型 𝒲 读入当前 query、当前 SOP、习惯库 hi,把 hi 里的偏好写进自然语言,输出给 UI Agent 的 q改 与 p改。不是向量检索,是文本改写。
改写前(通用模板,Step 5 结束)
q:「帮我点份晚餐」
p(SOP):
1. 打开美团
2. 搜索餐厅
3. 按评分筛选
4. 下单
Rewrite
改写后(个性化,Step 6)
q改:「帮我点份晚餐,附近、川菜、中辣」
p改(SOP):
1. 打开美团
2. 搜索餐厅
3. 先按距离排序,再筛 川菜 + 辣度
4. 下单
hi 例:「偏好川菜、重辣;习惯先按距离再比评分」→ 被 𝒲 抄写/融合进 q改 与 p改 的步骤文案。UI Agent 只读改写后的文本,不直接读 hi。
步进演示:离线建库 → 在线个性化执行
- User Demonstrations:多组 (query, 截图轨迹),用户无需标注偏好。
- Explicit flow:GPT-4o 从轨迹抽逐步 SOP,
ϕ(query)入向量库,供相似任务 few-shot。 - Implicit flow:同一演示增量写入用户习惯库
hi,跨 query 共享。 - SOP 检索线:embedding 相似度 > τ 时取历史 (q′, p′) → ℰ 生成新 SOP。
- 个性化改写线:𝒲(Qwen3-4B 蒸馏)输入 q, p, hi → 输出
q改,p改(论文写作 q̂、p̂)。 - 执行:UI-TARS 等 Agent 接收 q改, p改 + 当前屏幕,按用户习惯操作。
查看示例:点外卖任务的显式 SOP vs 隐式习惯
显式 SOP(per-query):「点外卖 → 1. 打开美团 2. 搜索餐厅 3. 按评分筛选 4. 下单」
隐式习惯(per-user):「偏好川菜、辣度中高;习惯先按距离排序再比评分」
Rewrite 前后(同任务):
- 改写前 p:按评分筛选 → 改写后 p改:先按距离,再筛川菜+辣度(来自 hi)
- 改写前 q:「帮我点份晚餐」 → 改写后 q改:补「附近、川菜、中辣」
Agent 只看到 q改/p改,不会直接读 hi 原文。