AVB 对论文《Recursive Agent Optimization (RAO)》做了清晰解读。这篇论文的核心是用强化学习(RL)训练 LLM Agent,让它们学会 spawn 递归子 Agent,在 Python REPL 中实现分而治之(divide and conquer)。
核心思想
RAO 训练 LLM 如何将大任务切片,委派给子 Agent(这些子 Agent 还可以继续 spawn 更多子 Agent),并在多个正交子问题上并行工作。
可以理解为:递归语言模型 + 强化学习 生了一个孩子。
实验环境
作者刻意选择了两个非常小的本地模型:
- Qwen3-4B-Instruct(稠密模型)
- Qwen3-VL-30B-A3B-Instruct(MoE模型)
任务都是长程/长上下文、需要仔细规划和分治策略的:
-
TextCraft-Synth:Minecraft 风格的合成游戏,Agent 必须收集材料、合成物品。需要自然发现和解决子问题(如:收集木头 → 合成木板 → 合成木棍)
-
Oolong-Real:长程 D&D 对话转录问答,文档长达10-12页,是非常困难的检索任务
-
DeepDive:需要多跳、迭代网络搜索和信息综合的复杂 QA
执行树与 Spawn 机制
当语言模型接到任务 X,它产生一个"轨迹"(trajectory)——即 Agent 为尝试完成任务所采取的一系列观察和行动。在此过程中,Agent 可以选择在委派的子任务 X1、X2 上 spawn 子 Agent,形成一个有根执行树:
- 每个节点 = 一个 Agent 实例解决一个任务
- 根节点 = 原始任务
- 子节点 = 该 Agent 决定委派的子任务
递归通过单个 async 函数实现:
result = await async_launch_subagent(
goal="find all papers about X", ...
)
策略本身决定:
- 是否委派(调用 launch_subagent)
- 子任务描述是什么
- 请求什么输出格式
- 是否并行化子任务(用
await asyncio.gather) - 如何聚合结果
选择 REPL 的原因很强大:返回类型不受限制、父节点可以用普通 Python 链式/组合/转换子输出、子节点可以串行或并发运行、最重要的是——子 Agent 返回的输出不会直接加载到父节点的上下文,而是保存在 Python 变量中,父节点可以操作这些变量(打印切片、验证键等)后再加载到上下文。
局部节点奖励(信用分配)
标准 RLVR 只有根节点在任务完成时获得奖励信号。在递归设置中这有问题:如果任务需要深度3的递归树,等输出传播回来获得奖励时,最底层的叶 Agent 已经相隔数百个 token,信用分配基本失效。
RAO 用局部成功信号解决:一个 LLM judge(gpt-5-mini)评估子任务输出并生成奖励,基于两个因素:
- Term 1:该节点是否解决了分配的任务?(直接成功信号)
- Term 2:该节点的子节点(如果有)是否在子任务上成功?(委派奖励信号)
对于委派奖励,作者用子节点的平均成功率而不是求和或计数。这防止了退化策略:Agent spawn 100个琐碎子任务只为收集奖励。Agent 只获得委派质量的信用,不是数量。
三个训练技巧
1. 多任务目标
每个 rollout 自动生成多深度的任务。从根任务"研究AI历史并写报告",根 Agent 可能 spawn:
- 深度1:"找1950s-1980s的论文"
- 深度1:"找1990s-2010s的论文"
- 深度2:"搜索Turing的工作"
- 深度2:"搜索早期神经网络论文"
RAO 同时训练每个深度的任务。同一策略(语言模型)被优化为深度0(根规划器)、深度1(中层委派者)、深度2+(叶执行者)的好 Agent。这也是课程学习的一种形式——子任务由模型自己生成,几乎总是比根任务简单。
2. Leave-One-Out (LOO) 基线
对每个根任务,RAO 采样 G 个独立的 rollout 树。目标是找到哪些独立树导致高奖励——然后最大化该行为。
任何轨迹 τ 在 rollout g 中的优势:
A(g) = Rollout g 的奖励 - 排除 g 的所有其他 rollout 的平均奖励
每个子 Agent 的优势单独计算:
优势 = 局部奖励 - 基线
3. 深度级逆频率加权
如果 Agent spawn 4个子节点,每个又 spawn 4个,就有 1+4+16=21 个轨迹节点,但只有1个根。如果天真地平均所有梯度,叶节点以16:1主导更新,导致模型过度优化为好的叶执行者,而欠优化为好的根规划者。
修复:按深度级逆频率加权。深度 d 的权重:
w = α / |B_d|
其中 α 是归一化常数,|B_d| 是该深度的轨迹数。直观上,这给出现更频繁的深度分配更小权重,减少树中人口稠密层级主导学习的倾向。
关键结果
1. 上下文管理技能在训练后期自发进化
在 Oolong-Real 训练中,递归 Agent 被限制在32K上下文窗口但需要处理55K+ token 的文档。它最初试图把整个输入文档打印到根上下文,立即填满并崩溃。然后完全自主地放弃了这个策略,学会了正确方法:将输入分块,每块委派给子 Agent。
2. 即使不需要递归,递归也有帮助
即使有完整的40K上下文窗口(足以无需递归解决任务),递归 Agent 仍然训练更快、表现更好。因为子 Agent 奖励充当密集的过程奖励——每个子任务完成都在任务中段给出训练信号,而不是只在最后。分而治之依然无敌。
3. 分而治之是可迁移的
模型只在中等难度的 TextCraft 任务上训练,从未见过困难任务。在评估时,它泛化到了更困难的任务。论文假设这是因为分而治之是可迁移策略——如果你学会很好地分解中等问题,可以递归地应用同样分解模式到更深层来解决更难的问题。
4. 30B模型逼近Claude、o3和GPT-5-mini
在 Oolong-Real 上,训练的递归 Agent 达到平均奖励0.320。一个30B开放模型,仅在此特定任务上用RL训练,几乎匹配万亿参数前沿模型!
5. 串行任务更慢但更聪明
在 DeepDive 上,递归 Agent 比单 Agent 慢18倍。单 Agent 快是因为它早早放弃、走捷径。递归 Agent 在只有它能解决的困难任务上使用深度4+,精确地在需要的地方分配更多计算。两者都能解决的任务平均深度2.9,但只有递归 Agent 能解决的任务平均深度4。
6. 简单任务上优势消失
在 ART-E(简单邮件搜索基准)上,RAO 在早期训练阶段仍然帮助模型更快学习,但最终性能趋同——单 Agent 追上了递归 Agent。这符合直觉:如果任务短、适合一个上下文窗口、不受益于分解,递归增加开销而没有有意义的收益。
训练细节澄清
- 不是把整个树作为一个序列更新——每个节点的轨迹独立更新
- 子输出 token 不会被父节点训练——子 Agent 的完整内部推理和轨迹永远不会出现在父节点的上下文中
- 基线在每个 rollout 的根计算——同一基线用于所有子 Agent 的优势计算
- 只训练 Assistant 生成的 token——系统提示、任务描述、观察(包括子输出)是上下文,不被训练