OpenClaw 技能系统深度解析:从 SKILL.md 到自动触发的工程链路 原创
引言
OpenClaw 的技能系统(Skill System)是其区别于普通聊天机器人的核心架构之一。一个技能本质上是一份 SKILL.md 文件,包含触发条件、步骤指令和可选的辅助文件。本文从源码层面拆解技能的注册、匹配、加载和执行链路,帮助你理解从”写一个 SKILL.md”到”技能被自动触发”中间发生了什么。
一、技能系统的设计哲学
OpenClaw 技能系统遵循三个设计原则:
- 声明式触发:技能通过 description 字段声明自己适用于什么场景,而非硬编码 if-else 分支
- 文件即技能:每个技能就是一个 SKILL.md 文件加可选辅助文件,无数据库、无编译
- 渐进式加载:模型先看到技能摘要,需要时才读取完整内容,节省 context 窗口
二、SKILL.md 结构规范
一个标准的 SKILL.md 文件结构如下:
---
name: blog-publishing
description: Publish or update articles on blog.azcore.top WordPress.
Use when user asks to publish, post, update, or write articles
to the blog, or mentions blog.azcore.top article publishing.
---
# Blog Publishing
## Prerequisites
- Server credentials are in KNOWN_ISSUES.md
## Steps
1. Write article as HTML file locally
2. Connect via paramiko and upload
3. Publish with wp-cli
4. Set original mark via MySQL
5. Verify with wp post list
关键字段解析:
| 字段 | 作用 | 规范 |
|---|---|---|
| name | 技能唯一标识 | 小写+连字符,2-4 词 |
| description | 触发条件声明 | 前 60 字符必须包含触发词 |
| 正文 | 执行步骤 | 有序步骤,每步以可验证的完成条件结尾 |
三、技能注册与发现机制
OpenClaw 在启动时会扫描多个目录层级,将技能注册到内部索引:
技能目录层级
# 内置技能(随 OpenClaw 分发)
~/.local/lib/node_modules/openclaw/skills/
~/.local/lib/node_modules/openclaw/custodian-skills/
# 工作区技能(用户自定义)
~/.openclaw/workspace/skills/
# 代理技能(绑定到特定 Agent)
~/.openclaw/agents/main/agent/workshop-skills/
# 插件技能(随插件安装)
~/.openclaw/plugin-skills/
# 技能库(通过 CLI 安装)
~/.openclaw/skills/
扫描过程在 Gateway 启动时完成,每个目录下的 SKILL.md 被解析后注册到全局技能表。技能优先级从高到低:
- Workshop 技能(workshop-skills/)- 最高优先级,Agent 专属
- 工作区技能(workspace/skills/)- 用户级
- 插件技能(plugin-skills/)- 插件提供
- 内置技能(skills/, custodian-skills/)- 系统级
四、触发匹配算法
当用户消息到达时,OpenClaw 不会把所有技能全文塞给模型。匹配分两步:
第一步:摘要注入
系统将所有注册技能的 name + description 压缩为 <available_skills> XML 块注入到 system prompt 中:
<available_skills>
<skill>
<name>blog-publishing</name>
<description>Publish or update articles on blog.azcore.top...</description>
<location>~/.openclaw/agents/main/agent/workshop-skills/blog-publishing/SKILL.md</location>
</skill>
...
</available_skills>
模型基于摘要判断是否需要某个技能。这一步消耗的 token 极少(每个技能约 50-100 token)。
第二步:按需读取
当模型判断某个技能匹配当前任务时,调用 read 工具读取 <location> 指向的 SKILL.md 完整内容。只有被读取的技能才会占用 context 窗口。
Scan <available_skills>. Clear match: read exact <location> with `read`; obey.
Several: most specific. None: read none.
Up-front max one. Never invent paths.
这段系统指令确保模型一次最多读取一个技能(除非明确需要多个),且只能读取列出的路径,不能自行编造。
五、description 写法对触发率的影响
description 是技能被正确触发的关键。几个实测有效的写法规则:
1. 触发词前置
前 60 字符是模型注意力最集中的区域。将最可能出现的用户关键词放在最前面:
# 好
description: Publish or update articles on blog.azcore.top WordPress.
Use when user asks to publish, post, update...
# 差
description: This skill provides comprehensive blog publishing
capabilities including article creation...
2. 一个 description 覆盖一个触发分支
如果一个技能有多个触发场景(比如”发布文章”和”更新文章”),在 description 中分别列出,而不是笼统描述:
description: Publish or update articles on blog.azcore.top WordPress.
Use when user asks to publish, post, update, or write articles
to the blog, or mentions blog.azcore.top article publishing.
3. 包含用户可能使用的原词
模型做语义匹配时,用户原词出现在 description 中会显著提高匹配率。包括中英文双语关键词:
description: Find and install OpenClaw skills (技能, 找技能, find-skill).
Use when users ask about skills or capability extension.
六、辅助文件与技能打包
一个技能不仅仅是 SKILL.md,可以包含辅助文件:
blog-publishing/
├── SKILL.md # 主技能文件
├── assets/
│ └── template.html # 文章模板
├── scripts/
│ └── publish.py # 发布脚本
├── examples/
│ └── example.md # 示例
└── references/
└── api-docs.md # 参考文档
SKILL.md 中通过相对路径引用辅助文件:
## Steps
1. Read the article template at `assets/template.html`
2. Fill in content following `examples/example.md`
3. Run `scripts/publish.py` to publish
模型在执行步骤时按需读取辅助文件。相对路径解析基准是 SKILL.md 所在目录。
七、Skill Workshop:技能的生命周期管理
OpenClaw 提供 Skill Workshop 系统管理技能的创建、评审和应用流程:
生命周期
create → revise → evaluate → apply → live
↘ reject
↘ quarantine
| 阶段 | 操作 | 说明 |
|---|---|---|
| create | skill_workshop(action=create) | 创建待审提案 |
| revise | skill_workshop(action=revise) | 修改提案内容 |
| evaluate | skill_workshop(action=evaluate) | 运行评估器检查质量 |
| apply | skill_workshop(action=apply) | 激活为正式技能 |
| reject | skill_workshop(action=reject) | 拒绝提案 |
关键设计:create/update 不会立即生效,必须经过 apply 步骤。这确保了技能变更的可审计性。在独立运行模式下,agent 可以自主创建和应用技能;在需要人工审批的模式下,提案保持 pending 状态等待用户确认。
八、技能与 Agent 的协同
在多 Agent 场景下,技能系统有几个关键行为:
1. Agent 专属技能
放在 workshop-skills/ 下的技能只对该 Agent 可见。例如 main agent 有 blog-publishing 技能,而其他 agent 不会看到它。
2. 子代理继承
通过 sessions_spawn 创建的子代理继承父代理的工作区,因此也能访问工作区级技能。但 Workshop 专属技能不会传递。
3. 技能与工具的关系
技能是”如何做”的知识,工具是”做什么”的能力。技能指导模型调用哪些工具、按什么顺序调用、如何处理结果。一个技能可能涉及多个工具的编排,但技能本身不提供新的工具能力。
九、性能优化与最佳实践
控制 SKILL.md 体积
SKILL.md 应保持在 10,000 字符以内。长篇的参考文档、数据表、示例应该拆到辅助文件中,只在需要时读取。这直接影响 context 窗口利用率。
避免冗余步骤
技能正文中的每一句话都应该改变行为。重复默认行为、复制其他技能内容、描述一次性任务的句子应该删除。原则:
# 好
"Run `wp post create` with --allow-root flag"
# 差
"You can use wp-cli to create posts. The wp-cli tool is a command-line
interface for WordPress. To create a post, you should..."
描述验证闭环
每个步骤以可验证的完成条件结尾,让模型能自检是否完成了该步骤:
## Steps
1. Write article HTML to /tmp/article.html
# Verify: `ls /tmp/article.html` exists and size > 0
2. Upload via paramiko
# Verify: SFTP put returns success
3. Publish with wp-cli
# Verify: Output contains "Success: Created post <ID>"
十、调试技能触发问题
如果技能没有被正确触发,排查步骤:
- 检查技能是否注册:确认 SKILL.md 在正确的目录下,且有有效的 frontmatter
- 检查 description:前 60 字符是否包含用户可能使用的关键词
- 检查 <available_skills>:在对话中搜索 system prompt 是否包含该技能条目
- 检查路径:location 字段指向的文件是否存在且可读
- 检查优先级冲突:是否有更高优先级的技能抢占了匹配
# 快速检查技能是否被加载
ls ~/.openclaw/workspace/skills/my-skill/SKILL.md
# 确认 frontmatter 格式正确
head -5 ~/.openclaw/workspace/skills/my-skill/SKILL.md
总结
OpenClaw 技能系统的精巧之处在于:用一份 Markdown 文件同时承担了”触发条件声明”、”执行步骤指南”和”辅助资源索引”三个角色。模型通过摘要做语义匹配,按需读取完整内容, Workshop 管理生命周期。理解了这条链路,就能写出触发率高、执行可靠的技能。核心是:description 决定是否被触发,正文决定执行质量。