SkillRL 技术分析与基于 OpenClaw 的落地实现方案

一、论文概述

(一)基本信息

  • 论文标题:SkillRL: Evolving Agents via Recursive Skill-Augmented Reinforcement Learning
  • 来源:arXiv 2602.08234
  • 研究团队:UNC-Chapel Hill、芝加哥大学、UCSD、伯克利联合发表
  • 开源代码aiming-lab/SkillRL

(二)核心问题

现有 LLM Agent 存在两大痛点:

  1. 基于记忆的方法(Memory-based):存储原始轨迹,冗余且噪声严重,难以有效复用,上下文窗口被大量无关细节占满
  2. 标准 RL 方法:缺乏结构化知识的跨任务迁移机制,学到的策略难以泛化到新场景

SkillRL 的目标是:将原始经验自动蒸馏为结构化、可复用的高层行为模式(技能),并让技能与模型策略在递归训练中共同演化

(三)核心创新

创新点 说明
经验蒸馏机制 从成功轨迹提取「战略演示」,从失败轨迹提炼「反事实教训」,转化为结构化技能
分层技能库(SkillBank) 分为通用技能(跨任务可迁移)和任务特定技能(针对特定场景),支持自适应检索
递归演化机制 技能库在 RL 训练过程中与 Agent 策略动态共同演化,每轮迭代都更新技能库内容

(四)训练流程

  1. 冷启动 SFT(监督微调):用初始成功轨迹对模型进行监督微调,给模型一个基础能力起点
  2. 递归 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:

  1. SKILL.md 文件格式 → 直接用来存储蒸馏出的结构化技能
  2. 热更新机制ensureSkillsWatcher()) → 新技能写入后自动被 Agent 感知
  3. 快照版本系统buildWorkspaceSkillSnapshot()) → 保证技能一致性
  4. Session JSONL 日志 → 现成的轨迹记录基础设施
  5. 子智能体编排sessions.spawn) → 支持复杂任务的递归分解

(三)落地建议

建议采用渐进式策略:

  1. 短期:仅在 OpenClaw TypeScript 侧实现 SkillBank + 经验蒸馏 + Prompt 注入,用大模型推理,验证技能管理思路
  2. 中期:引入 Python 训练框架,用收集的轨迹做 SFT + GRPO,训练专用小模型
  3. 长期:打通 OpenClaw 和训练框架的数据管道,实现 Agent 的自主进化闭环
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