0x00 概要
本系列的目的是:借着对 OpenClaw-RL 源码的学习,来梳理强化学习的一些相关概念和思想。所以,会有一些扩展和发散,OpenClaw-RL 只是一个切入点。而且,因为整篇系列是一个整体,所以有些概念的解读/学习会在不同的文章中出现,还请大家谅解。

OpenClaw-RL 是一个用于在线强化学习(Online RL)的框架,专门针对智能体工具使用场景。它通过从环境反馈中提取过程奖励信号来训练语言模型,支持三种主要模式:

openclaw-rl:基于二元奖励的强化学习(Binary RL / GRPO)
openclaw-opd:基于后见之明提示的在线策略蒸馏(On-Policy Distillation, OPD)
openclaw-combine:联合方法,在同一 PPO 更新中同时利用 RL reward 和 OPD teacher signal
framework

我们先给全篇定个基调:在 OpenClaw-RL 中,"环境(Environment)"并不是一个独立封装的模块,而是由 真实用户 + OpenClaw App + FastAPI Proxy 三者共同构成的隐式实体。OpenClaw-RL 的设计哲学是:环境的其他部分(状态、动作、转移)都可以用事实性描述来定义,比如 “代码执行后输出 X”、“用户回复了 Y”,这些都是可被客观验证的。

因此,本篇我们就来看看 OpenClaw-RL 的环境到底是如何设计的,以及一些与环境相关的功能。

0x01 环境建模基础
环境建模的核心,不是把现实世界完整模拟出来,而是把真实工作 “转写” 成一个结构上不失真的可训练决策过程。

1.1 标准 RL 系统的 4 模块架构
下图是标准 RL 系统的 4 模块架构,可以清楚地看到 “环境(Environment)” 所处的位置。

8-四模块结构

1.2 单轮 RL 下环境的退化
在深入讨论环境建模之前,我们先看一个关键背景:LLM 单轮 RL 中,环境被极度简化。

完整 RL loop 中环境承担四类职责:

s0 → a0 → r0 → s1 → a1 → r1 → … → st → done

环境负责: s0(初始状态)、s1→st 的转移、r0→rt(奖励)、done(终止)
但 LLM 单轮 RL 把多步交互压扁成了"一次性输出":

s0 → [a0, a1, …, at] → r

环境只负责: s0 (prompt) 和 r (terminal reward)
中间步骤(token 生成)全在 model 内部完成
环境不参与 token-level 交互 → 环境退化为 “prompt 提供器 + reward 打分器”
因此,在单轮场景下,环境的四类职责(State / Transition / Reward / Termination)中,Transition 和 Termination 几乎退化为零,真正起作用的只剩 State(提供 prompt) 和 Reward(打分) 两项。我们后面在 0x03 会看到,OpenClaw 的多轮对话场景会把这四项重新拉满,但理解单轮的退化形态,有助于看清 OpenClaw 设计的特殊性。

这里点出一个容易被忽视的点:State 虽然看起来"只是提供 prompt",但它决定了 prompt 分布,而 prompt 分布直接决定训练效率。想象两个环境:Env A 只提供数学题,Env B 提供数学+代码+写作,即使两者用完全相同的 reward function,训练出的模型也完全不同。State 的质量本质上就是 Rollout Allocation 的一部分。

1.3 环境建模的特点
环境建模的核心是结构性不失真,即因果结构的等价性,而非现象层面的相似性。一个看起来很"简单"但保留了"哪些决策影响哪些结果"的环,比一个看起来很"真实"但扭曲了这条因果链的环境更有价值。

完整模拟的代价与陷阱
我们来看看Web Agent的"完整模拟"尝试,其模拟如下:

真实浏览器 + 完整渲染 + JavaScript执行
真实网站(可能需要登录、CAPTCHA)
真实网络延迟
其问题如下:

单次rollout耗时数分钟(无法并发训练)
网站随时变化(训练数据不可复现)
大量细节与"做决策"无关(像素精度对决策无意义)
无法reset到相同初始状态(非Markov化)
完整模拟不仅不必要,而且可能损害训练一它把大量计算浪费在与决策无关的细节上。

