简介
OpenClaw 的真正威力在于其可扩展性。如果说模型(Model)是大脑,那么技能(Skill)就是双手。尽管 ClawdHub 社区注册表已包含数百个开箱即用的技能,但您可能还需要与自有公司 API、数据库系统或本地化硬件集成。
本指南将带您使用 Node.js 构建一个名为"WeatherCheck"的技能,将其暴露给 OpenClaw Agent,并正确格式化模型上下文协议(MCP)。
1. 理解架构(MCP)
OpenClaw 支持 Anthropic 的开放标准:模型上下文协议(MCP)。这意味着您无需编写脆弱的自定义解析器。您只需构建一个标准的 JSON-RPC 服务器(或 HTTP SSE 流),并暴露以下内容:
- 资源(Resources): 资源(Resources):模型可以选择读取的静态上下文(例如:"公司 API 文档")。
- 工具(Tools): 工具(Tools):模型可以决定执行的动作(例如:"fetch_weather_by_city")。
2. 项目初始化
让我们使用官方 MCP SDK 创建一个新的 Node.js 包。
mkdir my-first-skill && cd my-first-skill
npm init -y
npm install @modelcontextprotocol/sdk3. 编写技能服务器
创建一个 index.js 文件。我们将定义一个使用 stdio 传输的 MCP 服务器(这是 OpenClaw 启动并与您的本地技能通信的最简单方式)。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Initialize the standard MCP server
const server = new McpServer({
name: "WeatherCheck-Skill",
version: "1.0.0"
});
// Register a Tool that the AI can call
server.tool("get_weather",
"Fetch current weather for a specific city",
{
city: z.string().describe("The name of the city (e.g. London, Beijing)")
},
async ({ city }) => {
console.error(`Fetching hardware sensor or API for: ${city}`);
const mockTemp = Math.floor(Math.random() * 30);
return {
content: [{ type: "text", text: `The weather in ${city} is ${mockTemp}°C and Sunny.` }]
};
}
);
// Connect via standard I/O pipes
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("WeatherCheck Skill is running on stdio!");4. 在 OpenClaw 中注册技能
打开您的 ~/.openclaw/config.json(或根据版本为 skills.yml),告诉 OpenClaw 如何启动您的新 MCP 服务器。
{
"mcpServers": {
"weather_check": {
"command": "node",
"args": ["/absolute/path/to/my-first-skill/index.js"]
}
}
}5. 测试集成
重启您的 OpenClaw 守护进程,然后向 AI 提问:
嘿,今天在巴黎需要带伞吗?
如果配置正确,LLM 将在其上下文中看到 get_weather 工具,为'巴黎'生成 JSON 调用参数,您的 index.js 将返回模拟文本。LLM 随后会读取该文本并自然地回复您。
技能到底是个什么东西
这个词听起来比实际复杂。一个技能就是一个 Markdown 文件,带两个必填的 frontmatter 字段,用来告诉模型什么时候该出手、以及出手要做什么。没有插件 API 要学,也没有东西需要编译。
| 字段 | 必填 | 作用 |
|---|---|---|
| name | 是 | 小写字母、数字和连字符。技能的身份是它,不是文件夹名。 |
| description | 是 | 一行,160 字符以内。模型正是靠它来判断这个技能跟当前任务有没有关系。 |
| user-invocable | 否 | 是否作为斜杠命令出现。默认为 true。 |
| disable-model-invocation | 否 | 把它挡在系统提示词之外,于是只有你能手动触发。 |
| homepage | 否 | 在技能发现界面里展示。 |
description 承担的作用比文件里其他任何部分都大。模型在决定要不要用这个技能时,唯一看得到的就是它——所以「从 git log 生成发布说明」会被用到,而「发布说明助手」不会。把它写成对「我什么时候该用这个」的回答,而不是写成一个标题。
写一个,并让它被加载
整个流程就四条命令,唯一会绊住人的是最后一步:技能是在会话开始时读取的,所以一个已经在进行中的对话看不到你刚写好的文件。
mkdir -p ~/.openclaw/workspace/skills/hello-world cd ~/.openclaw/workspace/skills/hello-world
随便嵌套——`personal/my-skill/SKILL.md` 和放在顶层是一样的,因为身份来自 frontmatter 而不是路径。
cat > SKILL.md <<'MD' --- name: hello-world description: A simple skill that prints a greeting. --- # Hello World When the user asks for a greeting, use the `exec` tool to run: ```bash echo "Hello from your custom skill!" ``` MD
正文就是写给模型看的纯 Markdown。先写触发条件、再写操作步骤;一个只讲了「怎么做」却没讲「什么时候做」的技能,会一直闲置。
# Skills are picked up on a fresh session, not live. # In a chat, start one with: /new # # Or test it from the shell: openclaw agent --message "give me a greeting"
这就是大家会漏掉的那一步。网关确实在监视这些文件,但一个进行中的会话早已把提示词组装好了。让技能可见的是 `/new`。
# Invoke it directly by name instead of hoping it gets chosen: # /skill hello-world
如果 `/skill hello-world` 能跑、但用自然语言问就不行,那说明技能本身没问题,问题在 description。分清这两者能省掉大量瞎猜。
装别人的,以及发布你自己的
ClawHub 是公共注册表。这里涉及两个不同的工具,把它们搞混是最常见的第一个坎:`openclaw skills` 负责查找和安装,而独立的 `clawhub` CLI 负责发布这类需要登录的操作。
npm i -g clawhub clawhub login
发布需要账号,所以它独立成一个工具,而不在 Agent 的 CLI 里。注意 `openclaw skills` 没有 publish 子命令——去找它是个常见的死胡同。
clawhub skill publish ./my-skill --slug my-skill
路径指向包含 SKILL.md 的那个文件夹。可用参数有 `--slug`、`--version`、`--changelog`、`--tags`;注册表会记录版本、下载量和一份安全扫描摘要。
openclaw skills search "calendar" openclaw skills install @openclaw/demo openclaw skills update --all
这些会装进你当前的工作区,并记录来源——正因为记录了来源,`skills update --all` 之后才有可能做点有意义的事。
在安装别人写的技能之前
- ✗技能是写给一个能执行命令的 Agent 的指令。装之前先读一遍 SKILL.md,就像你会先读一遍再决定要不要把某个脚本 pipe 给 bash 一样。
- ✗注册表会显示安全扫描摘要。那是一个信号而不是保证,而且它完全没有评价这些指令对你的环境是不是个好主意。
- ✗技能继承你的工具策略。技能让 Agent 去执行什么,仍然受 tools.allow 和 tools.deny 约束——这一层才是你在装任何东西之前更该先弄对的。
- ✗一个从来不触发的技能,几乎总是 description 的问题,而不是加载的问题。先用 /skill 测一下就能分清这两者。
发布到 ClawdHub
当您的技能完善并经过测试后,打包您的代码库并向 Starmadebydata/clawdhub-registry 提交 Pull Request。社区采用从这里开始!更多详情,请参阅 官方发布指南。