
1. 从「对话」到「能力扩展」OpenClaw Skills 到底解决什么问题OpenClaw 默认只能对话这句话听起来像吐槽其实是它架构设计的起点。一个只会聊天的 Agent能力边界完全由模型权重决定而 Skills 要做的是把「领域说明书」以目录加 SKILL.md 的形式挂进工作区让模型在需要时再用 read 工具拉取全文从而在不改内核的前提下扩展行为边界。这就是 OpenClaw Skills 的核心定位也是「目录即技能」这个说法的来源。我第一次接触这套机制时最直观的感受是它不像传统的函数注册表更像给模型发了一本可以随时翻阅的操作手册。每个技能是一个文件夹里面放一份带 YAML frontmatter 的 SKILL.md运行时从多个根目录发现、过滤把「目录级摘要」写进系统侧提示需要细节时由模型用 read 打开完整文件。这种设计让能力扩展变得可维护、可版本化、可审计。适合谁读这篇如果你正在用 OpenClaw 做自动化工作流或者想给自己的 Agent 加一套「内部 API 调用规范」「SEO 审查清单」这类知识型能力又或者你只是想搞清楚 ClawHub 上装下来的技能包到底落在磁盘哪个位置、模型什么时候才会看见它那这篇就是为你写的。我会从源码视角拆解加载与注册机制交付可复制的技能目录结构、SKILL.md 字段配置以及本地验证技能被正确加载的检查动作。理解要点Skills 解决的是「如何把人类可维护的操作知识安全地交给模型按需加载」它不是又一个「函数注册表」而是以文档为边界的扩展单元。这个定位决定了后面所有的目录约定、加载顺序和提示注入方式。2. OpenClaw 里的 Skills 是什么目录即技能与三层能力分层OpenClaw 通过一个与 Agent Skills 兼容的技能目录来教模型如何使用工具。每个技能是一个文件夹内含带 YAML frontmatter 的 SKILL.md 与说明正文运行时再从多个根目录发现、过滤把「目录级摘要」写进系统侧提示需要细节时由模型用 read 打开完整文件。这套机制和「手机上的 App」类比依然贴切每个技能是自包含的扩展描述能力边界与使用方式可独立安装、更新、移除ClawHub 提供社区分发类似 npm 之于 JavaScript 包。在讲目录之前先把三种能力类型分清楚否则很容易把 Skills 和 Plugins 混为一谈。类型含义典型来源Built-in Tools核心能力读文件、Shell、web_fetch 等随 OpenClaw 安装提供Skills以 SKILL.md 为主的扩展工作区自建、ClawHub 安装、捆绑技能等Plugins基于 MCP 的集成任意兼容 MCP 的服务端对多数用户而言Skills 是把「操作知识」产品化的主路径Plugins 更适合把外部系统以工具形态接进来。官方文档在 SkillsOpenClaw中把「位置从哪加载」与「可见性是否进 allowlist」分成两维控制——后文在「多 Agent」一节会点到 agents.defaults.skills。为什么「只给目录」是对的Agent Skills 文档把渐进式披露概括成三层目录层会话开始时只看到技能名与简短描述控制 token指令层任务匹配时再用 read 打开完整 SKILL.md资源层脚本、参考文档、附件按需在后续步骤加载。OpenClaw 的实现与此一致默认注入的是 XML 形态的available_skills列表并明确提示模型用 read 加载技能文件。我试过把 20 个技能的正文都手工贴进 system prompt结果就是退化成「巨型静态提示词工程」token 爆炸不说模型还容易在无关技能里迷路。Skills 的性能与成本之间的关系本质是「摘要进提示、正文走工具」一旦你破坏了这条边界扩展平面的意义就没了。3. 可复制配置技能目录结构、SKILL.md 字段与 openclaw.json 片段这一节是全文最该动手的部分。先给一个最小可用的技能目录结构你可以直接复制到工作区workspace/ ├── skills/ │ ├── seo-checklist/ │ │ ├── SKILL.md │ │ └── references/ │ │ └── seo-guidelines.md │ └── internal-api/ │ ├── SKILL.md │ └── scripts/ │ └── query_api.py └── openclaw.jsonSKILL.md 的硬性要求是文件头必须是 YAML frontmatter且 name 与 description 非空否则该目录不算有效技能。下面是一份可直接复制的 SKILL.md 示例字段与官方约定一致--- name: seo-checklist description: SEO 优化检查清单适用于博客、网页等内容。涵盖标题、元描述、标题层级、关键词布局、可读性等。当用户需要检查或优化内容的 SEO 时使用。 --- # SEO 检查清单 当用户请求检查或优化内容的 SEO 时请先使用 read 工具读取 references/seo-guidelines.md 中的详细指南并按以下 checklist 逐项审核 ## 1. 标题Title - 长度 50-60 字符 - 主关键词靠近开头 - 避免堆砌关键词 ## 2. 元描述Meta Description - 长度 150-160 字符 - 包含行动号召CTA - 自然嵌入主关键词 ## 3. 标题层级H2/H3 - 清晰的层级结构 - 2-3 个标题中包含目标关键词 - 避免跳级如 H2 直接接 H4注意 frontmatter 里 description 的写法它要能回答「什么时候该用这个技能」而不是「这个技能是什么」。模型在 L1 目录层只看到 name 和 description靠它判断要不要进入这个技能。写得太泛模型会误触发写得太窄模型永远想不起来用。如果技能需要 API Key、开关、渠道白名单等配置产品侧往往还会在 openclaw.json默认路径多为~/.openclaw/openclaw.json可用$OPENCLAW_CONFIG_PATH覆盖里登记一项便于启用/禁用与注入环境变量。示例结构如下字段以你本机生成结果为准{ skills: { niceperson/brave-web-search: { enabled: true, config: { apiKey: ${BRAVE_API_KEY} } } } }理解要点SKILL.md 教模型「怎么用」openclaw.json 里那一段教运行时「给不给你用、密钥从哪来」——两条线经常同时出现但职责不同。把这两件事分开排障时就能快速定位是「模型没看见技能」还是「技能看见了但没权限」。4. 验证请求与成功结果本地检查技能是否被正确加载配置写完最怕的是「以为装上了其实模型根本没看见」。这一节给你一套可跟做的验证动作从磁盘到提示逐层确认。第一步确认目录与文件命名。技能根目录下每个子目录必须含 SKILL.md文件名大小写敏感。ClawHub 安装器在解压后会依次探测SKILL.md/skill.md/skills.md/SKILL.MD若都不存在则抛错downloaded archive is missing SKILL.md——规范文件名仍是 SKILL.md其余仅为兼容。源码里这段逻辑很直白// openclaw/src/agents/skills-clawhub.ts — ensureSkillRoot async function ensureSkillRoot(rootDir: string): Promisevoid { for (const candidate of [SKILL.md, skill.md, skills.md, SKILL.MD]) { if (await fileExists(path.join(rootDir, candidate))) { return; } } throw new Error(downloaded archive is missing SKILL.md); }第二步确认加载顺序。技能从以下目录发现优先级从高到低workspace/skills → workspace/.agents/skills → ~/.agents/skills → ~/.openclaw/skills托管/共享 → 捆绑技能 → skills.load.extraDirs最低多 Agent 时每个 Agent 有自己的 workspace因此workspace/skills天然是按 Agent 隔离的共享机器级技能则落在~/.openclaw/skills或通过 extraDirs 挂载公共包。第三步确认 frontmatter 被正确解析。本地加载器在读取 SKILL.md 时会校验真实路径落在技能根内随后解析 frontmatter并要求 name 与 description 非空否则该目录不算有效技能// openclaw/src/agents/skills/local-loader.ts — loadSingleSkillDirectory节选 const skillFilePath path.join(params.skillDir, SKILL.md); const raw readSkillFileSync({ rootRealPath: params.rootRealPath, filePath: skillFilePath, maxBytes: params.maxBytes, }); if (!raw) { return null; } let frontmatter: Recordstring, string; try { frontmatter parseFrontmatter(raw); } catch { return null; } const fallbackName path.basename(params.skillDir).trim(); const name frontmatter.name?.trim() || fallbackName; const description frontmatter.description?.trim(); if (!name || !description) { return null; }第四步确认提示注入。拼进模型上下文的 XML 由 formatSkillsForPrompt 生成它再次强调用 read 工具加载、相对路径相对技能目录解析// openclaw/src/agents/skills/skill-contract.ts — formatSkillsForPrompt节选 const lines [ \n\nThe following skills provide specialized instructions for specific tasks., Use the read tool to load a skills file when the task matches its description., When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands., , available_skills, ]; for (const skill of skills) { lines.push( skill); lines.push( name${escapeXml(skill.name)}/name); lines.push( description${escapeXml(skill.description)}/description); lines.push( location${escapeXml(skill.filePath)}/location); lines.push( /skill); } lines.push(/available_skills);成功结果长什么样在会话里问一个命中 description 的任务比如「帮我检查这篇博客的 SEO」模型应当先输出一次 read 调用去打开skills/seo-checklist/SKILL.md再按清单逐项给出结论。如果你在日志里看到available_skills里出现了你的技能名且模型确实发起了 read就说明加载链路是通的。5. 本篇常见错排查401、local proxy failed、reading choices 与 OAuth排障这一节按真实报错来对照方便你快速定位。401 Unauthorized多数出现在技能内部脚本调用外部 API 时。先确认 openclaw.json 里该技能的 config.apiKey 是否指向了正确的环境变量再确认环境变量本身在启动进程里可见。注意${BRAVE_API_KEY}这种写法是运行时展开不是字面量如果你把密钥直接写死在 SKILL.md 正文里模型读全文时会把它带进上下文既不安全也不该做。local proxy failed这类报错通常和网络出口配置有关先检查你的运行环境是否允许访问目标服务以及技能脚本里的 Base URL 是否写错。不要试图用任何非正规网络手段绕过正确做法是确认服务端可达、证书有效、端口未被占用。reading choices / 读取 choices 字段失败常见于技能脚本解析上游返回时字段名对不上。比如上游返回{ data: { items: [...] } }脚本却按choices取值。打开脚本对照真实响应体把取值路径改对即可。这类错误和 Skills 加载机制无关属于脚本自身逻辑问题。OAuth 相关报错如果技能依赖 OAuth 授权先确认授权回调地址与客户端配置一致token 是否过期。OAuth 流程失败时模型侧通常只会看到脚本返回的错误字符串所以建议在脚本里把关键错误码原样抛出方便你在日志里定位。技能装了但模型看不见回到第 4 节的四步验证。最常见的原因是 frontmatter 缺 description或者技能目录放错了根比如放进了~/.agents/skills但当前 Agent 的 workspace 优先级更高同名技能被覆盖。另外若技能设置了disable-model-invocation: true它不会出现在 L1 的available_skills中只能通过用户显式命令触发。热更新没生效技能文件改动后watcher 会 bump 快照版本下一轮用户消息到达时 shouldRefreshSnapshotForVersion 判定为真会话文件里的 skillsSnapshot.prompt 会被换成带新技能条目的 XML。如果你改完文件后当前会话没反应先确认 watcher 是否正常挂载再发一条新消息触发刷新。6. 语义一致 CTA把技能接进你的 OpenClaw 工作流技能目录建好、SKILL.md 写完、本地验证通过之后下一步就是把它真正用起来。如果你还在选模型或调 API可以先到模型对话页面体验一下不同模型对技能描述的理解差异如果你准备长期跑编码或 Agent 类任务Coding Plan 会更适合持续使用。模型对话https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewriteCoding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewrite控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewriteAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewriteClaude Code Anthropic 接入https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentskills_articleutm_campaignrewriteAPI 地址统一用 https://taotoken.net/api不加 UTM。把技能目录和这套接入配置放在一起你的 OpenClaw 才算真正具备了可扩展的能力平面。