1. 为什么 OpenClaw Skills 开发总卡在 Key 管理这一步
OpenClaw Skills 是模块化的能力包,能让 AI 助理快速获得特定功能,遵循 YAML frontmatter + Markdown 的标准规范,可以被 ClawHub 管理、共享和复现。简单说,你写一个 SKILL.md,别人clawhub install一下就能用上你的能力封装。适合谁?适合那些想让自己的 Agent 具备搜索、代码审查、文档生成等具体能力,又不想每次都从零写 prompt 的开发者。
但真正动手做完整链路的人会发现一个尴尬的现实:技能本身写起来不难,难的是技能里要调用模型。一个 multi-search-engine 技能要调模型做结果摘要,一个 code-review 技能要调模型做静态分析,一个 doc-writer 技能要调模型生成文档。每个技能都塞一个 API Key,配置文件里散落着不同厂商的 key,本地测试一套、发布后用户又得自己配一套。更麻烦的是,ClawHub 发布前检查里明确要求「无敏感信息(API keys、passwords)」,你根本不能把 key 写进 SKILL.md 或 config 里。
我试过最笨的办法:每个技能单独读环境变量,结果用户装三个技能要配三遍。后来统一走 TaoToken 的 OpenAI 兼容接口,一个 Key 覆盖多个模型,技能里只留一个 base_url 和 key 的引用位置,发布时天然干净。这篇就把从零开发到 ClawHub 发布的完整链路拆开,重点解决多工具调用时的 Key 管理痛点,交付 SKILL.md 骨架、config.toml 配置示例和统一 Key 接入步骤,最后给出发布前的本地验证动作。
2. TaoToken 前置准备:一个 Key 打通技能里的模型调用
TaoToken 在这里扮演的角色是「统一入口」。你的技能不需要关心背后是哪个模型厂商,只需要按 OpenAI 兼容格式发请求,Key 和 base_url 从配置里读。这样技能代码保持干净,发布到 ClawHub 时也不会夹带任何敏感信息。
先拿到 Key。访问 https://taotoken.net/api-keys 创建你的 API Key,建议按技能维度命名,比如skill-multi-search、skill-code-review,方便后续排查是哪个技能在消耗额度。创建后复制保存,页面只显示一次。
拿到 Key 之后,你需要确认两件事:base_url 用https://taotoken.net/api,请求路径按 OpenAI 兼容格式拼/v1/chat/completions。模型名可以在模型对话页面先试一下,确认你要用的模型 ID 拼写正确,再写进技能配置。
注意:不要把 Key 硬编码进 SKILL.md、config.toml 或任何会提交到 ClawHub 的文件。正确做法是技能运行时从环境变量或本地未提交的配置文件读取,发布包里只留占位符和说明。
如果你打算长期开发多个技能、频繁调试 Agent 工作流,可以了解一下 Coding Plan,它更适合持续性的编码和 Agent 场景,不用每次单独管理额度。但如果你只是先跑通一个技能,按量用 API 就够了。
3. 可复制配置:SKILL.md 骨架 + config.toml + 统一 Key 接入
3.1 项目结构
先建目录。OpenClaw 的 workspace 技能目录通常在~/.openclaw/workspace/skills/下:
mkdir -p ~/.openclaw/workspace/skills/multi-search-engine cd ~/.openclaw/workspace/skills/multi-search-engine推荐结构如下,必需文件只有 SKILL.md,其余按需添加:
multi-search-engine/ ├── SKILL.md # 主文档(必须,名字必须和文件夹名一致) ├── config.toml # 配置模板(本地用,发布时替换为示例) ├── scripts/ │ └── search.py # 辅助脚本 └── references/ └── engines.md # 详细参考3.2 SKILL.md 骨架
SKILL.md 的 YAML frontmatter 是 ClawHub 校验的重点,name 必须和文件夹名完全一致,version 遵循 semver:
--- name: multi-search-engine description: "跨多个搜索引擎检索并汇总结果,支持国内与国际引擎分组,输入关键词返回结构化摘要" version: 1.0.0 author: Your Name --- # Multi Search Engine 一句话价值主张:传一个关键词,拿到多个引擎的检索结果和模型汇总摘要。 ## 功能特性 - 支持 17 个搜索引擎的 URL 构造 - 国内 / 国际引擎分组,降低选择成本 - 结果经模型汇总,输出结构化摘要 ## 快速开始 ```bash python scripts/search.py --keyword "OpenClaw Skills"调用示例:
result = search({"keyword": "OpenClaw Skills", "engines": ["bing", "duckduckgo"]})配置
技能通过环境变量读取模型接入信息,不把 Key 写进任何提交文件:
| 变量名 | 说明 | 示例 |
|---|---|---|
| TAOTOKEN_API_KEY | 统一 Key | sk-xxxx |
| TAOTOKEN_BASE_URL | 接口地址 | https://taotoken.net/api |
| TAOTOKEN_MODEL | 模型 ID | 在模型对话页确认 |
安装与卸载
clawhub install multi-search-engine clawhub uninstall multi-search-engine故障排查
- 401:检查 TAOTOKEN_API_KEY 是否设置
- 404:检查 base_url 是否漏了 /v1 路径
- 超时:检查网络与模型 ID 是否正确
License
MIT
关键规则记牢:名字和文件夹名一致、禁止用 README.md 当主文档、示例代码必须能直接复制运行、避免写内部实现细节。 ### 3.3 config.toml 配置示例 技能里读配置建议用 TOML,结构清晰。本地开发时放真实值,发布前替换成占位符: ```toml [model] # 统一走 TaoToken,一个 Key 覆盖多个模型 base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" # 从环境变量读,不写明文 model = "your-model-id" # 在模型对话页确认后填入 timeout = 30 [search] engines_domestic = ["baidu", "bing", "sogou"] engines_international = ["duckduckgo", "brave", "wolframalpha"] max_results_per_engine = 5 [summary] enabled = true max_tokens = 800api_key_env这个设计是关键:配置文件里只写「去哪个环境变量拿 Key」,真实 Key 永远不进仓库、不进发布包。用户安装你的技能后,只需要设置一次环境变量,所有走 TaoToken 的技能都能复用。
3.4 统一 Key 接入脚本
在scripts/search.py里按 OpenAI 兼容格式调用:
import os import tomllib import requests def load_config(path="config.toml"): with open(path, "rb") as f: return tomllib.load(f) def call_model(prompt, cfg): api_key = os.environ.get(cfg["model"]["api_key_env"]) if not api_key: raise RuntimeError("未设置 TAOTOKEN_API_KEY 环境变量") url = cfg["model"]["base_url"].rstrip("/") + "/v1/chat/completions" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } payload = { "model": cfg["model"]["model"], "messages": [{"role": "user", "content": prompt}], "max_tokens": cfg["summary"]["max_tokens"], } resp = requests.post(url, headers=headers, json=payload, timeout=cfg["model"]["timeout"]) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"]设置环境变量后即可运行:
export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" python scripts/search.py --keyword "OpenClaw Skills"4. 验证请求:确认技能真的跑通再发布
写完代码别急着 publish,先在本地把请求跑通。最直接的方式是单独测一次模型调用,确认 Key、base_url、模型 ID 三件套没问题:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "your-model-id", "messages": [{"role": "user", "content": "回复 ok"}] }'返回里能看到choices[0].message.content就说明接入正常。如果这一步就报错,先别往下走,按第 5 节的排查表处理。
模型通了之后,本地安装技能并触发:
clawhub install .在 OpenClaw 会话里触发该技能,确认三件事:工具能被正确调用、参数传递符合预期、输出结构和你 SKILL.md 里写的一致。边界测试也别省:空关键词、无效引擎名、超长输入,看错误提示是否友好。发布前检查清单过一遍:SKILL.md 无语法错误、版本号递增、License 明确、无敏感信息、示例代码能跑通。
确认无误后发布:
clawhub login clawhub publish . --tag latest5. 本篇常见错排查
401 Unauthorized:最常见。先确认TAOTOKEN_API_KEY环境变量在当前 shell 里真的存在,echo $TAOTOKEN_API_KEY看一下。如果是在 OpenClaw 会话里触发技能,注意会话进程是否继承了你 export 的环境变量,必要时写进 shell 配置文件。
404 Not Found:base_url 拼错。正确是https://taotoken.net/api,请求时再拼/v1/chat/completions。如果你在 config 里把 base_url 写成了带/v1的,脚本又拼一次,就会变成/v1/v1/...。
模型 ID 报错:模型名拼写不对,或者该模型当前不可用。去模型对话页面实际发一条消息,确认能通再把 ID 抄进配置。
ClawHub 校验失败:九成是 SKILL.md 的 name 和文件夹名不一致,或者你放了 README.md 当主文档。ClawHub 只认 SKILL.md。
发布包里带了 Key:发布前用grep -r "sk-" .扫一遍,确认没有明文 Key。config.toml 里只留api_key_env占位。
超时:timeout 设太短,或者模型响应慢。把 timeout 调到 30 秒以上,长文本汇总场景可以到 60 秒。
6. 发布之后:把统一 Key 接入变成你的开发习惯
技能发布到 ClawHub 只是开始。后续维护时,每次改代码记得递增版本号:bugfix 走 patch,新功能走 minor,破坏性改动走 major。用户clawhub update multi-search-engine就能升级。
真正省心的地方在于,你所有技能都走同一套 TaoToken 接入方式。新技能直接复制 config.toml 的[model]段,改一下 model 字段就行,Key 和 base_url 完全复用。用户装你三个技能,也只需要配一次环境变量。接入文档里有完整的参数说明和更多调用示例,遇到格式问题可以先对照一遍。
如果你后面要做更复杂的 Agent 工作流,多个技能串起来跑,建议把 Coding Plan 也了解一下,长期编码场景下额度管理会更顺。先把第一个技能从零跑到发布,把 SKILL.md 骨架和 config.toml 模板沉淀下来,第二个技能就是复制粘贴改逻辑的事了。