什么是"结构上不失真”
核心:保留决策的因果结构,而非感官的真实性。

结构 = 以下四者的组合。结构上不失真,就说明其保留了这四者的组合。

动作空间(可以做什么)
状态—动作因果关系(做什么会导致什么)
奖励信号的归因结构(哪些决策真正重要)
难度分布(任务有没有代表性)
一个反例(结构失真)是:假设为了简化,把Web任务的"搜索"操作改为:“输入关键词,系统直接返回最相关的5个结果”。此时问题如下:

真实Web:关键词选择影响后续哪些信息可见
简化版:关键词选择对结果几乎无影响(系统帮你做了retrieval) → 模型永远学不到"如何构造有效搜索词"这个技能 → 结构被破坏,即使视觉上看起来"像网页"
结构失真 vs 细节失真
细节失真(可接受):

WebShop没有真实的UI渲染
ALFWorld的物理引擎不是完全准确的 → 对学习"如何导航到物品"的技能无影响
结构失真(不可接受):

"奖励函数惩罚所有超过10步的轨迹”(即使10步可以完成任务) → 模型学到的是"如何在10步内完成任务”,而非"如何完成任务” → 泛化到真实任务时:任务需要15步→模型表现差
"所有agent action必须从预定义列表中选择”(离散化action空间) → 模型无法学习构造复杂的文字指令
→ 迁移到真实任务(自由文本输入)时完全失效
"转写"的含义
转写 = 找到一个 MDP,使其与真实工作在决策层面等价:

真实工作 → MDP 转写
─────────────────────────────────────────────────────────
程序员修复 bug State: 代码 + issue 描述
Action: 生成 diff / 调用命令
Transition: 执行命令后的输出
Reward: 测试通过/失败

用户与 AI 对话 State: 对话历史
Action: 生成回复文本
Transition: 用户的下一句话(真实行为)
Reward: next_state 是否表明帮到了用户

家庭机器人导航 State: 房间图 + 物体位置
Action: 移动/拾取/放置
Transition: 物理模拟结果
Reward: 任务是否完成
OpenClaw 的转写方式
OpenClaw 是这个原则的极致实践—它几乎不转写,直接使用真实工作:

真实对话 = 直接的 MDP

State = messages array(原始对话历史,无抽象)
Action = 完整自然语言回复(无离散化)
Transition = 用户的下一条真实消息(非模拟)
Reward = judge(response, next_state)(唯一的人工成分)
转写的最小化带来的优势:

无模拟Gap(真实环境即训练环境)
动作空间与真实部署完全一致
状态转移由真实用户驱动(最真实的外部反馈)
唯一的结构风险是:Reward函数设计不当 → 即使其他一切真实,MDP结构仍然失真 → 这就是PRM judge 设计的核心挑战。

0x02 真实用户 Environment
2.1 标准 env
标准 env(如 Atari/MuJoCo/数学验证)的优点如下:

☑ 确定性:相同 action → 相同 next state
☑ 可重复:env.reset() 随时重来
☑ 可控速:想跑多快跑多快
☑ 可并行:开 1000 个 env 实例
☑ 可观测:完整状态可见
☑ 均匀分布:可以控制 prompt 分布
2.2 真实用户
真实用户创造了自然的"能力边界课程"

用户不发送不可能完成的任务(会换平台)

用户不发送完全无需AI的任务(会自己做)

→ 用户群体的需求分布天然集中在"AI需要思考但可以成功"的区间 → 这是一种"有机的curriculum",无需显式的难度控制

对比:离线RL必须从固定数据集采样,可能大量遇到模型太强/太弱的任务(饱和/无法完成),产生大量零梯度组

2.3 特殊挑战
真实用户作为 Environment 的特殊挑战如下。

不可控的数据到达速率
凌晨3点:0个用户 → 训练饿死 → rollout_batch_size=16,可能等 30 分钟
晚上8点:50个用户同时聊 → 数据洪水 → queue 堆积→数据变stale(off-policy 程度加剧)
代码应对:

