Skip to content

uuuyq/simpleclaw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

SimpleClaw - Skill 系统说明

概述

SimpleClaw 的 Skill(技能)系统是一种「可插拔专家指令」机制。每个 Skill 是一个 SKILL.md 文件,描述如何完成某类特定任务(如转录音频、操作 GitHub、调用外部 API)。模型在 System Prompt 中看到技能列表,当用户请求匹配时自行读取技能文件并遵循其指令执行。


Skill 文件结构

Skill 由目录 + SKILL.md 文件构成,文件分 YAML frontmatterMarkdown 正文 两部分:

skills/
  openai-whisper-api/
    SKILL.md          ← 主入口
    scripts/
      transcribe.sh   ← 技能引用的辅助脚本

Frontmatter 字段(YAML)

字段 必须 说明
name 技能唯一标识名,fallback 为目录名
description 一句话描述,展示在 System Prompt 的 <available_skills>
homepage 官网链接,UI 可点击
user-invocable 是否允许用户通过 /skill 命令直接调用(默认 true
disable-model-invocation 设为 true 则不出现在 System Prompt,仅供内部引用(默认 false
metadata.openclaw OpenClaw 扩展元数据(见下文)

OpenClaw 扩展元数据(metadata.openclaw)

字段 类型 说明
always boolean 设为 true 时忽略 env/bin 检测,始终加载
emoji string UI 展示用图标
skillKey string 覆盖默认的配置 key(默认等于 name)
primaryEnv string 主 API Key 环境变量名(UI 可配置)
os string[] 限定适用平台,如 ["darwin", "linux"]
requires object 运行时依赖要求(见下文)
install object[] 安装规格列表

SkillRequires 运行时依赖

字段 类型 逻辑 说明
bins string[] AND 所有 bin 都必须存在
anyBins string[] OR 任一 bin 存在即可
env string[] AND 所有 env 变量都必须设置
config string[] AND 配置路径条件,如 "browser.enabled"

Skill 文件示例

---
name: openai-whisper-api
description: Transcribe audio using OpenAI Whisper API
homepage: https://platform.openai.com/docs/guides/speech-to-text
user-invocable: true
metadata:
  openclaw:
    emoji: 🎤
    primaryEnv: OPENAI_API_KEY
    os: [darwin, linux, windows]
    requires:
      env: [OPENAI_API_KEY]
      bins: [curl]
---

# OpenAI Whisper API

## Usage

```bash
curl https://api.openai.com/v1/audio/transcriptions \\
  -H "Authorization: Bearer $OPENAI_API_KEY" \\
  -F file="@{baseDir}/audio.mp3" \\
  -F model=whisper-1

Parameters

  • file: Audio file path (supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm)
  • model: Always use whisper-1
  • language: Optional, ISO-639-1 code (e.g., en, zh)
  • response_format: Optional, json, text, srt, verbose_json, vtt

> **注意**:正文中的 `{baseDir}` 是技能根目录的占位符,模型在 System Prompt 指引中被告知将相对路径解析为技能目录的绝对路径。

---

## Skills 加载机制

### 扫描源(按优先级从低到高)

| 优先级 | 源 | 路径 | source 标签 |
|--------|----|------|-------------|
| 1 | 内置捆绑技能 | `<install>/skills/` | `openclaw-bundled` |
| 2 | 托管技能 | `~/.simpleclaw/skills/` | `openclaw-managed` |
| 3 | 工作区技能 | `<workspace>/skills/` | `openclaw-workspace` |
| 4 | 额外目录 | `config.skills.extraDirs` 配置 | `openclaw-extra` |

同名技能(按 `skill.name`)**高优先级源覆盖低优先级源**,最终合并到一张 `Map<name, Skill>`。

### 单目录扫描逻辑

1. 若目录本身有 `SKILL.md`,将整个目录视为一个技能,直接返回
2. 否则遍历一级子目录,每个含 `SKILL.md` 的子目录是一个技能
3. 过滤隐藏目录(`.` 开头)和 `node_modules`
4. 跳过超出大小上限(默认 256KB)的 `SKILL.md`

---

## 配置参数

Skills 系统的所有配置位于 `config.yml` 的 `skills` 节点下:

```yaml
skills:
  # 是否加载内置技能(默认 true)
  loadBundled: true
  
  # 内置技能白名单(null 或空列表表示无限制)
  allowBundled:
    - openai-whisper-api
    - github-cli
  
  # 被禁用的技能列表
  disabledSkills:
    - deprecated-skill
  
  # 额外技能目录列表
  extraDirs:
    - /path/to/custom/skills
    - /another/skill/dir
  
  # 容量限制配置
  maxCandidatesPerRoot: 300      # 每根最多候选目录数(默认 300)
  maxSkillsLoadedPerSource: 200  # 每源最多加载技能数(默认 200)
  maxSkillsInPrompt: 150         # Prompt 最多展示技能数(默认 150)
  maxSkillsPromptChars: 30000    # Prompt 最大字符数(默认 30000)
  maxSkillFileBytes: 256000      # 单技能文件最大字节(默认 256KB)

配置项说明

配置键 默认值 说明
skills.loadBundled true 是否加载内置捆绑技能
skills.allowBundled null 内置技能白名单,限制只能加载列表中的技能
skills.disabledSkills [] 被禁用的技能名称列表
skills.extraDirs [] 额外的技能目录路径列表
skills.maxCandidatesPerRoot 300 每根目录最多扫描的候选目录数
skills.maxSkillsLoadedPerSource 200 每个来源最多加载的技能数
skills.maxSkillsInPrompt 150 System Prompt 中最多展示的技能数
skills.maxSkillsPromptChars 30000 技能相关 Prompt 的最大字符数
skills.maxSkillFileBytes 256000 单个 SKILL.md 文件的最大字节数

Skills 过滤与可见性

运行时过滤规则

技能加载时会进行多维度过滤(全部条件为 AND 关系):

  1. 用户禁用检查skillConfig.enabled !== false
  2. 白名单检查:如配置了 skills.allowBundled,内置技能必须在白名单内
  3. 运行时环境检查evaluateRuntimeEligibility()):
    • os:当前平台在允许平台列表内(无列表则不限)
    • requires.bins:所有必需二进制文件可执行
    • requires.anyBins:至少一个 bin 可执行
    • requires.env:所有必需 env 变量非空
    • requires.config:所有配置路径条件为真
    • always=true:跳过所有运行时检查,强制加载

可见性控制

标志 说明
user-invocable: false 不允许用户通过 /skill 命令直接调用
disable-model-invocation: true 不出现在 System Prompt 的 <available_skills> 中,但仍可被内部引用访问

Skills 在 System Prompt 中的注入

格式示例

<available_skills>
<skill name="openai-whisper-api" description="Transcribe audio using OpenAI Whisper API" path="~/.simpleclaw/skills/openai-whisper-api/SKILL.md" />
<skill name="github-cli" description="Execute GitHub CLI commands" path="~/.simpleclaw/skills/github-cli/SKILL.md" />
</available_skills>

<skill_usage_instructions>
When a user request matches a skill, use the read_file tool to read the SKILL.md 
and follow its instructions. The {baseDir} placeholder in skill content refers 
to the skill's root directory.
</skill_usage_instructions>

路径压缩

为节省 Token,技能路径中的 $HOME/ 会被替换为 ~/

  • 原路径:/Users/alice/.simpleclaw/skills/foo/SKILL.md
  • 压缩后:~/.simpleclaw/skills/foo/SKILL.md

每个路径节约 5-6 token,100 个技能约节约 500 token。

惰性加载设计

模型只知道技能文件的路径,不预先加载内容。当任务匹配时模型调用 read_file 工具读取 SKILL.md,再按内容执行。这避免了所有技能文件内容涌入上下文。


核心类说明

Skill(模型类)

public class Skill {
    private String name;           // 技能名称
    private String description;    // 技能描述
    private String source;         // 来源标签
    private SkillMetadata metadata; // 扩展元数据
    
    // 检查是否始终加载(忽略 env/bin 检测)
    public boolean isAlwaysLoaded()
    
    // 获取主环境变量名
    public String getPrimaryEnv()
}

SkillMetadata(元数据)

public class SkillMetadata {
    private boolean always;        // 是否始终加载
    private String emoji;          // UI 图标
    private String skillKey;       // 配置 key
    private String primaryEnv;     // 主 API Key 环境变量
    private List<String> os;       // 适用平台列表
    private SkillRequires requires; // 运行时依赖
    private List<Map<String, Object>> install; // 安装规格
    
    // 检查平台限制
    public boolean isOsAllowed(String currentOs)
}

SkillRequires(运行时依赖)

public class SkillRequires {
    private List<String> bins;     // 必须存在的二进制(AND)
    private List<String> anyBins;  // 任一存在的二进制(OR)
    private List<String> env;      // 必须设置的环境变量
    private List<String> config;   // 配置路径条件
    
    // 检查是否有任何依赖要求
    public boolean hasRequirements()
}

SkillsLoader(加载器)

public class SkillsLoader {
    // 加载所有可用技能(按优先级合并)
    public Map<String, Skill> loadAllSkills()
    
    // 获取启用的技能列表(根据配置和运行时环境过滤)
    public List<Skill> getEnabledSkills(List<String> skillFilter)
}

SkillParser(解析器)

public class SkillParser {
    // 解析 SKILL.md 文件,提取 YAML frontmatter 和 Markdown 正文
    public Optional<Skill> parseSkillFile(Path file, String source)
}

使用示例

创建自定义 Skill

  1. 在工作区创建技能目录:
mkdir -p my-project/skills/my-custom-skill
  1. 创建 SKILL.md 文件:
---
name: my-custom-skill
description: Execute custom data processing tasks
metadata:
  openclaw:
    emoji: 📊
    requires:
      bins: [python3]
---

# My Custom Skill

## Usage

Run the processing script:

```bash
python3 {baseDir}/scripts/process.py --input "$INPUT_FILE"

3. 放置辅助脚本:
```bash
mkdir -p my-project/skills/my-custom-skill/scripts
echo '#!/usr/bin/env python3
import sys
print(f"Processing: {sys.argv}")' > my-project/skills/my-custom-skill/scripts/process.py

配置技能加载

config.yml 中添加:

skills:
  extraDirs:
    - /absolute/path/to/more/skills
  disabledSkills:
    - some-unwanted-skill

注意事项

  1. 技能名称唯一性:同名技能高优先级源会覆盖低优先级源
  2. 路径安全:技能路径必须在允许的目录范围内,禁止软链接逃逸
  3. 文件大小限制:默认单技能文件最大 256KB,超大文件会被跳过
  4. 运行时检测:依赖检测失败会导致技能被过滤,不会出现在 Prompt 中
  5. 惰性加载:模型需要时才会读取 SKILL.md 内容,不会自动加载

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages