
1. 从一次 Skills 部署失败说起OpenClaw 的 Skills 机制本质上是一套「本地可执行能力注册协议」你把 Python 或 Node.js 脚本按约定放进工作空间目录OpenClaw 在运行时扫描并把它挂载成智能体可调用的工具。听起来简单但真正跑通一条从开发到 MySQL 联调的链路中间会撞上目录识别、依赖缺失、配置字段拼写、Key 管理分散这几类问题。这篇手记聚焦的就是这条链路Skills 用 Python/Node.js 怎么写、config.toml 和 settings.json 怎么配、MySQL 联调怎么验证、部署阶段哪些坑最容易反复踩。适合谁看已经在本地跑起 OpenClaw、想让智能体真正去查数据库或做视频总结的自用党以及手上有一堆 AI 工具、Key 散落在各个配置文件里、想统一收口的人。我会给出可直接复制的配置骨架并演示通过 TaoToken 的统一 Key/API 通道接入 AI 工具让 Skills 里的模型调用不再东一个 Key 西一个 Key。先说结论Skills 跑不起来九成不是代码写错而是「环境没装、目录放错、配置字段对不上」这三件事。下面按顺序拆。2. TaoToken 前置统一 Key 与 API 通道在写 Skills 之前先把模型调用的出口统一掉。否则你会在每个 Skill 里硬编码不同的 base_url 和 api_key后面换模型、换通道时要一个个改非常痛苦。TaoToken 在这里扮演的角色是「统一 Key/API 通道」你申请一个 Key通过它的 API 地址去调用不同模型Skills 代码里只认一个环境变量。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。操作路径建议这样走先去控制台创建 Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建完在 API Keys 页面复制页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。想先确认模型通不通用模型对话页试一句 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。如果你后面要长期跑编码类或 Agent 类 Skill可以看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入细节和字段说明在文档里 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。注意Key 只放在环境变量或本地配置文件里不要提交到 Git 仓库也不要在 Skill 代码里写死明文。拿到 Key 之后先设一个环境变量后面所有 Skill 都复用它# Linux / macOS export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api # Windows PowerShell $env:TAOTOKEN_API_KEYsk-你的key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api这一步做完Skills 里的模型调用就有了统一出口接下来写代码和配置才不会乱。3. 可复制配置config.toml 与 settings.json 骨架OpenClaw 的配置分两层一层是框架级的 config.toml管工作空间、Skills 扫描路径、模型通道另一层是 Skill 级的 settings.json管这个技能自己的参数比如数据库连接、超时、模型名。先给 config.toml 骨架。字段名以你本地版本为准下面这份是我实测能跑通的形态# config.toml [workspace] # Skills 扫描根目录Python 和 Node.js 分开放 skills_dir ./workspace/skills python_dir ./workspace/skills/python node_dir ./workspace/skills/node [model] # 统一走 TaoToken 通道 provider openai-compatible base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model gpt-4o-mini timeout_seconds 60 [skills] # 开启自动扫描改完文件不用重启 auto_reload true scan_interval 5 [logging] level info file ./logs/openclaw.log关键点api_key_env写的是环境变量名不是 Key 本身。这样 config.toml 可以放心进版本库。再给一个 MySQL 查询 Skill 的 settings.json 骨架{ name: mysql_query_helper, version: 1.0.0, runtime: python, entry: main.py, description: 连接 MySQL 执行查询并返回结果, timeout: 30, env: { MYSQL_HOST: 127.0.0.1, MYSQL_PORT: 3306, MYSQL_USER: readonly_user, MYSQL_PASSWORD: your_password, MYSQL_DB: demo_db }, model: { base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model_name: gpt-4o-mini }, permissions: { allow_network: true, allow_file_write: false } }对应的 Python 入口文件用 pymysql 做最小实现# workspace/skills/python/mysql_query_helper/main.py import os import json import pymysql def run(payload: dict) - dict: sql payload.get(sql, ).strip() if not sql.lower().startswith(select): return {ok: False, error: only SELECT allowed} conn pymysql.connect( hostos.environ[MYSQL_HOST], portint(os.environ[MYSQL_PORT]), useros.environ[MYSQL_USER], passwordos.environ[MYSQL_PASSWORD], databaseos.environ[MYSQL_DB], cursorclasspymysql.cursors.DictCursor, connect_timeout10, ) try: with conn.cursor() as cur: cur.execute(sql) rows cur.fetchall() return {ok: True, rows: rows} finally: conn.close() if __name__ __main__: import sys payload json.loads(sys.argv[1]) if len(sys.argv) 1 else {} print(json.dumps(run(payload), ensure_asciiFalse))依赖写在同目录 requirements.txtpymysql1.1.0Node.js 版结构一样只是入口换成 index.js依赖用 package.json 管理settings.json 里runtime: node。4. 验证请求从依赖安装到成功返回配置写完不代表能跑。按下面顺序逐步验证每一步都有明确的成功信号。第一步装依赖。Python 技能进目录执行cd workspace/skills/python/mysql_query_helper pip install -r requirements.txt成功信号终端最后一行出现Successfully installed pymysql-1.1.0。如果报ModuleNotFoundError说明依赖没装到当前解释器检查which python和pip -V是否指向同一个环境。第二步单独跑一次 Skill绕过 OpenClaw 直接验证逻辑python main.py {sql: SELECT 1 AS n}成功信号输出{ok: true, rows: [{n: 1}]}。这一步过了说明数据库连通、SQL 执行正常。第三步启动 OpenClaw看扫描日志openclaw start --config ./config.toml成功信号日志里出现loaded skill: mysql_query_helper (python)。如果没出现多半是目录不在python_dir下或者 settings.json 的name字段和目录名不一致。第四步通过对话触发 Skill。在 OpenClaw 对话里说「帮我查一下 demo_db 里 users 表前 5 条」观察它是否调用mysql_query_helper并返回数据。成功信号返回真实行数据且日志里有一次skill invoke记录。第五步验证模型通道。让 Skill 里带一次模型调用比如把查询结果交给模型总结。如果返回正常说明 TaoToken 的 Key 和 base_url 生效。想单独确认模型通不通用模型对话页发一句即可 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。5. 本篇常见错排查报错一ModuleNotFoundError: No module named pymysql原因依赖没装或装到了别的 Python 环境。排查pip show pymysql看是否安装which python确认解释器路径。修复用python -m pip install -r requirements.txt强制绑定当前解释器。报错二Cannot find module mysql2Node.js原因没进技能目录跑npm install或 node_modules 被 .gitignore 排除后没重建。修复cd workspace/skills/node/xxx npm install确认目录下出现 node_modules。报错三Skill 不加载日志无loaded skill原因目录放错或 settings.json 字段拼写错误。排查对照 config.toml 里的python_dir确认文件实际路径用python -m json.tool settings.json校验 JSON 合法性。修复把技能移到正确目录字段名严格对齐。报错四Access denied for user原因MySQL 账号密码或权限不对。排查用mysql -u readonly_user -p -h 127.0.0.1手动登录一次。修复确认 settings.json 里 env 字段和实际账号一致只读账号不要给写权限。报错五模型调用返回 401原因TAOTOKEN_API_KEY没设或设错。排查echo $TAOTOKEN_API_KEY看是否有值。修复重新 export或检查 config.toml 里api_key_env写的变量名和实际一致。报错六改了代码不生效原因auto_reload没开或扫描间隔太长。修复config.toml 里设auto_reload true或手动重启 OpenClaw。6. 收口把 Key 和 Skill 都管起来跑通之后建议做两件收尾的事。一是把所有 Skill 的模型配置都指向同一个TAOTOKEN_API_KEY环境变量这样以后换模型只改一处二是给每个 Skill 的 settings.json 加permissions白名单尤其是数据库类技能只允许 SELECT避免误操作。如果你后面要长期跑编码类或 Agent 类 SkillCoding Plan 那条线可以看 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入字段和报错对照在文档里查 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。Key 管理和新建在 API Keys 页 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后留一个我踩过的坑Skills 目录名不要用中文或空格OpenClaw 扫描时可能识别不到用下划线命名最稳。