_drain_output_queue 的while 循环 + timeout 日志
“waiting for API-produced samples: 3/16, queue=0” ← 在等用户
不可控的Prompt分布
标准RL:从curated dataset采样 → 数学题/代码题/写作题均匀分布

OpenClaw:用户想问啥问啥

可能的情况:

  • 连续50个人问“帮我写情书”→模型在情书上过拟合
  • 没人问数学→数学能力退化
  • 大量hello/你好→无效训练数据
    → 无法做curriculum learning (课程学习) → 无法控制 difficulty distribution

不可重复(Non-replayable)
标准RL:同一个prompt可以生成N=16个回答 → GRPO组内比较

OpenClaw:

用户说“帮我分析这个bug”
你不能让用户“再说一遍“,然后给4个不同回答
→ N=1,GRPO退化 → 无法做rejection sampling(挑最好的回答) → 无法做best-of-N

非平稳(Non-stationary)
标准RL:env 规则不变(CartPole的物理规则固定)

OpenClaw:

  • 周一用户主要问工作问题
  • 周末用户主要闲聊
  • 新功能上线后用户行为突变
  • 某个话题在社交媒体爆火→ 突然大量相关问题
    → “环境“本身在变化 → 之前学到的策略可能不再适用 → 需要持续适应

延迟反馈(Delayed &Partial Reward)
标准RL:action→立即得到reward(毫秒级)

OpenClaw:

模型回复 → 用户看了… → 可能5分钟后才回复下一条 → 这5分钟内不知道用户满不满意 → PRM评分是替代品,不是真实用户反馈 → 用户可能直接退出(无反馈)
→ 真实的reward signal其实从未获得 → PRM是noisy proxy

部分可观测(Partial Observability)
标准RL:env.state完全可见

OpenClaw:

  • 用户的真实意图不可见(“帮我写代码“→是作业?工作?学习?)
  • 用户的满意度不可见(沉默满意)
  • 用户的上下文不可见(他之前用别的 AI 聊过什么?)
  • 多轮对话中的隐式状态不可见
    → 模型只能通过messages推断意图 → PRM也只能基于文本评分,无法知道用户真实感受

训练影响环境(Training Affects Environment)
标准RL:

env 不受agent训练影响
CartPole不会因为agent变强而改变物理规则
OpenClaw:

模型变好 → 用户满意度上升 → 用户更活跃 → 更多数据 → 训练更快
模型变差 → 用户流失 → 数据减少 → 训练变慢/停滞
模型学会某种风格 → 吸引特定用户群 → prompt 分布偏移
→ 正反馈/负反馈循环 → 非平稳加剧 → 可能陷入 “filter bubble” (信息茧房)

2.4 OpenClaw 的应对策略
挑战 OpenClaw 的应对 效果
①数据断流 _drain_output_queue 阻塞等待 ⭐⭐ 基本够用
②分布不可控 无 (完全被动) ❌ 未解决
③不可重复 N=1 + OPD 补偿 ⭐⭐⭐ 部分补偿
④非平稳 无显式处理 ❌ 未解决
⑤延迟反馈 PRM 即时代理评分 ⭐⭐⭐ 可用但有噪声
⑥部分可观测 多轮 session 维护 ⭐⭐ 基本够用
⑦训练影响环境 无显式处理 ❌ 未解决
真实用户作为 environment 有 7 大挑战。

OpenClaw 解决了"能跑起来"的工程层面的 3 个 (①③⑤ / 数据断流、不可重复、延迟反馈),但"跑得好"的理论层面的 4 个 (②④⑥⑦ / 分布不可控、非平稳、部分可观测、训练影响环境) 还未解决,还有很大空间。

0x03 OpenClaw 环境的作用
前面 1.2 节我们看到,单轮 LLM RL 中环境会退化为"prompt 提供器 + reward 打分器"。但 OpenClaw 是多轮对话场景,四类职责会被重新拉满。我们结合代码逐一拆解。先回顾环境在 OpenClaw 中的四类职责对应关系:

8-OpenClaw 环境

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