技能即文档 —— SKILL.md 如何让 OpenClaw 自主学习新工具
关键词:SKILL.md|工具自描述|Markdown 解析|函数调用|动态注册|开发者友好
在传统 AI 系统中,为智能体添加新能力(如“查询数据库”或“部署服务”)通常需要:
- 编写 TypeScript 函数
- 注册到工具列表
- 更新提示词(prompt)
- 重启服务
这一过程对开发者不友好,更无法由非技术人员参与。OpenClaw 提出一种全新范式:技能即文档(Skill-as-Documentation)。
其核心载体是 SKILL.md —— 一个纯 Markdown 文件,既可被人类阅读,也能被 AI 和系统解析,自动注册为可用工具。无需代码、无需重启,只需写一篇清晰的说明文档,AI 就能学会新技能。
本文将详解 SKILL.md 的设计哲学、语法规范、解析机制与工程价值。
一、为什么需要 SKILL.md?
传统工具注册的痛点

OpenClaw 的愿景
让任何懂业务的人(开发者、运维、产品经理)都能通过写文档,教会 AI 新能力。
二、SKILL.md 核心设计:三段式结构
每个 SKILL.md 文件包含三个标准化区块:
# 查询用户订单状态
根据用户 ID 和订单号,从内部数据库获取订单当前状态。
## 参数
- `userId` (string): 用户唯一标识,格式为 `user_abc123`
- `orderId` (string): 订单编号,如 `ORD-2024-089`
## 执行
调用内部 API:`GET /api/v1/orders?userId={{userId}}&orderId={{orderId}}`
> 需要 `orders:read` 权限。
1. 标题 + 描述(供 AI 理解用途)
- 标题 = 工具名称(
query_user_order) - 描述 = 工具功能摘要(注入 prompt)
2. 参数区块(结构化输入)
- 使用
- name (type): description格式 - 支持类型:
string、number、boolean、array - 可选标记:
[optional]、[default: "value"]
3. 执行区块(系统如何调用)
- 可包含:
- Shell 命令(由
exec.ts执行) - HTTP 请求(由内置 HTTP 客户端执行)
- 调用其他技能(组合技能)
- Shell 命令(由
- 支持 Mustache 模板变量:
{{userId}}
一份文档,三重用途:人类阅读、AI 理解、系统执行。
三、文件组织与发现机制
目录结构
agents/
└── customer-support/
├── config.yaml
└── skills/
├── query_user_order.SKILL.md
├── refund_order.SKILL.md
└── check_inventory.SKILL.md
- 每个智能体拥有独立
skills/目录 - 文件名自动转为工具 ID(下划线命名)
动态加载
- OpenClaw 启动时扫描所有
*.SKILL.md - 热重载支持:文件修改后自动重新解析(无需重启)
- 解析失败时记录警告,不影响其他技能
所见即所得,改完即生效。
四、解析器:从 Markdown 到 Tool Schema
src/skills/parse-skill-md.ts 负责将 SKILL.md 转为结构化工具定义:
解析流程
- 按标题分割区块
const sections = markdown.split(/^##\s+/m); - 提取参数
/^-\s+([a-zA-Z0-9_]+)\s+\((string|number|boolean|array)\)(?:\s+\[optional\])?(?:\s+\[default:\s+(.+?)\])?\s*:\s*(.+)$/ - 识别执行指令
- 若以
http:或https:开头 → HTTP 工具 - 若包含
$或bash:→ Shell 工具 - 否则视为描述性文本(仅用于 prompt)
- 若以
输出结构(兼容 OpenAI Function Calling)
interface ParsedSkill {
name: string; // "query_user_order"
description: string; // "根据用户 ID 和订单号..."
parameters: {
type: "object",
properties: {
userId: { type: "string", description: "..." }
},
required: ["userId", "orderId"]
};
implementation: {
type: "http" | "shell" | "composite";
template: string; // "GET /api/v1/orders?userId={{userId}}..."
}
}
输出可直接注入 LLM 的
tools字段。
五、执行引擎:三种技能类型
1. HTTP 技能
## 执行
GET https://api.example.com/users/{{userId}}
Headers:
Authorization: Bearer {{env.API_KEY}}
- 自动注入环境变量(如
{{env.API_KEY}}→process.env.API_KEY) - 支持 POST/PUT,自动序列化 JSON body
2. Shell 技能
## 执行
$ kubectl get pod {{podName}} -n {{namespace}}
- 交由
exec.ts执行(继承三层隔离模型) - 自动申请权限提升(如需)
3. 复合技能(Composite Skill)
## 执行
先调用 `get_user_profile(userId={{userId}})`,
再调用 `check_subscription_status(profileId=...)`
- 系统识别
调用 \xxx`` 模式 - 自动编排多步工具调用
- 支持中间结果传递
技能可组合,能力可叠加。
六、安全与权限控制
SKILL.md 虽然易写,但安全不容妥协:
1. 环境变量白名单
- 仅允许引用预定义的 env 变量:
# config.yaml allowedEnvVars: - "API_KEY" - "DB_HOST" - 禁止
{{env.HOME}}、{{env.PATH}}等敏感变量
2. HTTP 域名限制
- 可配置允许的域名:
allowedHttpHosts: - "api.internal.example.com" - "localhost:8080"
3. Shell 命令审批
- 所有 Shell 技能默认需用户审批(即使写在
SKILL.md中)
开放不等于放任。
七、实战案例:客服机器人新增“退款”技能
步骤 1:创建 skills/refund_order.SKILL.md
# 为用户发起退款
根据订单号和退款原因,向财务系统提交退款请求。
## 参数
- `orderId` (string): 订单编号
- `reason` (string): 退款原因(如“商品损坏”)
- `amount` (number) [optional]: 退款金额(默认全额)
## 执行
POST https://finance.internal.example.com/refunds
Body:
{
"orderId": "{{orderId}}",
"reason": "{{reason}}",
"amount": {{amount || "null"}},
"operator": "{{session.userId}}"
}
Headers:
Authorization: Bearer {{env.FINANCE_API_KEY}}
步骤 2:保存文件
- OpenClaw 自动加载,注册新工具
refund_order
步骤 3:用户对话
用户:“订单 ORD-2024-089 商品破损,请退款。”
AI 行为:
- 识别意图 → 调用
refund_order(orderId="ORD-2024-089", reason="商品破损") - 自动填充
operator为当前客服 ID - 发送 HTTP 请求
- 返回:“退款已提交,预计 3 个工作日内到账。”
从需求到上线,只需写一篇文档。
八、与传统方法对比

结语:文档即代码,技能即服务
SKILL.md 的本质,是将“工具定义”从代码中解放出来,使其成为一种声明式、可协作、自包含的知识单元。它模糊了“文档”与“程序”的边界,让 AI 的能力扩展变得像写 Wiki 一样简单。
这不仅是工程优化,更是人机协作范式的升级——未来,教会 AI 做事,或许只需说一句:“我写了个 SKILL.md,你看看能不能用。”
在下一篇中,我们将探讨 OpenClaw 的 Web UI 架构,解析其如何实现低延迟、高一致性的多端体验。
下一篇预告:
第 14 篇:Web UI 架构 —— 如何实现与 CLI/WhatsApp 一致的交互体验
浙公网安备 33010602011771号