SkillRL 技术分析与基于 OpenClaw 的落地实现方案
每个 Skill 是一个目录,包含SKILL.md---description: 变压器巡检异常检测技能bins:- node- python3env:config:---# 变压器巡检技能当检测到变压器温度异常时,执行以下流程:1. 获取红外热成像数据2. 对比历史基线温度3. 判断是否超过安全阈值(85°C)4. 生成告警报告并推送给运维人员SkillRL 在 OpenClaw 中的实现分为两
SkillRL 技术分析与基于 OpenClaw 的落地实现方案
一、论文概述
(一)基本信息
- 论文标题:SkillRL: Evolving Agents via Recursive Skill-Augmented Reinforcement Learning
- 来源:arXiv 2602.08234
- 研究团队:UNC-Chapel Hill、芝加哥大学、UCSD、伯克利联合发表
- 开源代码:aiming-lab/SkillRL
(二)核心问题
现有 LLM Agent 存在两大痛点:
- 基于记忆的方法(Memory-based):存储原始轨迹,冗余且噪声严重,难以有效复用,上下文窗口被大量无关细节占满
- 标准 RL 方法:缺乏结构化知识的跨任务迁移机制,学到的策略难以泛化到新场景
SkillRL 的目标是:将原始经验自动蒸馏为结构化、可复用的高层行为模式(技能),并让技能与模型策略在递归训练中共同演化
(三)核心创新
| 创新点 | 说明 |
|---|---|
| 经验蒸馏机制 | 从成功轨迹提取「战略演示」,从失败轨迹提炼「反事实教训」,转化为结构化技能 |
| 分层技能库(SkillBank) | 分为通用技能(跨任务可迁移)和任务特定技能(针对特定场景),支持自适应检索 |
| 递归演化机制 | 技能库在 RL 训练过程中与 Agent 策略动态共同演化,每轮迭代都更新技能库内容 |
(四)训练流程
- 冷启动 SFT(监督微调):用初始成功轨迹对模型进行监督微调,给模型一个基础能力起点
- 递归 RL 循环:
- Agent 执行任务 → 收集轨迹
- 蒸馏成功/失败轨迹为技能 → 更新 SkillBank
- 在推理时将相关技能注入 Prompt → 指导 Agent 决策
- 使用 GRPO(Group Relative Policy Optimization)更新模型权重
- 重复迭代,技能库和模型策略共同进化
(五)实验效果
| 指标 | 数据 |
|---|---|
| 基准测试 | ALFWorld、WebShop 和 7 个搜索增强任务上达到 SOTA |
| 性能提升 | 相比强基线提升 15.3%+ |
| Token 压缩 | 实现 10-20% 的 Token 压缩(相比存储原始轨迹) |
| 小模型超越大模型 | 7B 模型性能超越 GPT-4o |
二、核心定性:Skill 调优 vs 模型能力优化
(一)结论
两者兼有,但本质上是以 Skill 调优为核心驱动的模型能力优化。
(二)详细分析
| 维度 | 分析 |
|---|---|
| Skill 调优(主要,占比约 80%) | 论文的核心创新——自动发现技能、构建分层 SkillBank、递归演化技能库。技能以结构化知识的形式存在于外部技能库中,在推理时通过检索注入 Prompt |
| 模型能力优化(次要,占比约 20%) | 论文使用了冷启动 SFT 和 GRPO 强化学习来实际更新模型权重,模型参数确实被优化了,但这种优化是服务于更好地利用技能 |
(三)本质定性
SkillRL 是一个「技能驱动的 Agent 策略优化框架」,其核心哲学是:
- 不是靠堆模型参数来变强,而是靠结构化知识积累(技能)来变强
- 模型权重的更新(SFT + RL)是手段,技能的发现和演化才是目的
- 最终目标是让小模型(7B)通过更好的技能组织,达到甚至超越大模型(GPT-4o)的效果
三、OpenClaw 架构分析
仓库地址:https://github.com/openclaw/openclaw
官方文档:https://docs.openclaw.ai
(一)技术栈
| 组件 | 语言 | 占比 | 说明 |
|---|---|---|---|
| 核心框架 | TypeScript | 85.7% | Gateway 网关 + Agent 运行时 + Skills 系统 |
| iOS 客户端 | Swift | 10.1% | 原生 iOS 端 |
| Android 客户端 | Kotlin | 1.8% | 原生 Android 端 |
| 脚本 | Shell / JS | 1.5% | 构建工具、辅助脚本 |
(二)核心架构
┌───────────────────────────────────────────────────────────┐
│ OpenClaw Gateway │
│ (TypeScript / Node.js) │
│ │
│ ┌──────────────┐ ┌───────────────┐ ┌────────────────┐ │
│ │ Agent Runtime │ │ Skills System │ │ Sub-Agent Mgr │ │
│ │ (pi-embedded) │ │ (SKILL.md) │ │ (sessions.spawn│ │
│ └──────┬───────┘ └───────┬───────┘ └────────┬───────┘ │
│ │ │ │ │
│ ┌──────▼──────────────────▼────────────────────▼───────┐ │
│ │ Skills Snapshot System │ │
│ │ buildWorkspaceSkillSnapshot() → 版本化快照 │ │
│ │ ensureSkillsWatcher() → 文件监听 + 热更新 │ │
│ │ applySkillEnvOverridesFromSnapshot() → 环境变量注入 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼─────────────────────────────┐ │
│ │ Session JSONL Logging │ │
│ │ ~/.openclaw/agents/{agent}/sessions/{id}.jsonl │ │
│ └──────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
(三)Skills 系统详解
1. Skill 定义格式(SKILL.md)
每个 Skill 是一个目录,包含 SKILL.md 文件,使用 YAML frontmatter + Markdown 指令:
---
name: inspect-transformer
description: 变压器巡检异常检测技能
version: 1.0.0
bins:
- node
- python3
env:
- OPENAI_API_KEY
config:
model: gpt-4o
---
# 变压器巡检技能
当检测到变压器温度异常时,执行以下流程:
1. 获取红外热成像数据
2. 对比历史基线温度
3. 判断是否超过安全阈值(85°C)
4. 生成告警报告并推送给运维人员
2. Skills 加载优先级(低 → 高)
extra(最低) < bundled < managed < personal < project < workspace(最高)
3. 技能快照系统
SKILL.md 变更
↓
ensureSkillsWatcher() 检测到文件变化
↓
bumpSkillsSnapshotVersion() 递增快照版本号
↓
下一轮 Agent 执行时 buildWorkspaceSkillSnapshot() 重建快照
↓
resolveSkillsPromptForRun() 将技能上下文注入 LLM Prompt
4. 子智能体编排
createSessionsSpawnTool():支持递归任务分治- 防递归保护:subagent 不能再 spawn subagent
- 生命周期管理:重启恢复、结果回传、清理策略
(四)关键源码入口
| 模块 | 文件路径 | 职责 |
|---|---|---|
| Skills 主逻辑 | src/agents/skills.ts |
技能加载、解析 |
| 快照构建 | src/agents/skills/workspace.ts |
生成版本化快照 |
| 热更新监听 | src/agents/skills/refresh.ts |
SKILL.md 文件变化检测 |
| 环境覆盖 | src/agents/skills/env-overrides.ts |
执行前注入/执行后回滚 |
| 远程同步 | src/infra/skills-remote.ts |
多设备间能力同步 |
| Agent 运行时 | src/agents/pi-embedded-runner/run/attempt.ts |
单次执行尝试 |
| 子智能体 | src/agents/tools/sessions-spawn-tool.ts |
任务分治 |
四、能力边界划分:OpenClaw 能做什么,不能做什么
(一)核心边界
| 层面 | 职责 | 归属 |
|---|---|---|
| Agent 编排层 | Gateway 调度、多 Agent 协同、Tool 调用、Prompt 构建、Skills 管理、轨迹记录 | OpenClaw(TypeScript) |
| 模型训练层 | SFT 微调、RL 策略梯度、GRPO 权重更新 | 训练框架(TRL、OpenRLHF、veRL 等,Python) |
OpenClaw 本质是一个 Agent 编排与推理框架,它管的是「模型怎么被调用、Agent 怎么协同」,但它不碰模型权重。SFT/RL/GRPO 都需要对模型做反向传播、更新参数,属于训练框架的职责。
(二)SkillRL 能力拆分
OpenClaw 可以直接实现的部分(TypeScript,不需要训练模型)
| 模块 | 说明 | 对应 OpenClaw 源码 |
|---|---|---|
| SkillBank 技能库 | 技能存储、向量检索、分层管理、持久化 | 扩展 src/agents/skills/ |
| 经验蒸馏 | 用 LLM 调用(推理)来总结轨迹、提取技能 | 新增 Skill 或扩展 Agent 逻辑 |
| Prompt 注入 | 推理时把检索到的技能拼进 Prompt | 扩展 resolveSkillsPromptForRun() |
| 轨迹收集 | Agent 执行任务并记录完整轨迹 | 利用 Session JSONL 日志 |
| 技能库动态更新 | 动态增删改 SKILL.md、触发快照版本更新 | 利用热更新机制 |
OpenClaw 做不了的部分(需要 Python 训练框架)
| 模块 | 说明 | 需要的工具 |
|---|---|---|
| 冷启动 SFT | 用成功轨迹微调模型权重,让模型学会按技能格式输出 | TRL、LLaMA-Factory |
| RL 训练 | 通过环境奖励信号更新模型策略 | veRL、OpenRLHF |
| GRPO 优化 | 组相对策略优化,词元级策略梯度 + KL 惩罚 | TRL (trl.GRPOTrainer) |
五、基于 OpenClaw 的代码实现方案
(一)总体架构
┌────────────────────────────────────────────────────────────────┐
│ OpenClaw Gateway (TypeScript) │
│ │
│ ┌──────────────┐ ┌───────────────┐ ┌─────────────────────┐ │
│ │ Agent 调度器 │ │ 技能检索模块 │ │ 轨迹收集器 │ │
│ └──────┬───────┘ └──────┬────────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ ┌──────▼─────────────────▼───────────────────────▼─────────┐ │
│ │ SkillBank(分层技能库 + 元数据管理) │ │
│ │ ┌──────────────────┐ ┌──────────────────────┐ │ │
│ │ │ 通用技能 (generic)│ │ 任务特定技能 (task) │ │ │
│ │ │ SKILL.md + metrics│ │ SKILL.md + metrics │ │ │
│ │ └──────────────────┘ └──────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────▼─────────────────────────────────┐│
│ │ 经验蒸馏引擎(Experience Distiller) ││
│ │ 成功轨迹 → 战略演示 失败轨迹 → 反事实教训 ││
│ │ (通过 LLM 推理调用实现,不需要训练) ││
│ └───────────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────▼─────────────────────────────────┐│
│ │ 轨迹导出器 → JSONL / REST API ││
│ │ (给外部 Python 训练框架提供数据) ││
│ └───────────────────────────────────────────────────────────┘│
└────────────────────────────────────────────────────────────────┘
║
║ JSONL 数据管道 / REST API
▼
┌────────────────────────────────────────────────────────────────┐
│ Python 训练框架(TRL / veRL / OpenRLHF) │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 三阶段训练器(SFT → RL → GRPO) │ │
│ │ 读取 JSONL 轨迹 → 训练模型 → 输出新 checkpoint │ │
│ └─────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
(二)模块一:SkillBank — 分层技能库(TypeScript)
在 OpenClaw 的 Skills 系统基础上扩展,增加 SkillRL 的元数据管理和向量检索。
// src/agents/skills/skillrl-bank.ts
// 基于 OpenClaw 的 Skills 快照系统扩展
import { readFile, writeFile, readdir, mkdir } from 'fs/promises'
import { join } from 'path'
// ===== 类型定义 =====
interface Skill {
skillId: string
name: string
description: string
strategyPattern: string[] // 关键决策步骤序列
abstractScript: string // 高层脚本(如 "定位→检测→上报→处置")
applicableScenarios: string[] // 适用场景
skillType: 'generic' | 'task_specific'
successRate: number
usageCount: number
failureLessons: string[]
embedding?: number[] // 向量嵌入(用于语义检索)
}
interface SkillMetrics {
skillId: string
successRate: number
usageCount: number
lastUsedAt: number
avgExecutionTime: number
}
// ===== SkillBank 核心类 =====
class SkillBank {
private genericSkills: Map<string, Skill> = new Map()
private taskSpecificSkills: Map<string, Map<string, Skill>> = new Map()
private skillsDir: string
constructor(skillsDir: string) {
// skillsDir 指向 OpenClaw 的 Skills 目录
// 例如 ~/.openclaw/skills/ 或项目级 .openclaw/skills/
this.skillsDir = skillsDir
}
/**
* 添加技能到对应层级
* 同时生成 SKILL.md 文件,让 OpenClaw 的热更新机制自动检测
*/
async addSkill(skill: Skill, taskId?: string): Promise<void> {
if (skill.skillType === 'generic' || !taskId) {
this.genericSkills.set(skill.skillId, skill)
} else {
if (!this.taskSpecificSkills.has(taskId)) {
this.taskSpecificSkills.set(taskId, new Map())
}
this.taskSpecificSkills.get(taskId)!.set(skill.skillId, skill)
}
// 写入 SKILL.md 文件,触发 OpenClaw 快照更新
await this.persistSkillToFile(skill, taskId)
}
/**
* 自适应检索:先查任务特定技能,再补通用技能
*/
async retrieve(query: string, taskId?: string, topK: number = 5): Promise<Skill[]> {
const candidates: Array<{ similarity: number; skill: Skill }> = []
// 优先检索任务特定技能
if (taskId && this.taskSpecificSkills.has(taskId)) {
for (const skill of this.taskSpecificSkills.get(taskId)!.values()) {
const sim = this.computeSimilarity(query, skill)
candidates.push({ similarity: sim, skill })
}
}
// 补充通用技能
for (const skill of this.genericSkills.values()) {
const sim = this.computeSimilarity(query, skill)
candidates.push({ similarity: sim, skill })
}
// 按相似度排序并返回 top-K
candidates.sort((a, b) => b.similarity - a.similarity)
return candidates.slice(0, topK).map(c => c.skill)
}
/**
* 更新技能使用统计
*/
updateSkillStats(skillId: string, success: boolean): void {
const skill = this.findSkill(skillId)
if (!skill) return
skill.usageCount += 1
if (success) {
skill.successRate = (
skill.successRate * (skill.usageCount - 1) + 1.0
) / skill.usageCount
} else {
skill.successRate = (
skill.successRate * (skill.usageCount - 1)
) / skill.usageCount
}
}
/**
* 清理低效技能,防止技能库膨胀
*/
prune(minSuccessRate: number = 0.2, minUsage: number = 5): void {
const toRemove: string[] = []
for (const [sid, skill] of this.genericSkills) {
if (skill.usageCount >= minUsage && skill.successRate < minSuccessRate) {
toRemove.push(sid)
}
}
for (const sid of toRemove) {
this.genericSkills.delete(sid)
}
}
/**
* 持久化技能到 SKILL.md 文件
* 利用 OpenClaw 的 ensureSkillsWatcher() 自动检测变更
*/
private async persistSkillToFile(skill: Skill, taskId?: string): Promise<void> {
const subDir = taskId ? `task-${taskId}` : 'generic'
const skillDir = join(this.skillsDir, subDir, skill.skillId)
await mkdir(skillDir, { recursive: true })
const skillMd = `---
name: ${skill.name}
description: ${skill.description}
version: 1.0.0
skillType: ${skill.skillType}
successRate: ${skill.successRate}
usageCount: ${skill.usageCount}
applicableScenarios:
${skill.applicableScenarios.map(s => ` - ${s}`).join('\n')}
---
# ${skill.name}
${skill.description}
## 策略模式
${skill.strategyPattern.map((step, i) => `${i + 1}. ${step}`).join('\n')}
## 高层脚本
${skill.abstractScript}
## 失败教训
${skill.failureLessons.length > 0 ? skill.failureLessons.map(l => `- ${l}`).join('\n') : '暂无'}
`
await writeFile(join(skillDir, 'SKILL.md'), skillMd, 'utf-8')
}
/**
* 从 Skills 目录加载所有技能
*/
async loadFromDisk(): Promise<void> {
// 读取 generic/ 和 task-*/ 子目录
const entries = await readdir(this.skillsDir, { withFileTypes: true })
for (const entry of entries) {
if (!entry.isDirectory()) continue
if (entry.name === 'generic') {
const skills = await this.loadSkillsFromDir(join(this.skillsDir, entry.name))
for (const skill of skills) {
this.genericSkills.set(skill.skillId, skill)
}
} else if (entry.name.startsWith('task-')) {
const taskId = entry.name.replace('task-', '')
const skills = await this.loadSkillsFromDir(join(this.skillsDir, entry.name))
this.taskSpecificSkills.set(taskId, new Map())
for (const skill of skills) {
this.taskSpecificSkills.get(taskId)!.set(skill.skillId, skill)
}
}
}
}
/**
* 导出全部技能为 JSON(供 Python 训练框架读取)
*/
async exportToJSON(outputPath: string): Promise<void> {
const data = {
generic: Object.fromEntries(this.genericSkills),
taskSpecific: Object.fromEntries(
Array.from(this.taskSpecificSkills.entries()).map(
([tid, skills]) => [tid, Object.fromEntries(skills)]
)
),
exportedAt: Date.now()
}
await writeFile(outputPath, JSON.stringify(data, null, 2), 'utf-8')
}
// ===== 私有方法 =====
private findSkill(skillId: string): Skill | undefined {
if (this.genericSkills.has(skillId)) {
return this.genericSkills.get(skillId)
}
for (const taskSkills of this.taskSpecificSkills.values()) {
if (taskSkills.has(skillId)) {
return taskSkills.get(skillId)
}
}
return undefined
}
private computeSimilarity(query: string, skill: Skill): number {
// 简单的关键词匹配(生产环境应替换为向量语义检索)
const queryTokens = new Set(query.toLowerCase().split(/\s+/))
const skillTokens = new Set(
`${skill.description} ${skill.applicableScenarios.join(' ')}`.toLowerCase().split(/\s+/)
)
let overlap = 0
for (const token of queryTokens) {
if (skillTokens.has(token)) overlap++
}
return overlap / Math.max(queryTokens.size, 1)
}
private async loadSkillsFromDir(dirPath: string): Promise<Skill[]> {
// 解析 SKILL.md 文件的 YAML frontmatter
// 实际实现中需要用 gray-matter 等库
const skills: Skill[] = []
try {
const entries = await readdir(dirPath, { withFileTypes: true })
for (const entry of entries) {
if (!entry.isDirectory()) continue
const skillMdPath = join(dirPath, entry.name, 'SKILL.md')
try {
const content = await readFile(skillMdPath, 'utf-8')
const skill = this.parseSkillMd(entry.name, content)
if (skill) skills.push(skill)
} catch {
// SKILL.md 不存在则跳过
}
}
} catch {
// 目录不存在则跳过
}
return skills
}
private parseSkillMd(skillId: string, content: string): Skill | null {
// 简化的 frontmatter 解析(生产环境用 gray-matter)
const match = content.match(/^---\n([\s\S]*?)\n---/)
if (!match) return null
// 从 frontmatter 中提取字段(简化实现)
const frontmatter = match[1]
const getName = (key: string): string => {
const m = frontmatter.match(new RegExp(`^${key}:\\s*(.+)$`, 'm'))
return m ? m[1].trim() : ''
}
return {
skillId,
name: getName('name'),
description: getName('description'),
strategyPattern: [],
abstractScript: '',
applicableScenarios: [],
skillType: getName('skillType') as 'generic' | 'task_specific' || 'generic',
successRate: parseFloat(getName('successRate')) || 0,
usageCount: parseInt(getName('usageCount')) || 0,
failureLessons: []
}
}
}
export { SkillBank, Skill, SkillMetrics }
(三)模块二:Experience Distiller — 经验蒸馏引擎(TypeScript)
用 LLM 推理调用来总结轨迹,提炼为结构化技能。此模块在 OpenClaw 内通过 LLM 推理调用即可完成,不需要训练。
// src/agents/skills/skillrl-distiller.ts
// 在 OpenClaw 的 Agent Runtime 中通过 LLM 调用实现经验蒸馏
import type { Skill } from './skillrl-bank'
interface TrajectoryStep {
observation: string
action: string
result: string
reward: number
}
interface Trajectory {
task: string
steps: TrajectoryStep[]
totalReward: number
success: boolean
error?: string
timestamp: number
}
class ExperienceDistiller {
private llmGenerate: (prompt: string) => Promise<string>
constructor(llmGenerate: (prompt: string) => Promise<string>) {
// llmGenerate 是 OpenClaw Agent Runtime 提供的 LLM 调用函数
// 可以是 Gateway 管控的任意模型(GPT-4o、Qwen-72B 等)
this.llmGenerate = llmGenerate
}
/**
* 成功轨迹 → 战略演示(Strategic Demonstrations)
*/
async distillSuccess(trajectory: Trajectory): Promise<Skill> {
const prompt = `分析以下成功的 Agent 执行轨迹,提取可复用的决策模式。
任务描述: ${trajectory.task}
执行步骤:
${this.formatSteps(trajectory.steps)}
最终结果: 成功
请提取:
1. 技能名称(一个简洁短语)
2. 技能描述(一句话概括这个行为模式)
3. 关键决策步骤(按顺序列出 3-5 个关键动作)
4. 高层脚本(用"→"连接的抽象流程)
5. 适用场景(列出 2-3 个可能复用的场景)
以 JSON 格式输出,字段:name, description, keySteps, abstractScript, applicableScenarios`
const response = await this.llmGenerate(prompt)
const skillData = JSON.parse(response)
return {
skillId: `skill_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
name: skillData.name,
description: skillData.description,
strategyPattern: skillData.keySteps,
abstractScript: skillData.abstractScript,
applicableScenarios: skillData.applicableScenarios,
skillType: 'generic',
successRate: 1.0,
usageCount: 1,
failureLessons: []
}
}
/**
* 失败轨迹 → 反事实教训(Counterfactual Lessons)
*/
async distillFailure(trajectory: Trajectory): Promise<{
rootCause: string
failedStep: number
counterfactualAdvice: string
preventionRule: string
}> {
const prompt = `分析以下失败的 Agent 执行轨迹,提取失败教训。
任务描述: ${trajectory.task}
执行步骤:
${this.formatSteps(trajectory.steps)}
最终结果: 失败(原因: ${trajectory.error || '未知'})
请分析:
1. 失败的根本原因
2. 具体哪一步出了问题(步骤编号)
3. 反事实建议(如果当时怎么做,可能成功)
4. 防护原则(今后遇到类似情况应该怎么做)
以 JSON 格式输出,字段:rootCause, failedStep, counterfactualAdvice, preventionRule`
const response = await this.llmGenerate(prompt)
return JSON.parse(response)
}
private formatSteps(steps: TrajectoryStep[]): string {
return steps.map((s, i) =>
` Step ${i + 1}: [观察] ${s.observation} → [动作] ${s.action} → [结果] ${s.result}`
).join('\n')
}
}
export { ExperienceDistiller, Trajectory, TrajectoryStep }
(四)模块三:Skill-Augmented Agent — 技能增强推理(TypeScript)
在 OpenClaw Agent Runtime 的基础上增加 SkillBank 检索 + Prompt 注入能力。
// src/agents/skills/skillrl-agent.ts
// 扩展 OpenClaw 的 Agent Runtime,增加 SkillRL 技能增强推理
import type { SkillBank, Skill } from './skillrl-bank'
import type { Trajectory, TrajectoryStep } from './skillrl-distiller'
interface AgentConfig {
llmGenerate: (prompt: string) => Promise<string>
skillBank: SkillBank
maxSkillsPerPrompt: number // 每次最多注入多少技能
}
class SkillAugmentedAgent {
private llmGenerate: (prompt: string) => Promise<string>
private skillBank: SkillBank
private maxSkills: number
constructor(config: AgentConfig) {
this.llmGenerate = config.llmGenerate
this.skillBank = config.skillBank
this.maxSkills = config.maxSkillsPerPrompt || 3
}
/**
* 技能增强的决策函数
* 在 OpenClaw 的 attempt.ts 中调用
*/
async act(observation: string, task: string, taskId?: string): Promise<string> {
// 1. 从 SkillBank 检索相关技能
const relevantSkills = await this.skillBank.retrieve(
`${task} ${observation}`,
taskId,
this.maxSkills
)
// 2. 构建技能增强 Prompt
const prompt = this.buildSkillPrompt(observation, task, relevantSkills)
// 3. 模型推理
const action = await this.llmGenerate(prompt)
return action
}
/**
* 构建带技能上下文的 Prompt
* 这会被注入到 OpenClaw 的 resolveSkillsPromptForRun() 流程中
*/
private buildSkillPrompt(observation: string, task: string, skills: Skill[]): string {
let skillContext = ''
for (let i = 0; i < skills.length; i++) {
const skill = skills[i]
skillContext += `
【技能 ${i + 1}】${skill.name}
描述: ${skill.description}
流程: ${skill.abstractScript}
关键步骤: ${skill.strategyPattern.join(' → ')}
成功率: ${Math.round(skill.successRate * 100)}%`
if (skill.failureLessons.length > 0) {
skillContext += `\n 注意事项: ${skill.failureLessons[skill.failureLessons.length - 1]}`
}
skillContext += '\n'
}
return `你是一个智能巡检 Agent。根据当前观察和可用技能,决定下一步动作。
## 当前任务
${task}
## 当前观察
${observation}
## 可参考的技能经验
${skillContext}
## 要求
- 优先使用已有技能中的策略模式
- 如果没有合适的技能,生成原始动作
- 输出格式: {"action": "...", "reasoning": "...", "skillUsed": "技能名或null"}`
}
}
export { SkillAugmentedAgent, AgentConfig }
(五)模块四:轨迹收集器(TypeScript)
集成到 OpenClaw 的 Session 生命周期中,收集 Agent 执行轨迹。
// src/agents/skills/skillrl-collector.ts
// 利用 OpenClaw 的 Session JSONL 日志系统收集轨迹
import { appendFile, mkdir } from 'fs/promises'
import { join } from 'path'
import type { Trajectory, TrajectoryStep } from './skillrl-distiller'
interface ToolInvocation {
name: string
input: Record<string, unknown>
result: string
error: string | null
executionTime: number
}
class TrajectoryCollector {
private currentTrajectory: TrajectoryStep[] = []
private exportDir: string
constructor(exportDir: string) {
// exportDir 指向轨迹导出目录
// 例如 ~/.openclaw/skillrl/trajectories/
this.exportDir = exportDir
}
/**
* 在 attempt.ts 的每次工具调用后 hook
* 记录 Agent 的每一步执行
*/
recordStep(step: TrajectoryStep): void {
this.currentTrajectory.push(step)
}
/**
* 从 OpenClaw 的 ToolInvocation 转换为 SkillRL 的 TrajectoryStep
*/
fromToolInvocation(observation: string, invocation: ToolInvocation): TrajectoryStep {
return {
observation,
action: `${invocation.name}(${JSON.stringify(invocation.input)})`,
result: invocation.error || invocation.result,
reward: invocation.error ? -0.5 : 0.5
}
}
/**
* 会话结束时,导出完整轨迹为 JSONL
* 供 Python 训练框架批量读取
*/
async finishAndExport(task: string, success: boolean, error?: string): Promise<Trajectory> {
const trajectory: Trajectory = {
task,
steps: [...this.currentTrajectory],
totalReward: this.currentTrajectory.reduce((sum, s) => sum + s.reward, 0),
success,
error,
timestamp: Date.now()
}
// 导出为 JSONL(追加模式)
await mkdir(this.exportDir, { recursive: true })
const exportFile = join(this.exportDir, `trajectories_${this.getDateStr()}.jsonl`)
await appendFile(exportFile, JSON.stringify(trajectory) + '\n', 'utf-8')
// 重置当前轨迹
this.currentTrajectory = []
return trajectory
}
/**
* 获取待导出的轨迹数量(供训练触发器使用)
*/
async getPendingTrajectoryCount(): Promise<number> {
// 读取 exportDir 中所有 .jsonl 文件的行数
// 简化实现
return this.currentTrajectory.length
}
private getDateStr(): string {
const d = new Date()
return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`
}
}
export { TrajectoryCollector, ToolInvocation }
(六)模块五:SkillRL 编排器 — 串联全流程(TypeScript)
在 OpenClaw Gateway 中编排整个 SkillRL 流程。
// src/agents/skills/skillrl-orchestrator.ts
// OpenClaw 侧的 SkillRL 总编排器
import { SkillBank } from './skillrl-bank'
import { ExperienceDistiller } from './skillrl-distiller'
import { SkillAugmentedAgent } from './skillrl-agent'
import { TrajectoryCollector } from './skillrl-collector'
import type { Trajectory } from './skillrl-distiller'
interface SkillRLConfig {
skillsDir: string // Skills 存储目录
trajectoryExportDir: string // 轨迹导出目录
llmGenerate: (prompt: string) => Promise<string> // LLM 推理函数
maxSkillsPerPrompt?: number
pruneMinSuccessRate?: number
pruneMinUsage?: number
batchExportThreshold?: number // 积累多少条轨迹后触发批量导出
}
class SkillRLOrchestrator {
private skillBank: SkillBank
private distiller: ExperienceDistiller
private agent: SkillAugmentedAgent
private collector: TrajectoryCollector
private config: SkillRLConfig
constructor(config: SkillRLConfig) {
this.config = config
this.skillBank = new SkillBank(config.skillsDir)
this.distiller = new ExperienceDistiller(config.llmGenerate)
this.agent = new SkillAugmentedAgent({
llmGenerate: config.llmGenerate,
skillBank: this.skillBank,
maxSkillsPerPrompt: config.maxSkillsPerPrompt || 3
})
this.collector = new TrajectoryCollector(config.trajectoryExportDir)
}
/**
* 初始化:从磁盘加载已有技能
*/
async initialize(): Promise<void> {
await this.skillBank.loadFromDisk()
}
/**
* 执行一次技能增强推理
* 在 OpenClaw 的 Agent 执行循环中调用
*/
async executeWithSkills(observation: string, task: string, taskId?: string): Promise<string> {
return this.agent.act(observation, task, taskId)
}
/**
* 记录执行步骤
* Hook 到 OpenClaw 的 attempt.ts 中的工具调用
*/
recordStep(observation: string, action: string, result: string, reward: number): void {
this.collector.recordStep({ observation, action, result, reward })
}
/**
* 会话结束后处理轨迹
* 在 OpenClaw Session 结束时调用
*/
async onSessionEnd(task: string, success: boolean, error?: string): Promise<void> {
// 1. 导出轨迹
const trajectory = await this.collector.finishAndExport(task, success, error)
// 2. 经验蒸馏(在 OpenClaw 内通过 LLM 推理完成)
await this.distillAndUpdateSkillBank(trajectory)
// 3. 定期清理低效技能
this.skillBank.prune(
this.config.pruneMinSuccessRate || 0.2,
this.config.pruneMinUsage || 5
)
}
/**
* 蒸馏轨迹并更新技能库
*/
private async distillAndUpdateSkillBank(trajectory: Trajectory): Promise<void> {
if (trajectory.success) {
// 成功轨迹 → 蒸馏出新技能
try {
const newSkill = await this.distiller.distillSuccess(trajectory)
await this.skillBank.addSkill(newSkill)
// addSkill 内部会写 SKILL.md → 触发 OpenClaw 热更新
} catch (e) {
console.error('Failed to distill success trajectory:', e)
}
} else {
// 失败轨迹 → 提取教训,附加到相关技能
try {
const lesson = await this.distiller.distillFailure(trajectory)
const relatedSkills = await this.skillBank.retrieve(trajectory.task, undefined, 1)
if (relatedSkills.length > 0) {
relatedSkills[0].failureLessons.push(lesson.preventionRule)
// 重新写入 SKILL.md 更新教训
await this.skillBank.addSkill(relatedSkills[0])
}
} catch (e) {
console.error('Failed to distill failure trajectory:', e)
}
}
}
/**
* 手动触发技能库导出(供 Python 训练框架读取)
*/
async exportSkillBank(outputPath: string): Promise<void> {
await this.skillBank.exportToJSON(outputPath)
}
}
export { SkillRLOrchestrator, SkillRLConfig }
(七)模块六:三阶段训练器(Python,独立于 OpenClaw)
此模块完全独立于 OpenClaw,运行在 Python 环境中,定期读取 OpenClaw 导出的轨迹数据进行模型训练。
# training/skillrl_trainer.py
# 独立的 Python 训练框架,通过 JSONL 文件与 OpenClaw(TS)通信
import json
import glob
import numpy as np
from pathlib import Path
from dataclasses import dataclass
@dataclass
class TrajectoryData:
"""与 OpenClaw TypeScript 侧的 Trajectory 接口对应"""
task: str
steps: list[dict]
total_reward: float
success: bool
error: str | None
timestamp: int
class SkillRLTrainer:
"""
SkillRL 三阶段递归训练器
阶段 1: 冷启动 SFT(需要 TRL / LLaMA-Factory)
阶段 2: RL 策略优化(需要 veRL / OpenRLHF)
阶段 3: GRPO 最终优化(需要 TRL trl.GRPOTrainer)
此训练器独立于 OpenClaw 运行,通过文件系统交换数据:
- 输入:~/.openclaw/skillrl/trajectories/*.jsonl(由 OpenClaw TS 侧导出)
- 输入:~/.openclaw/skillrl/skillbank.json(技能库快照)
- 输出:~/.openclaw/models/skillrl-v{N}/(训练完成的模型 checkpoint)
"""
def __init__(self, openclaw_data_dir: str, model_name: str = 'Qwen/Qwen2.5-7B'):
self.data_dir = Path(openclaw_data_dir)
self.trajectory_dir = self.data_dir / 'trajectories'
self.skillbank_path = self.data_dir / 'skillbank.json'
self.model_output_dir = self.data_dir / 'models'
self.model_name = model_name
def load_trajectories(self) -> list[TrajectoryData]:
"""从 OpenClaw 导出的 JSONL 文件中读取轨迹"""
trajectories = []
for jsonl_file in sorted(self.trajectory_dir.glob('*.jsonl')):
with open(jsonl_file) as f:
for line in f:
data = json.loads(line.strip())
trajectories.append(TrajectoryData(
task=data['task'],
steps=data['steps'],
total_reward=data['totalReward'],
success=data['success'],
error=data.get('error'),
timestamp=data['timestamp']
))
return trajectories
def load_skillbank(self) -> dict:
"""加载 OpenClaw 导出的技能库快照"""
if self.skillbank_path.exists():
with open(self.skillbank_path) as f:
return json.load(f)
return {'generic': {}, 'taskSpecific': {}}
# ========================================
# 阶段 1: 冷启动 SFT(需外部训练框架)
# ========================================
def cold_start_sft(self):
"""用成功轨迹做监督微调,让模型学会使用技能的格式"""
trajectories = self.load_trajectories()
skillbank = self.load_skillbank()
# 筛选成功轨迹
success_trajs = [t for t in trajectories if t.success]
# 构建 SFT 训练数据
sft_data = []
for traj in success_trajs:
for step in traj.steps:
sft_data.append({
'input': f'任务: {traj.task}\n观察: {step["observation"]}',
'output': step['action']
})
# 使用 TRL SFTTrainer 执行微调
# from trl import SFTTrainer, SFTConfig
# trainer = SFTTrainer(model=..., args=SFTConfig(...), train_dataset=sft_data)
# trainer.train()
print(f'SFT 数据准备完成: {len(sft_data)} 条样本')
# ========================================
# 阶段 2: RL + 技能演化
# ========================================
def rl_with_skill_evolution(self, num_iterations: int = 10):
"""递归 RL 循环 —— 读取新轨迹,更新技能评分"""
for iteration in range(num_iterations):
trajectories = self.load_trajectories()
# 按时间戳筛选本轮新增的轨迹
# 实际实现中需要记录上次处理的时间戳
success_trajs = [t for t in trajectories if t.success]
fail_trajs = [t for t in trajectories if not t.success]
print(f'迭代 {iteration + 1}: '
f'{len(success_trajs)} 条成功, {len(fail_trajs)} 条失败')
# GRPO 策略优化
self._grpo_update(trajectories)
# ========================================
# 阶段 3: GRPO 策略优化
# ========================================
def _grpo_update(self, trajectories: list[TrajectoryData]):
"""
GRPO(Group Relative Policy Optimization)
核心:多候选比较 + 留一法优势估计 + KL 惩罚
需要 TRL (trl.GRPOTrainer) 支持
"""
# from trl import GRPOTrainer, GRPOConfig
#
# config = GRPOConfig(
# output_dir=str(self.model_output_dir / f'skillrl-v{int(time.time())}'),
# per_device_train_batch_size=4,
# num_train_epochs=3,
# learning_rate=1e-6,
# kl_coef=0.01,
# )
#
# trainer = GRPOTrainer(
# model=self.model,
# args=config,
# train_dataset=self._prepare_grpo_dataset(trajectories),
# reward_funcs=self._compute_reward,
# )
# trainer.train()
rewards = [t.total_reward for t in trajectories]
print(f'GRPO 数据: {len(trajectories)} 条轨迹, '
f'平均奖励: {np.mean(rewards):.3f}')
def _compute_reward(self, trajectory: TrajectoryData) -> float:
"""计算轨迹的综合奖励"""
task_reward = trajectory.total_reward
efficiency_bonus = -0.01 * len(trajectory.steps)
return task_reward + efficiency_bonus
# ========================================
# 入口函数
# ========================================
def run_full_pipeline(self):
"""执行完整的三阶段训练"""
print('=== 阶段 1: 冷启动 SFT ===')
self.cold_start_sft()
print('=== 阶段 2: RL + 技能演化 ===')
self.rl_with_skill_evolution(num_iterations=10)
print('=== 训练完成 ===')
print(f'模型输出目录: {self.model_output_dir}')
if __name__ == '__main__':
import sys
data_dir = sys.argv[1] if len(sys.argv) > 1 else '~/.openclaw/skillrl'
trainer = SkillRLTrainer(data_dir)
trainer.run_full_pipeline()
(八)模块七:跨语言数据管道(TypeScript ↔ Python)
OpenClaw(TypeScript)和训练框架(Python)之间的数据交互。
// src/agents/skills/skillrl-bridge.ts
// OpenClaw 侧:与 Python 训练框架的数据桥接
import { spawn } from 'child_process'
import { watch } from 'fs'
import { readFile, writeFile } from 'fs/promises'
import { join } from 'path'
interface BridgeConfig {
dataDir: string // ~/.openclaw/skillrl/
pythonScript: string // training/skillrl_trainer.py 的路径
batchThreshold: number // 积累多少条轨迹后触发训练
autoTrigger: boolean // 是否自动触发训练
checkIntervalMs: number // 检查间隔(毫秒)
}
class SkillRLBridge {
private config: BridgeConfig
private isTraining = false
constructor(config: BridgeConfig) {
this.config = config
}
/**
* 启动桥接服务
* 定期检查轨迹数量,达到阈值后触发 Python 训练
*/
startAutoTrigger(): void {
if (!this.config.autoTrigger) return
setInterval(async () => {
if (this.isTraining) return
const count = await this.getPendingTrajectoryCount()
if (count >= this.config.batchThreshold) {
console.info(`[SkillRL Bridge] ${count} 条轨迹已积累,触发训练...`)
await this.triggerTraining()
}
}, this.config.checkIntervalMs)
}
/**
* 监听模型更新信号
* Python 训练完成后会写入一个信号文件
*/
watchForModelUpdates(onNewModel: (modelPath: string) => void): void {
const signalFile = join(this.config.dataDir, 'model_update_signal.json')
watch(signalFile, async () => {
try {
const content = await readFile(signalFile, 'utf-8')
const signal = JSON.parse(content)
onNewModel(signal.modelPath)
} catch {
// 忽略解析错误
}
})
}
/**
* 触发 Python 训练进程
*/
async triggerTraining(): Promise<void> {
if (this.isTraining) {
console.warn('[SkillRL Bridge] 训练正在进行中,跳过')
return
}
this.isTraining = true
const trainer = spawn('python3', [
this.config.pythonScript,
this.config.dataDir
])
trainer.stdout.on('data', (data: Buffer) => {
console.info(`[SkillRL Trainer] ${data.toString().trim()}`)
})
trainer.stderr.on('data', (data: Buffer) => {
console.error(`[SkillRL Trainer Error] ${data.toString().trim()}`)
})
trainer.on('close', async (code: number) => {
this.isTraining = false
if (code === 0) {
console.info('[SkillRL Bridge] 训练完成')
// 写入信号文件通知 OpenClaw 加载新模型
await writeFile(
join(this.config.dataDir, 'model_update_signal.json'),
JSON.stringify({
modelPath: join(this.config.dataDir, 'models', 'latest'),
timestamp: Date.now()
}),
'utf-8'
)
} else {
console.error(`[SkillRL Bridge] 训练失败,退出码: ${code}`)
}
})
}
private async getPendingTrajectoryCount(): Promise<number> {
// 统计 trajectories/ 目录中的 JSONL 行数
// 简化实现
return 0
}
}
export { SkillRLBridge, BridgeConfig }
(九)完整使用示例(TypeScript)
在 OpenClaw 项目中集成 SkillRL 的完整示例:
// 使用示例:在 OpenClaw 项目中初始化 SkillRL
import { SkillRLOrchestrator } from './src/agents/skills/skillrl-orchestrator'
import { SkillRLBridge } from './src/agents/skills/skillrl-bridge'
// 1. 初始化 SkillRL 编排器
const orchestrator = new SkillRLOrchestrator({
skillsDir: `${process.env.HOME}/.openclaw/skills/skillrl`,
trajectoryExportDir: `${process.env.HOME}/.openclaw/skillrl/trajectories`,
llmGenerate: async (prompt: string) => {
// 使用 OpenClaw Gateway 管控的模型进行推理
// 实际对接 OpenClaw 的 LLM 调用接口
const response = await fetch('http://localhost:3000/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt, model: 'gpt-4o' })
})
const data = await response.json()
return data.text
},
maxSkillsPerPrompt: 3,
pruneMinSuccessRate: 0.2,
pruneMinUsage: 5
})
// 2. 初始化并加载已有技能
await orchestrator.initialize()
// 3. 启动数据桥接(自动触发 Python 训练)
const bridge = new SkillRLBridge({
dataDir: `${process.env.HOME}/.openclaw/skillrl`,
pythonScript: './training/skillrl_trainer.py',
batchThreshold: 100, // 积累 100 条轨迹后触发训练
autoTrigger: true,
checkIntervalMs: 30 * 60 * 1000 // 每 30 分钟检查一次
})
bridge.startAutoTrigger()
// 4. 监听模型更新
bridge.watchForModelUpdates((modelPath) => {
console.info(`新模型已就绪: ${modelPath}`)
// 通知 OpenClaw Gateway 切换到新模型
// 实际实现中需要调用 Gateway 的模型热切换 API
})
// 5. Agent 执行循环中使用
const observation = '变压器温度异常升高至 85°C,红外影像显示局部过热'
const task = '电力变电站设备异常处置'
// 技能增强推理
const action = await orchestrator.executeWithSkills(observation, task, 'power_inspection')
// 记录步骤
orchestrator.recordStep(observation, action, '已生成告警报告', 1.0)
// 会话结束
await orchestrator.onSessionEnd(task, true)
六、落地实施路径
(一)两条路径对比
路径 A:轻量方案(仅 OpenClaw TypeScript 侧,不训练模型)
OpenClaw Agent (TypeScript)
↓
推理时:SkillBank 检索技能 → 注入 Prompt → 模型推理
↓
执行后:收集轨迹 → LLM 蒸馏技能 → 更新 SKILL.md → 触发热更新
↓
循环(技能库在进化,但模型权重不变)
- 预期收益:获得 SkillRL 约 60-70% 的效果
- 适用场景:使用 GPT-4o / Qwen-72B 等大模型做推理,大模型本身足够聪明,只需要提供好的经验参考
- 优势:零训练成本,全 TypeScript 实现,快速验证
路径 B:完整方案(OpenClaw TypeScript + Python 训练框架)
┌───────────────────────┐ ┌──────────────────────┐
│ OpenClaw (TS) │ │ Python 训练框架 │
│ 推理 + 编排 + 技能管理 │ ←────→ │ TRL / veRL │
│ │ │ │
│ • SkillBank (TS) │ JSONL │ • SFT 冷启动 │
│ • 经验蒸馏 (TS) │ ──────→ │ • GRPO 策略优化 │
│ • Prompt 注入 (TS) │ │ • 模型权重更新 │
│ • 轨迹收集 (TS) │ 新模型 │ │
│ • Agent 协同 (TS) │ ←────── │ │
│ • 热更新 (TS) │ 信号文件 │ │
└───────────────────────┘ └──────────────────────┘
- 预期收益:获得 SkillRL 100% 的效果(论文中 7B 超越 GPT-4o 的效果)
- 适用场景:用自己的 7B/14B 小模型,追求极致性能
- 所需工具:TRL(trl.GRPOTrainer)、veRL、OpenRLHF 等
(二)数据交互格式
轨迹 JSONL 格式(OpenClaw TS → Python)
{
"task": "电力变电站设备异常处置",
"steps": [
{
"observation": "变压器温度异常升高至 85°C",
"action": "调用红外热成像分析工具",
"result": "检测到 A 相绕组局部过热",
"reward": 0.5
}
],
"totalReward": 2.5,
"success": true,
"timestamp": 1740700000000
}
模型更新信号(Python → OpenClaw TS)
{
"modelPath": "~/.openclaw/skillrl/models/skillrl-v3",
"timestamp": 1740700000000,
"metrics": {
"sftLoss": 0.23,
"grpoReward": 3.2,
"evaluationScore": 0.85
}
}
(三)分步落地建议
| 阶段 | 目标 | 方式 | 技术栈 | 周期 |
|---|---|---|---|---|
| 第一步(短期) | 验证 SkillRL 技能管理思路是否有效 | 仅 OpenClaw 内实现 SkillBank + 经验蒸馏 + Prompt 注入,用大模型推理 | TypeScript | 2-4 周 |
| 第二步(中期) | 训练专用小模型 | 引入 Python 训练框架,用收集的轨迹做 SFT + GRPO,训练 7B/14B 专用模型 | TS + Python | 1-2 月 |
| 第三步(长期) | 全闭环自动进化 | OpenClaw 编排 + 轨迹 + 技能管理,训练框架定期更新模型,两系统通过数据管道打通 | TS + Python | 持续 |
七、与巡检场景的适配要点
(一)技能分层设计
| 层级 | 巡检场景示例 |
|---|---|
| 通用技能 | 设备状态验证、异常信号初步判断、多 Agent 协同基础逻辑、巡检路径规划通用策略 |
| 电力巡检技能 | 变压器绝缘老化识别、输电线路覆冰检测、开关柜局部放电判断 |
| 化工巡检技能 | 管道泄漏检测流程、有毒气体浓度预警、压力容器安全评估 |
| 轨道交通技能 | 接触网巡检重点、轨道几何参数检测、信号设备状态判断 |
(二)蒸馏模板适配
成功轨迹蒸馏应重点提取:
- 关键决策阈值(如温度异常判定标准)
- 设备操作的标准化流程
- 多设备协同的调度逻辑
失败轨迹蒸馏应重点提取:
- 误判的根本原因(特征提取不精准、环境干扰等)
- 极端场景的防护原则
- 设备兼容性问题的规避策略
(三)SKILL.md 巡检示例
---
name: transformer-overheat-detection
description: 变压器过热异常检测与应急处置技能
version: 2.1.0
skillType: task_specific
successRate: 0.87
usageCount: 42
applicableScenarios:
- 电力变电站日常巡检
- 高负荷期间设备监控
- 高温天气特巡
---
# 变压器过热异常检测
## 策略模式
1. 获取红外热成像数据,识别温度异常区域
2. 对比历史基线温度(近 7 天均值 ± 2σ)
3. 判断是否超过安全阈值(油面 85°C / 绕组 105°C)
4. 超阈值则立即生成 I 级告警并推送运维
5. 记录异常时间序列,关联负荷数据分析趋势
## 高层脚本
采集温度 → 基线对比 → 阈值判断 → 告警分级 → 运维推送 → 趋势分析
## 失败教训
- 仅看瞬时温度容易被环境温度波动干扰,必须结合历史基线
- 高负荷时段温度升高属正常工况,需关联负荷数据判断
八、总结
(一)核心架构
SkillRL 在 OpenClaw 中的实现分为两个技术栈:
| 层面 | 技术栈 | 职责 |
|---|---|---|
| Agent 编排 + 技能管理 | TypeScript(OpenClaw) | SkillBank 管理、经验蒸馏、Prompt 注入、轨迹收集、SKILL.md 热更新 |
| 模型训练 | Python(TRL / veRL) | 冷启动 SFT、GRPO 策略优化、模型权重更新 |
两者通过 JSONL 轨迹文件 和 模型更新信号文件 实现跨语言通信。
(二)关键对接点
OpenClaw 原有的 Skills 系统天然适合 SkillRL:
- SKILL.md 文件格式 → 直接用来存储蒸馏出的结构化技能
- 热更新机制(
ensureSkillsWatcher()) → 新技能写入后自动被 Agent 感知 - 快照版本系统(
buildWorkspaceSkillSnapshot()) → 保证技能一致性 - Session JSONL 日志 → 现成的轨迹记录基础设施
- 子智能体编排(
sessions.spawn) → 支持复杂任务的递归分解
(三)落地建议
建议采用渐进式策略:
- 短期:仅在 OpenClaw TypeScript 侧实现 SkillBank + 经验蒸馏 + Prompt 注入,用大模型推理,验证技能管理思路
- 中期:引入 Python 训练框架,用收集的轨迹做 SFT + GRPO,训练专用小模型
- 长期:打通 OpenClaw 和训练框架的数据管道,实现 Agent 的自主进化闭环
更多推荐

所有评论(0)