1. 为什么我要手写一个 openclaw Skill:从“能聊”到“能干活”的那一步
openclaw 里的 Skill,说白了就是给 Agent 装的一个“能力插件”。大模型本身只会生成文本,你问它今天天气它只能编,但如果你给它一个 Skill,里面写清楚“去哪个接口拿数据、用什么参数、返回怎么解析”,它就能真的把结果拿回来。这就是 openclaw Skill 最核心的价值:把自然语言指令翻译成可执行的动作序列。
我一开始也以为写 Skill 是很高级的事,得懂框架源码、得会写插件协议。实际拆开看,一个 Skill 就是一个文件夹,核心只有一个SKILL.md。这个 Markdown 文件里写清楚两件事:什么情况下用这个 Skill,以及具体每一步怎么做。openclaw 读到它,就照着执行。你可以把它理解成一份写给 AI 看的“操作手册”,格式是结构化的,但内容全是自然语言加命令。
那为什么这篇要扯到 TaoToken 配置?因为绝大多数有价值的 Skill,最终都要调用外部能力——要么是模型推理,要么是某个 API。Agent 自己不会凭空产生鉴权信息,它需要你在 Skill 里或者 openclaw 的配置里,把 Base URL、API Key、Model ID 这三样东西填对。我踩过的坑就是:Skill 逻辑写得没问题,但请求发出去一直 401,排查半天发现是端点配错了。所以这篇的目标很明确:带你从零手写一个 openclaw Skill,以SKILL.md为入口,把 Agent 调用外部能力时的鉴权与端点配置一次性跑通,最后用一个本地 Agent 触发 Skill 的动作来验证。
适合谁看?如果你已经在用 openclaw,想让 Agent 帮你做点实际的事,比如读一篇文章、查一个数据、跑一段分析,而不是只在那聊天,那这篇就是写给你的。不需要你懂 openclaw 源码,但需要你会基本的终端操作,知道什么是环境变量,能看懂 JSON 和 YAML 的结构。下面所有步骤都可以直接复制,我尽量把每个参数为什么这么填也讲清楚。
2. 前置准备:TaoToken 统一 Key 与 API 通道怎么配进 openclaw
在写 Skill 之前,得先把“外部能力”的入口准备好。openclaw 的 Agent 要调用模型或者外部 API,需要一个统一的通道。我用的是 TaoToken 的 API 通道,它的好处是一个 Key 可以走多个模型,Base URL 统一,不用每个 Skill 都去改端点。
先拿 Key。打开 TaoToken 官网https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,注册后在控制台里找到 API Keys 页面,新建一个 Key。这个 Key 就是后面所有请求的凭证,格式通常是一串以sk-开头的字符串。拿到之后不要直接写死在SKILL.md里,而是放到环境变量或者 openclaw 的配置文件里,这样 Skill 分享出去也不会泄露。
TaoToken 的 API 端点统一是https://taotoken.net/api,注意这个地址后面不加任何 UTM 参数,就是纯粹的 API 入口。在 openclaw 里配置的时候,Base URL 填这个,然后模型名填你实际要用的 Model ID,比如claude-sonnet-4-20250514或者gpt-4o这类。Key 就填你刚才生成的那串。
具体配置位置在 openclaw 的openclaw.json里。如果你还没有这个文件,在~/.openclaw/目录下新建一个。结构大概是这样:
{ "providers": { "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key", "default_model": "claude-sonnet-4-20250514" } }, "skills": { "enabled": true, "path": "~/.openclaw/skills" } }这里providers下面可以配多个通道,但我们现在只用 TaoToken 一个。base_url就是https://taotoken.net/api,api_key填你的 Key,default_model填你常用的模型 ID。skills部分告诉 openclaw 去哪里加载 Skill,默认就是~/.openclaw/skills。
如果你不想把 Key 写在 JSON 里,也可以用环境变量。在~/.zshrc或~/.bashrc里加一行export TAOTOKEN_API_KEY="sk-你的Key",然后在openclaw.json里把api_key的值写成"${TAOTOKEN_API_KEY}"。openclaw 启动时会自动读取环境变量替换。这样更安全,尤其是你打算把配置同步到多台机器的时候。
配好之后,先别急着写 Skill,用一条 curl 命令验证一下通道是否通:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复一个字:通"}] }'如果返回的 JSON 里有choices字段,并且内容里有一个“通”字,说明 Key 和端点都没问题。如果返回 401,检查 Key 有没有复制错;如果返回 404,检查 Base URL 是不是写成了https://taotoken.net/api而不是别的路径。这一步过了,后面 Skill 里的模型调用才有意义。
3. 可复制配置:手写 SKILL.md 与 openclaw.json 的完整片段
现在进入正题,手写一个 Skill。我以“读取网页正文并总结”为例,这个 Skill 会调用 openclaw 内置的浏览器工具去抓页面,然后把正文交给模型总结。整个 Skill 只有一个SKILL.md文件,放在~/.openclaw/skills/web-summarizer/目录下。
先建目录和文件:
mkdir -p ~/.openclaw/skills/web-summarizer cd ~/.openclaw/skills/web-summarizer touch SKILL.md然后编辑SKILL.md,内容如下。注意前置元数据部分用---包起来,这是 openclaw 识别 Skill 的入口。
--- name: web-summarizer description: 读取指定网页的正文内容,调用模型生成摘要,支持中英文页面 version: 1.0.0 author: your-name tags: [web, summary, browser] triggers: - "总结这个网页" - "帮我读一下这篇文章" - "提取网页正文" tools: - bash - read - write --- ## 适用场景 当用户提供一个网页链接,并要求总结、提取关键信息或翻译时,使用此 Skill。 ## 前置条件 需要 openclaw 的浏览器工具可用。如果浏览器未连接,先执行 `openclaw browser list` 检查。 ## 执行步骤 1. **检查浏览器连接** - 运行 `openclaw browser list` - 如果返回为空,提示用户启动带调试端口的浏览器,并终止 2. **打开目标网页** - 使用 `openclaw browser navigate --url {用户提供的链接}` - 等待 3 秒让页面渲染完成 3. **获取页面内容** - 执行 `openclaw browser snapshot` - 返回的是页面 DOM 结构 4. **提取正文** - 从 snapshot 中提取 `article` 或 `main` 标签内的文本 - 如果找不到,取 `body` 的前 3000 字符 - 清洗掉 script、style 标签内容 5. **调用模型总结** - 将正文作为输入,调用 TaoToken 通道的模型 - 模型 ID 使用 `claude-sonnet-4-20250514` - 提示词:`请用中文总结以下内容,不超过 200 字:{正文}` 6. **返回结果** - 格式: 标题:{页面标题} 摘要:{模型返回的摘要} 原文链接:{用户提供的链接} ## 错误处理 - 浏览器未连接 → 给出启动命令并终止 - 页面加载超时 → 提示网络问题,建议重试 - 正文提取为空 → 返回 snapshot 前 500 字符供用户判断 - 模型调用返回 401 → 检查 TaoToken Key 是否有效这个文件里,前置元数据的name是 Skill 唯一标识,用小写加连字符;description会进入 Skill 索引,方便 Agent 判断什么时候加载;triggers是触发词,用户说的话里包含这些词,Agent 就会考虑调用这个 Skill;tools声明这个 Skill 需要哪些工具权限,这里用了 bash、read、write,因为要执行命令和读写临时文件。
SKILL.md写完后,openclaw 会自动监听文件变化,不需要重启。但如果你改了openclaw.json里的 provider 配置,最好重启一下 openclaw 进程,确保配置生效。
再贴一下openclaw.json的完整片段,把 TaoToken 通道和 Skill 路径都配好:
{ "providers": { "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "${TAOTOKEN_API_KEY}", "default_model": "claude-sonnet-4-20250514", "timeout": 60 } }, "skills": { "enabled": true, "path": "~/.openclaw/skills", "auto_reload": true }, "browser": { "debug_port": 9222, "default_timeout": 10000 } }这里auto_reload设为 true,这样你改完SKILL.md保存后,openclaw 会自动重新加载,不用手动重启。browser.debug_port是浏览器调试端口,后面启动 Chrome 的时候要用同一个端口。
如果你用的是 Claude Code 或者 Cline 这类工具来辅助写 Skill,它们的配置里也有类似的 Base URL 和 Key 填写位置。比如 Claude Code 的settings.json里,env部分可以加ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,但注意 TaoToken 的通道是兼容 OpenAI 格式的,所以如果你用 Claude Code 的原生 Anthropic 协议,需要确认端点是否支持。更稳妥的方式是直接用 openclaw 自己的 provider 配置,让 openclaw 去管理模型调用,Skill 里只写业务逻辑。
4. 验证请求:本地 Agent 触发 Skill 并看到成功结果
配置写好了,现在来验证。先确保浏览器已经启动并打开了调试端口。Mac 下命令是:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222Windows 下是:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222启动后,在终端里跑openclaw browser list,应该能看到一个可连接的浏览器实例。如果返回空,说明端口没开对,或者 Chrome 已经在运行但没有带调试参数,需要先完全退出 Chrome 再重新启动。
然后启动 openclaw 的交互界面。如果你用的是 Web 控制台,直接在输入框里打:
帮我总结这个网页:https://example.com/article观察 Agent 的反应。正常情况下,它会先识别到触发词“总结这个网页”,然后加载web-summarizer这个 Skill,接着按步骤执行:检查浏览器连接、打开链接、抓取 snapshot、提取正文、调用模型总结、返回结果。
如果一切顺利,你会在控制台看到类似这样的输出:
标题:示例文章标题 摘要:这是一篇关于某某主题的文章,主要讲了三点内容…… 原文链接:https://example.com/article这就说明 Skill 跑通了。整个过程不需要你手动干预,Agent 自己完成了从触发到执行的链路。
如果你想更直观地看每一步,可以打开另一个终端,实时看日志:
tail -f ~/.openclaw/logs/skill.log日志里会打印 Skill 加载、工具调用、模型请求的详细信息。比如你会看到Loading skill: web-summarizer、Executing step 1: check browser、Calling model via taotoken这样的行。如果某一步卡住了,日志里会有对应的错误信息。
再验证一个边界情况:故意给一个不存在的链接,看 Skill 的错误处理是否生效。输入:
帮我总结这个网页:https://example.com/not-existAgent 应该会走到“页面加载超时”或“正文提取为空”的分支,返回提示信息而不是直接崩溃。这说明你的错误处理逻辑写对了。
最后,验证模型调用是否真的走了 TaoToken 通道。在日志里搜索taotoken,应该能看到请求的 Base URL 是https://taotoken.net/api,模型 ID 是claude-sonnet-4-20250514。如果看到的是别的端点,说明openclaw.json里的 provider 配置没生效,需要检查 JSON 格式是否正确,或者环境变量有没有被正确读取。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
写 Skill 和配通道的过程中,有几个报错几乎每个人都会遇到。我把自己踩过的和社群里高频出现的整理出来,对照着排查。
401 Unauthorized
这是最常见的。日志里会显示401或者invalid api key。原因通常是三个:Key 复制的时候多了空格或者少了字符;环境变量没生效,openclaw.json里读到的还是空字符串;Key 被撤销或者过期了。排查方法:先在终端里echo $TAOTOKEN_API_KEY,看有没有值。如果没有,检查~/.zshrc或~/.bashrc里有没有 export,改完要source一下。如果有值,用前面那条 curl 命令直接测,确认 Key 本身有效。如果 curl 也 401,那就是 Key 的问题,去 TaoToken 控制台重新生成一个。
local proxy failed
这个报错通常出现在 openclaw 尝试连接浏览器或者外部端点的时候。日志里会写local proxy failed或者connection refused。如果是浏览器相关,检查 Chrome 有没有带--remote-debugging-port=9222启动,端口是不是被占用。如果是模型调用相关,检查base_url是不是写成了https://taotoken.net/api,有没有多写/v1或者少写。TaoToken 的端点就是https://taotoken.net/api,后面接/v1/chat/completions是完整的请求路径,但 Base URL 只到/api。
reading choices 报错
这个一般出现在模型返回的 JSON 解析阶段。日志里会显示cannot read property 'choices' of undefined或者reading 'choices'。原因是模型返回的结构和预期不一致,可能是请求体格式不对,或者模型 ID 写错了导致返回了错误信息。排查方法:在日志里找到完整的响应体,看error字段写了什么。常见的是model not found,那就是 Model ID 填错了,去 TaoToken 的模型列表里核对一下。另一个可能是messages格式不对,确保是[{"role": "user", "content": "..."}]这种结构。
OAuth 相关报错
如果你在 Skill 里调用了需要 OAuth 的外部服务,比如某些第三方 API,可能会遇到OAuth token expired或者invalid grant。这不是 TaoToken 的问题,而是那个外部服务的鉴权过期了。解决方法是在 Skill 里加一步刷新 token 的逻辑,或者提示用户重新授权。如果报错信息里出现了OAuth但你没有主动用 OAuth,那可能是某个工具的默认鉴权方式被触发了,检查tools声明里有没有多余的权限。
Skill 不触发
有时候你写了triggers,但 Agent 就是不调用这个 Skill。原因可能是description写得太模糊,Agent 在索引里匹配不到。把description写得更具体一点,比如“读取网页正文并总结”就比“处理网页”好。另外,triggers里的词要和用户实际说的话接近,不要写太偏的术语。如果还是不行,在 openclaw 的调试模式里看 Skill 索引的加载情况,确认SKILL.md被正确解析了。
CC Switch / Cline MCP / Codex auth.json 的三件套
如果你在用 CC Switch 或者 Cline 的 MCP 功能来管理 openclaw 的模型通道,记住任何一处配置都要写全三件套:Base URL、Key、Model ID。Base URL 是https://taotoken.net/api,Key 是你的 TaoToken Key,Model ID 是具体模型名。少一个都会导致请求失败。Codex 的auth.json里也是类似,base_url和api_key必须成对出现,model字段填 Model ID。不要只填 Key 不填 Base URL,那样会走默认端点,大概率不通。
6. 跑通之后:把 Skill 变成可复用的资产
Skill 跑通之后,你可以把它复制到其他机器上,只要目标机器有 openclaw 和同样的 TaoToken 配置,就能直接加载。如果你想让 Skill 支持用户自定义参数,可以在SKILL.md的前置元数据里加config声明,然后在openclaw.json里覆盖默认值。比如加一个summary_length参数,默认 200 字,用户可以在配置里改成 500。
更进一步的玩法是 Skill 组合。比如你写一个“抓取网页”的 Skill,再写一个“总结文本”的 Skill,然后在第一个 Skill 的最后一步调用第二个 Skill。这样就把两个独立的能力串成了工作流。openclaw 支持在SKILL.md里用自然语言描述“调用另一个 Skill”,Agent 会自己解析并执行。
如果你想把 Skill 分享出去,可以把它打包成一个文件夹,里面包含SKILL.md和可选的scripts/、references/。发布到 ClawHub 或者自己的仓库都行。但注意,分享之前一定要检查SKILL.md里有没有硬编码的 Key 或者敏感信息。用环境变量引用的方式最安全,别人拿到你的 Skill 后只需要配自己的 Key 就能跑。
最后说一个实际经验:Skill 的价值不在于写得多复杂,而在于它能不能稳定地解决一个具体问题。我一开始写了一个“万能助手”Skill,什么都能干,结果 Agent 经常不知道该用哪一步。后来拆成三个小 Skill,每个只做一件事,触发准确率和执行成功率都上去了。所以如果你刚开始写,建议从一个最小的、单一功能的 Skill 入手,跑通之后再逐步扩展。
现在你可以打开终端,建一个自己的 Skill 目录,把上面的SKILL.md模板复制进去,改改name和description,配好 TaoToken 的 Base URL 和 Key,然后让 Agent 触发一次。跑通第一个之后,后面就是复制粘贴改改逻辑的事了。