OpenClaw 实战 10|扩展开发:Skill / Tool / Plugin 区分 + 完整安装流程 + 链路证伪调优原创
# 扩展开发:Skill / Tool / Plugin 区分 + 完整安装流程 + 链路证伪调优
这一篇不讲"插件架构设计"那一套抽象话题,只讲给 OpenClaw 加新能力的完整流程 + 多环境扩展隔离 + 真实调优方法论。
本文所有内容都来自
~/.hermes/workspace/blog-material/notes/claude-code/下的 4 条真实扩展会话记录(2026-06-18 ~ 2026-06-25):
<session-file>— 集成 Qwen3-Coder + ComfyUI(含 contextWindow 调优)<session-file>— 多部署插件排查<session-file>— skill-creator SKILL.md 规范<session-file>— 多环境 Skill 安装关键认知:OpenClaw 的扩展不是单一形态,Tool / Skill / Plugin / Command 4 种扩展点严格区分,混用就会翻车。
# §1 给 Nova 装 telegram-business skill 的连环踩坑
我想给
真实场景(来自 <session-file>):
skill 本身很简单(npx clawhub install 一行就下来了),但环境一复杂就翻车——容器/裸机混淆、PATH、Token、Provider 改名、TTS 链路误判,全在这一次里撞齐了。
坑 1:多环境混淆
我家有 3 个 OpenClaw 实例:
上的 Nova :Docker + Supervisor,SSH 端口 2223- 内部品牌宿主机:裸机 + systemd,SSH 端口 22
- 家用 NAS:裸机 + systemd,SSH 端口 22
致命陷阱:systemctl --user status openclaw-gateway,命令在容器里"看似返回了"(其实报 Unit not found),我误以为服务没启动,开始瞎改配置。
解药:任何操作前先做拓扑探测:
# 黄金命令
ssh -p 2223 <USER>@<IP> "which openclaw; supervisorctl status openclaw"
2
supervisorctl status成功 → 容器systemctl --user status成功 → 裸机 systemd- 两个都成功 → 立即停手排查
坑 2:PATH 找不到 openclaw
SSH 进容器后直接 openclaw config set 报 command not found。nvm/pnpm 的 bin 没自动加载。
# 必须显式 export
export PATH=/home/<USERNAME>/.nvm/versions/node/v22.20.0/bin:/home/<USERNAME>/.local/share/pnpm/bin:$PATH
export HOME=/home/<USERNAME>
2
3
坑 3:Gateway Token Mismatch(最隐蔽)
装 Skill 后 openclaw CLI 完全连不上 Gateway,但 Telegram Bot 还能回消息(走降级轮询)。日志报 gateway token mismatch。
根因:Skill 配置文件写了新 Token,但 Supervisor env 里的 OPENCLAW_GATEWAY_TOKEN 没同步。两边 sha256 不一样。
修复:让 config 跟随 env(单一来源):
openclaw config set gateway.auth.token '${OPENCLAW_GATEWAY_TOKEN}'
supervisorctl reread && supervisorctl update && supervisorctl restart openclaw
2
坑 4:Provider 改名导致 API Key 丢失
Skill 配置文件改了一个 Provider 名字(claude-haiku → claude-internal),重启后 Agent 一调模型就报 No API key found。
根因:SQLite auth_profile_store 表里的 Key 还绑在旧 Provider 名上。改 JSON 不动 SQLite = Key 找不到。
修复:手动迁移 SQLite 或重配 Provider。
坑 5:TTS 链路误判
Skill 启用后我让 Agent 发语音,听到声音就去查本地 TTS 服务日志,发现 index-tts2 有大量请求——我以为是 Skill 在用本地 TTS。
实际:Nova 实际用自建 CosyVoice(端口 8082)。index-tts2 的请求是 Kong 转发给其他服务的,与本次 Skill 无关。
根因:日志存在 ≠ 当前调用。必须"触发-观测-计数变化"建立因果链。
5 个坑叠加,从"装个 Skill"演变成"3 小时连环排错"。
# §2 4 种扩展点:Tool / Skill / Plugin / Command
OpenClaw 有 4 种扩展点(基于 4 条素材综合 + 官方 SKILL 体系),严格区分:
| 类型 | 形态 | 适合 | 不适合 | 真实示例 |
|---|---|---|---|---|
| Tool | 单个原子能力函数 | Agent 直接调用的原子操作 | 多步骤业务流程 | git_status, read_file, send_message |
| Skill | 一组 Tool + 配置 + 文档 | 完成具体任务的完整方案 | 一次性原子操作 | skill-creator, freshrss-reader, summarize(均为真实 skill) |
| Plugin | 扩展 Gateway 自身 | 给 Gateway 加新通道/适配器 | 业务 Skill | Telegram 通道、vLLM Provider |
| Command | CLI 子命令 | 管理员操作 | Agent 自动调用 | openclaw config set |
# 2.1 判定口诀
- Agent 要直接调的原子操作 → Tool
- Agent 要完成一个任务 → Skill(由多个 Tool 组成)
- 改 Gateway 自身行为 → Plugin
- 给管理员用的 → Command
# 2.2 真实混淆陷阱
典型错误:把 Skill 当 Tool 写。
# 错:把 Skill 写成单 Tool
def telegram_business_send(message):
"""Skill 'telegram-business' 的发送消息功能"""
...
# 对:拆成 Tool + Skill
# Tool: 原子能力
def telegram_send(chat_id, text):
...
def telegram_business_get_pending():
...
# Skill: 完整方案
class TelegramBusinessSkill:
"""组合 telegram_send + telegram_business_get_pending 实现完整业务"""
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Skill 应该包含 3 类文件(来自 <session-file>):
SKILL.md— frontmatter + 描述(Agent 只读 description 判断要不要加载)scripts/— 实现脚本(可选)references/— 详细文档(Agent 任务匹配后才读)
# §3 Skill 的目录结构与 frontmatter 规范
来自 <session-file>,OpenClaw 自带的 skill-creator Skill 给出了完整规范。
# 3.1 标准目录结构
skill-name/
├── SKILL.md # 必需:frontmatter + 描述 + 触发词
├── license.txt # 必需:许可证
├── scripts/ # 可选:实现脚本
│ └── quick_validate.py
├── references/ # 可选:详细文档
│ └── architecture.md
└── assets/ # 可选:资源文件
2
3
4
5
6
7
8
# 3.2 SKILL.md frontmatter 规范
---
name: <skill-name> # 必需:Skill 唯一标识
description: <一句话描述> # 必需:Agent 用它判断是否加载
homepage: https://... # 可选:项目主页
license: Apache-2.0 # 可选:许可证
allowed-tools: [tool1, tool2] # 可选:允许 Agent 调用的 Tool 白名单
user-invocable: true # 可选:用户能不能 /<name> 显式调用
metadata: # 可选:自定义元数据
audience: all
workflow: yes
---
2
3
4
5
6
7
8
9
10
11
frontmatter 白名单字段(来自 quick_validate.py):
| 字段 | 必需 | 含义 |
|---|---|---|
name | ✅ | Skill 标识 |
description | ✅ | 任务匹配描述 |
homepage | - | 主页 URL |
license | - | 许可证 |
allowed-tools | - | Tool 白名单 |
user-invocable | - | 能否用户显式调 |
metadata | - | 自定义字段 |
非法字段会被 quick_validate.py 拒绝。
# 3.3 按需加载机制
OpenClaw 只加载 Skill 的 description 到上下文,匹配任务后才读 SKILL.md 正文:
[Skill A] description: "查询 git 仓库状态" ← 进入上下文(精简)
[Skill B] description: "生成 ComfyUI 图像" ← 进入上下文(精简)
[Skill A] SKILL.md 正文(3000 字) ← 仅任务匹配后加载
2
3
description 的写法决定 Skill 能不能被触发:
# 差:含糊
description: "Helper Skill"
# 好:明确 + 触发词
description: |
查询 git 仓库状态(未提交改动、领先/落后多少)。
触发词:"git 状态"、"仓库 diff"、"领先多少"
2
3
4
5
6
7
# §4 Skill 安装完整流程(基于 06-25)
把 <session> 的踩坑抽成标准流程。
# 4.1 安装前:5 步检查
# 1. 拓扑判定
ssh -p <PORT> <USER>@<IP> "which openclaw; supervisorctl status openclaw"
# 2. PATH 准备(避免命令找不到)
export PATH=/home/<USERNAME>/.nvm/versions/node/v22.20.0/bin:/home/<USERNAME>/.local/share/pnpm/bin:$PATH
export HOME=/home/<USERNAME>
# 3. 备份配置(防止 Skill 配置文件破坏现有)
cp -a ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak.$(date +%Y%m%d-%H%M%S)
# 4. Token 双源对齐(确保 Gateway 能正常接收 CLI)
HASH_A=$(python3 -c 'import json,hashlib;print(hashlib.sha256(json.load(open("/home/<USERNAME>/.openclaw/openclaw.json"))["gateway"]["auth"]["token"].encode()).hexdigest())')
HASH_B=$(tr '\0' '\n' < /proc/$(pgrep -f openclaw-gateway)/environ | grep OPENCLAW_GATEWAY_TOKEN | sha256sum | awk '{print $1}')
[ "$HASH_A" = "$HASH_B" ] || {
echo "❌ Token 不一致,先对齐"
openclaw config set gateway.auth.token '${OPENCLAW_GATEWAY_TOKEN}'
supervisorctl reread && supervisorctl update && supervisorctl restart openclaw
exit 1
}
# 5. Provider 在线
openclaw infer model providers
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 4.2 安装:3 种方式
方式 1:通过 ClawHub 注册表(推荐)
OpenClaw 的 skill 注册表是 ClawHub(自带 clawhub skill 封装)。先查自带的 57 个,不够再装:
npx clawhub install <skill-name> # 下载到 ~/.openclaw/workspace/skills/<name>
# 校验 frontmatter(用内置 skill-creator 的脚本)
python3 ~/.openclaw/workspace/skills/skill-creator/scripts/quick_validate.py \
~/.openclaw/workspace/skills/<name>/
2
3
4
方式 2:从 git clone
cd ~/.openclaw/workspace/skills/
git clone https://github.com/<user>/telegram-business.git
cd telegram-business
python ~/.nvm/versions/node/v22.20.0/lib/node_modules/openclaw/skills/skill-creator/scripts/quick_validate.py .
2
3
4
方式 3:从源码目录复制(开发态)
cp -r /workspace/openclaw/skills/<new-skill> ~/.openclaw/workspace/skills/
# 4.3 启用:注册到 openclaw.json
{
"skills": {
"entries": {
"telegram-business": {
"enabled": true,
"path": "~/.openclaw/workspace/skills/telegram-business"
}
}
}
}
2
3
4
5
6
7
8
9
10
# 4.4 重启 + 验证
# 重启 Gateway(配置才生效)
supervisorctl reread && supervisorctl update && supervisorctl restart openclaw
# 验证:看应用层 ready 日志
supervisorctl tail -f openclaw | grep -E 'ready|skill.*loaded'
# 验证:Skill 是否出现在列表
openclaw skills list | grep telegram-business
# 端到端:Telegram 发 "/telegram-business help" 看 Agent 是否响应
2
3
4
5
6
7
8
9
10
# §5 多环境部署下的扩展隔离(基于 06-25 / 06-22)
最复杂的扩展场景:同一套 Skill 在多个实例上跑(
# 5.1 多环境差异
| 维度 | CasaOS / NAS (裸机) | |
|---|---|---|
| 进程管理 | Supervisor | user systemd |
| SSH 端口 | 2223 | 22 |
| PATH | nvm 在 /home/<USERNAME>/.nvm/... | 通常在 /usr/local/bin |
| TTS | 自建 CosyVoice (:8082) | 以该机实测为准(早期 Edge TTS 已非默认) |
| Gateway 端口 | 18789 | 18789(默认) |
| 反向代理 | Kong | 无 |
# 5.2 Skill 配置的"实例特异性"
同一个 Skill 在不同实例上的 config 不同:
# <aws-instance> 上的 telegram-business
api_base: "http://localhost:8082/v1/audio/speech" # 自建 CosyVoice
provider_name: "claude-internal"
telegram_bot_token: "${AWS_US_TELEGRAM_TOKEN}"
# NAS 上的 telegram-business
api_base: "https://api.openai.com/v1/audio/speech" # 远程
provider_name: "claude-haiku"
telegram_bot_token: "${NAS_TELEGRAM_TOKEN}"
2
3
4
5
6
7
8
9
必须分别配置,不能假设通用。
# 5.3 操作隔离的 3 条铁律
- 永远先确认目标环境:ssh 端口 + 进程管理方式
- 远程命令先 export PATH:避免
command not found - Token 双源对齐再装 Skill:避免"装完 CLI 全挂"
# §6 上下文压缩调优:Qwen3-A3B 长对话"变蠢"(来自 06-18)
最复杂的扩展场景之一:为新模型调 OpenClaw 上下文参数(来自 <session-file>)。
# 6.1 现象
# 6.2 根因
OpenClaw 默认 reserveTokensFloor=20000,触发压缩阈值约 24 万 token。但 A3B MoE 模型的实际有效上下文窗口远小于 24 万 token(模型宣称的 contextWindow=262144 包含预训练窗口 + 推理不稳定区)。
压缩阈值过高 → 模型在不稳定区运行 → 答错问题。
# 6.3 修复
{
"models": {
"providers": {
"qwen3-coder": {
"contextWindow": 110000, // 从 262144 降到 110000
"reserveTokens": 20000 // 主动压缩阈值
}
}
}
}
2
3
4
5
6
7
8
9
10
效果:约 90K token 时自动触发主动压缩(Preemptive Compaction),模型始终在稳定区运行。
# 6.4 复用规则
**MoE 模型(特别是 A3B 这种激活参数小的)**不要用宣称的 contextWindow,根据实际推理效果下调阈值并启用主动压缩。
# §7 ComfyUI Skill 开发(来自 06-18)
最实际的扩展:给 OpenClaw 加 ComfyUI 文生图/文生视频能力(来自 <session-file>)。
# 7.1 文生图 Skill:comfyui-image-gen
# ~/.openclaw/workspace/skills/comfyui-image-gen/scripts/generate.py
import requests, json, sys
WORKFLOW = {
"1": {"class_type": "KSampler", # ← 必须是 KSampler,不能用 KSamplerAdvanced
"inputs": {"sampler_name": "euler", "cfg": 7.0, "steps": 20}},
# ...
}
def generate(prompt: str, output: str):
"""文生图,prompt → output PNG"""
# 1. 提交工作流到 ComfyUI
r = requests.post("http://localhost:8188/prompt", json={"prompt": WORKFLOW})
# 2. 轮询直到完成
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
关键陷阱:文生图必须用 KSampler,不是 KSamplerAdvanced(后者多 1 个 add_noise 参数,默认值错位会导致全黑图)。
# 7.2 文生视频 Skill:comfyui-text-to-video
Wan2.2 + LightX2V LoRA,关键参数:
| 参数 | 值 | 原因 |
|---|---|---|
cfg | 1.0 | 适配蒸馏 LoRA(默认 7.0 会过饱和) |
frames | 4n+1 | Wan2.2 要求的帧数公式 |
| KSampler | 双专家分段采样 | 前段 + 后段用不同 KSampler |
| ModelSampling | ModelSamplingSD3 (shift=8.0) | 文生视频专用,不是文生图的 AuraFlow (shift=3.0) |
# 7.3 Skill 验证清单
# 1. quick_validate
python ~/.nvm/versions/node/v22.20.0/lib/node_modules/openclaw/skills/skill-creator/scripts/quick_validate.py ~/.openclaw/workspace/skills/comfyui-image-gen/
# 2. 端到端:Agent 调一次
openclaw skill test comfyui-image-gen --prompt "a cat"
# 期望:返回 PNG 路径
# 3. 看 Skill 日志
supervisorctl tail -f openclaw | grep comfyui
2
3
4
5
6
7
8
9
# §8 调优方法论:链路证伪(来自 06-22 / 06-25)
最隐蔽的调优陷阱:日志存在 ≠ 当前调用。验证功能必须"触发-观测-计数变化"建立因果链(来自 <session-file> + <session>)。
# 8.1 典型误判场景
| 误判 | 实际 |
|---|---|
| 本地 TTS 日志活跃 → Agent 在用 | Kong 转发给其他服务 |
| Gateway 报 ready → 配置生效 | 应用层 ready ≠ CLI 可连(Token Mismatch) |
| Provider 显示在线 → 模型可调 | Provider 改了名字,SQLite Key 没迁 |
| Telegram 还回消息 → Agent 活着 | 降级轮询,CLI 已死 |
# 8.2 4 步证伪法
[触发] 用户行为 → 让 Agent 真正调用一次目标功能
[观测] 看目标服务的实时指标(计数、端口流量、行为响应)
[计数] 触发前后指标变化
[归因] 计数变化 → 当前调用经过;计数无变化 → 旁路流量
2
3
4
# 8.3 实战:TTS 链路证伪
# 1. 触发:让 Agent 发语音
openclaw infer model providers --test-tts "hello"
# 2. 观测:本地 TTS 服务日志计数
grep -c "POST /v1/audio/speech" /workspace/index-tts2/service.log
# 假设:1234
# 3. 再触发一次
openclaw infer model providers --test-tts "world"
# 4. 计数变化?
grep -c "POST /v1/audio/speech" /workspace/index-tts2/service.log
# 1234 ← 没变,说明 index-tts2 没被调用
# 1235 ← 变了,说明 Agent 确实用 index-tts2
2
3
4
5
6
7
8
9
10
11
12
13
14
# 8.4 Thinking 模式验证(低侵入 vs 高侵入)
来自 <session-file>:
| 方法 | 步骤 | 侵入性 |
|---|---|---|
| 低侵入(行为验证) | 发 23*47=? 看响应耗时(2-8s 开启 / <1s 关闭)+ 内容结构 | 低 |
| 高侵入(抓包验证) | tcpdump vLLM port + grep enable_thinking | 高(影响生产) |
# §9 下一篇
下一篇:11|最佳实践——把全系列的真实翻车压成 10 条可落地 SOP,与推送二次确认硬规则。
# §10 Agent 可直接解析的元数据块
{
"_meta": {
"doc_version": "2026-06-27",
"article_id": "openclaw-extension",
"profile_context": "blog",
"estimated_read_time": "15min",
"real_material_count": 4,
"material_sources": [
"notes/claude-code/<session-file>.md",
"notes/claude-code/<session-file>.md",
"notes/claude-code/<session-file>.md",
"notes/claude-code/<session-file>.md"
]
},
"extension_types": {
"tool": "单原子能力函数,Agent 直接调用",
"skill": "Tool + 配置 + 文档的完整方案",
"plugin": "扩展 Gateway 自身(通道/适配器)",
"command": "管理员 CLI 子命令"
},
"skill_structure": {
"required": ["SKILL.md (frontmatter + description)", "license.txt"],
"optional": ["scripts/", "references/", "assets/"],
"frontmatter_whitelist": ["name", "description", "homepage", "license", "allowed-tools", "user-invocable", "metadata"],
"lazy_load": "仅 description 进上下文,匹配任务才读正文"
},
"installation_flow": [
"拓扑判定:which openclaw + supervisor/systemctl status",
"export PATH(nvm/pnpm)+ export HOME",
"备份 ~/.openclaw/openclaw.json",
"Token 双源对齐(sha256 比对)",
"Provider 在线验证(openclaw infer model providers)",
"安装 Skill(openclaw skill install 或手动 clone)",
"quick_validate.py 验证",
"openclaw.json 注册 entries.enabled=true",
"supervisorctl restart openclaw",
"应用层 ready 日志验证",
"openclaw skills list 验证",
"端到端测试(Telegram / CLI ping)"
],
"comfyui_skill_critical_params": {
"text_to_image_ksampler": "KSampler(非 KSamplerAdvanced)",
"text_to_video_cfg": 1.0,
"text_to_video_frames": "4n+1",
"model_sampling": "ModelSamplingSD3 (shift=8.0)"
},
"context_compression": {
"moe_a3b_warning": "激活参数小的 MoE 不要用宣称 contextWindow",
"recommended": {
"contextWindow": 110000,
"reserveTokens": 20000
}
},
"safety_rules": [
"永远先做拓扑判定(容器 vs 裸机 vs 源码)",
"远程跑 openclaw 前显式 export PATH 和 HOME",
"Token 双源永远让 config 跟随 env",
"改 Skill 配置后必重启 Gateway + 看应用层 ready 日志",
"MoE 模型下调 contextWindow 并启用主动压缩",
"验证链路用'触发-观测-计数变化'四步法,禁日志存在即归因",
"Skill 必须走 quick_validate.py 验证才能启用"
],
"verification": {
"topology": "ssh -p <PORT> <USER>@<IP> 'which openclaw; supervisorctl status openclaw'",
"skill_list": "openclaw skills list",
"skill_validate": "python skills/skill-creator/scripts/quick_validate.py skills/<name>",
"token_consistency": "sha256 对比 config + env",
"end_to_end": "Telegram 发指令看 Agent 响应"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
AI Agent 使用指南:
- 当用户说"装个 Skill" → 走 §4.1 5 步检查 + §4.2 3 种安装方式
- 当用户说"Skill 不生效" → 走 §4.4 重启 + 应用层 ready 日志验证
- 当用户说"两个 OpenClaw 混了" → 走 §5.3 操作隔离 3 条铁律
- 当用户说"长对话变蠢" → 走 §6 上下文压缩调优,下调 contextWindow
- 当用户说"想加 ComfyUI" → 走 §7,cfg=1.0 + KSampler(非 Advanced)+ ModelSamplingSD3
- 当用户说"日志看到调用但功能没生效" → 走 §8 链路证伪 4 步法