当大模型的上下文窗口成为稀缺资源,如何让 AI 在 50+ 个专业领域之间按需切换,同时不浪费一个 token?OpenClaw 的 Skills 系统给出了一个工程上极其优雅的答案。
一、背景:AI Agent 的"万能"困局
你一定遇到过这样的场景——
让 AI 帮你查天气,它不知道该调用哪个 API;让它帮你操作 1Password,它不知道 CLI 怎么用;让它帮你生成图片,它连 Python 脚本都要从头写一遍。
问题不在于模型不够聪明,而在于模型缺少特定领域的程序性知识(Procedural Knowledge)。这类知识——"具体用什么命令"、"参数怎么填"、"脚本长什么样"——不是通过预训练能完全覆盖的。
传统的解决方案是写一大段 System Prompt,把所有领域的知识塞进去。但这会导致:
- 上下文窗口爆炸:50 个领域的详细指令能轻松吃掉 10 万+ tokens
- 注意力稀释:模型在大段 prompt 中找到相关段落的能力会下降
- 维护噩梦:增删改一个领域需要触碰整个 prompt
OpenClaw(一个开源的多渠道 AI 助手网关)提出了一种不同的思路:Skills 系统。
二、Skills 不只是"文档"
一看到"Skill"这个词,你可能会想到 Custom Instructions 或者 Prompt Template——写一段文字告诉 AI 怎么做。
OpenClaw 的 Skill 远不止于此。它是一个完整的可分发能力包(Capability Package),包含:
skill-name/
├── SKILL.md # 必需:元数据声明 + 使用指令
├── scripts/ # 可选:可执行脚本(Python/Bash/Node)
├── bin/ # 可选:二进制包装器
├── references/ # 可选:按需加载的参考文档
└── assets/ # 可选:模板、图片等输出资源
让我们逐层拆解。
三、第一层:声明式元数据——"我是谁、我需要什么"
每个 Skill 的 SKILL.md 顶部有一个 YAML frontmatter 块。以本地 TTS(文字转语音)Skill 为例:
---
name: sherpa-onnx-tts
description: Local text-to-speech via sherpa-onnx (offline, no cloud)
metadata:
openclaw:
emoji: "🗣️"
os: ["darwin", "linux", "win32"]
requires:
env: ["SHERPA_ONNX_RUNTIME_DIR", "SHERPA_ONNX_MODEL_DIR"]
install:
- id: "download-runtime-macos"
kind: "download"
os: ["darwin"]
url: "https://github.com/.../sherpa-onnx-v1.12.23-osx-universal2-shared.tar.bz2"
archive: "tar.bz2"
extract: true
stripComponents: 1
targetDir: "runtime"
- id: "download-runtime-linux-x64"
kind: "download"
os: ["linux"]
url: "https://github.com/.../sherpa-onnx-v1.12.23-linux-x64-shared.tar.bz2"
...
- id: "download-model-lessac"
kind: "download"
url: "https://github.com/.../vits-piper-en_US-lessac-high.tar.bz2"
targetDir: "models"
---
这段元数据声明了五件事:
| 字段 | 含义 |
|---|---|
os | 支持哪些操作系统 |
requires.bins | 需要哪些命令行工具 |
requires.env | 需要哪些环境变量 |
requires.anyBins | 多个工具中有一个即可 |
install | 依赖缺失时如何自动安装 |
关键洞察:这些信息是给运行时引擎看的,不是给模型看的。 运行时在 Skill 被触发之前就用这些元数据做资格检查和依赖安装。
四、内置的自动安装系统
这是 Skills 机制最出乎意料的部分——它内建了 5 种安装器。
看一下实际的安装命令构建逻辑(src/agents/skills-install.ts):
function buildInstallCommand(spec: SkillInstallSpec, prefs: SkillsInstallPreferences) {
switch (spec.kind) {
case "brew":
return { argv: ["brew", "install", spec.formula] };
case "node":
return { argv: buildNodeInstallCommand(spec.package, prefs) };
case "go":
return { argv: ["go", "install", spec.module] };
case "uv":
return { argv: ["uv", "tool", "install", spec.package] };
case "download":
// 单独处理:下载 + 解压
return { argv: null, error: "download install handled separately" };
}
}
五种安装器覆盖了主流的包管理生态:
| kind | 用途 | 实际命令示例 |
|---|---|---|
brew | macOS Homebrew | brew install python |
node | npm/pnpm/yarn/bun 全局包 | npm install -g <package> |
go | Go 模块 | go install <module> |
uv | Python 工具 | uv tool install <package> |
download | 下载归档文件并解压 | 从 GitHub Releases 下载 .tar.bz2 |
而且,node 安装器还会尊重用户的包管理器偏好:
function buildNodeInstallCommand(packageName: string, prefs: SkillsInstallPreferences): string[] {
switch (prefs.nodeManager) {
case "pnpm": return ["pnpm", "add", "-g", "--ignore-scripts", packageName];
case "yarn": return ["yarn", "global", "add", "--ignore-scripts", packageName];
case "bun": return ["bun", "add", "-g", "--ignore-scripts", packageName];
default: return ["npm", "install", "-g", "--ignore-scripts", packageName];
}
}
注意 --ignore-scripts——默认禁用 npm 的 postinstall 脚本,这是一个安全考量。
download 安装器更有意思,它实现了完整的"下载 → 解压 → 安全校验"流程:
// 下载文件到临时目录
const result = await downloadFile({ url, rootDir: safeRoot, relativePath, timeoutMs });
// 自动检测归档类型
const archiveType = resolveArchiveType(spec, filename); // tar.gz / tar.bz2 / zip
// 解压到目标目录
await extractArchive({ archivePath, archiveType, targetDir, stripComponents, timeoutMs });
所有下载目标都被严格限制在 ~/.openclaw/tools/<skill-name>/ 下,有完整的路径遍历防护。
从用户视角看:你说"帮我用本地 TTS 朗读这段话",系统发现 sherpa-onnx-tts Skill 可用但依赖未安装,自动下载对应平台的运行时和语音模型,然后执行。整个过程对用户透明。
五、运行时资格检查——"这个 Skill 现在能不能用"
在 Skill 被注入到 AI 上下文之前,运行时会做一系列检查(src/agents/skills/config.ts):
function shouldIncludeSkill(params) {
const { entry, config, eligibility } = params;
// 1. 用户手动禁用了?
if (skillConfig?.enabled === false) return false;
// 2. 不在 bundled allowlist 中?
if (!isBundledSkillAllowed(entry, allowBundled)) return false;
// 3. 运行时资格检查
return evaluateRuntimeEligibility({
os: entry.metadata?.os, // 操作系统匹配
requires: entry.metadata?.requires, // 依赖检查
hasBin: hasBinary, // 本机二进制检查
hasRemoteBin: eligibility?.remote?.hasBin, // 远程设备二进制检查
hasEnv: (envName) => Boolean( // 环境变量检查
process.env[envName] ||
skillConfig?.env?.[envName] ||
(skillConfig?.apiKey && entry.metadata?.primaryEnv === envName)
),
});
}
这意味着:
- Linux 上不会出现 macOS 专属的 Apple Notes Skill
- 没有安装
tmux的机器上不会出现 tmux Skill - 没有配置
OPENAI_API_KEY的环境不会出现 OpenAI 图片生成 Skill - 连接了 iOS 设备时,才会出现需要 iOS 的 Skill
这种"按能力过滤"的设计,避免了 AI 去调用一个根本不可能成功的工具。
六、渐进式加载——上下文窗口的精细管理
这是整套设计最精巧的部分。Skills 使用三层渐进式加载(Progressive Disclosure)来管理上下文开销:
┌─────────────────────────────────────────┐
│ Level 1: 元数据(始终在上下文中) │
│ name + description ≈ 100 tokens/skill │
│ 50 个 Skill ≈ 5000 tokens │
└──────────────┬──────────────────────────┘
│
AI 判断:"这个 Skill 和当前任务相关"
│
┌──────────────▼──────────────────────────┐
│ Level 2: SKILL.md 正文(触发后加载) │
│ 具体命令、参数、工作流 < 5000 words │
└──────────────┬──────────────────────────┘
│
AI 判断:"需要更多细节" / "需要执行脚本"
│
┌──────────────▼──────────────────────────┐
│ Level 3: 附属资源(按需加载/执行) │
│ scripts/ → 直接执行,不占上下文 │
│ references/ → 读取到上下文 │
│ bin/ → 直接调用,不占上下文 │
└─────────────────────────────────────────┘
具体的限制参数:
const DEFAULT_MAX_SKILLS_IN_PROMPT = 150; // 最多 150 个 Skill 的元数据
const DEFAULT_MAX_SKILLS_PROMPT_CHARS = 30_000; // 元数据总字符上限 30K
const DEFAULT_MAX_SKILL_FILE_BYTES = 256_000; // 单个 SKILL.md 最大 256KB
为什么这很重要?
假设你有 50 个 Skill。传统做法是把所有 50 个 Skill 的完整文档塞进 System Prompt,可能需要 10 万+ tokens。
而在 OpenClaw 的方案中:
- Level 1 只需要约 5000 tokens(50 × 100)
- Level 2 只在用户明确触发某个领域时加载
- Level 3 中的脚本甚至不需要进入上下文窗口——AI 只需要知道"运行
{baseDir}/scripts/gen.py"就行
节省的 token 可以用来处理更长的对话历史、更丰富的工具输出。
七、Skill 的丰富形态——不只一种"能力"
从 OpenClaw 内置的 50+ 个 Skill 来看,它们呈现出非常不同的形态:
形态 1:纯知识注入型
以 weather Skill 为例——目录下只有一个 SKILL.md,教 AI 如何用 curl 调用 wttr.in:
---
name: weather
description: "Get current weather and forecasts via wttr.in or Open-Meteo."
metadata: { "openclaw": { "requires": { "bins": ["curl"] } } }
---
## Commands
### Current Weather
curl "wttr.in/London?format=3"
### Forecasts
curl "wttr.in/London?format=v2"
AI 天然知道 curl,但不知道 wttr.in 的 API 格式。Skill 补全了这块知识。
形态 2:脚本捆绑型
openai-image-gen Skill 自带了一个完整的 Python 脚本(scripts/gen.py,约 11KB),并声明了自动安装:
metadata:
openclaw:
requires: { "bins": ["python3"], "env": ["OPENAI_API_KEY"] }
install:
- id: "python-brew"
kind: "brew"
formula: "python"
bins: ["python3"]
AI 不需要从头写图片生成代码——直接调用打包好的脚本:
python3 {baseDir}/scripts/gen.py --prompt "a lobster astronaut" --count 4
脚本还自带测试(test_gen.py),是经过验证的确定性实现。
形态 3:二进制 + 运行时下载型
sherpa-onnx-tts Skill 自带了一个 Node.js 包装脚本(bin/sherpa-onnx-tts),并声明了跨平台的运行时下载——macOS、Linux、Windows 各一份,外加语音模型文件。
这不是简单的"教 AI 用工具",而是在用户不知情的情况下完成了一个完整的软件安装流程。
形态 4:参考文档型
1password Skill 有一个 references/ 目录,包含 get-started.md 和 cli-examples.md。SKILL.md 本体保持精简,只在 AI 判断需要深入了解时才加载 references。
这种设计特别适合复杂 API——SKILL.md 放"概述 + 常用命令",references 放"完整 API 文档"。
形态 5:编排型(Meta Skill)
coding-agent Skill 教 AI 如何 spawn 和管理其他 AI Agent:
## The Pattern: workdir + background + pty
# 启动 Codex agent 在后台
bash pty:true workdir:~/project background:true command:"codex exec --full-auto 'Build a snake game'"
# 监控进度
process action:log sessionId:XXX
# 发送输入
process action:submit sessionId:XXX data:"yes"
这不再是"让 AI 用工具",而是让 AI 管理其他 AI。
形态 6:自举型(Self-bootstrapping)
skill-creator Skill 教 AI 如何创建新的 Skill。它自带了 init_skill.py、package_skill.py、quick_validate.py 三个脚本,覆盖了 Skill 的创建、打包、验证全流程。
这意味着系统可以自我扩展——AI 可以根据用户需求创建新的 Skill,打包后分发。
八、安全机制——不信任任何输入
社区贡献的 Skill 可能包含恶意代码。OpenClaw 在多个层面做了防护。
安装时安全扫描
src/security/skill-scanner.ts 在 Skill 安装时扫描所有 JS/TS 文件,检测危险代码模式:
type SkillScanFinding = {
ruleId: string;
severity: "info" | "warn" | "critical";
file: string;
line: number;
message: string;
evidence: string;
};
发现 critical 级别的问题会生成警告,用户可以选择是否继续。
输入净化
所有 frontmatter 中的安装参数都经过严格校验:
// Brew formula 校验——防止命令注入
const BREW_FORMULA_PATTERN = /^[A-Za-z0-9][A-Za-z0-9@+._/-]*$/;
// npm 包名校验
function normalizeSafeNpmSpec(raw) {
if (!spec || spec.startsWith("-")) return undefined; // 防止 flag 注入
if (validateRegistryNpmSpec(spec) !== null) return undefined;
return spec;
}
// 下载 URL 校验——只允许 http/https
function normalizeSafeDownloadUrl(raw) {
const parsed = new URL(value);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return undefined;
return parsed.toString();
}
路径安全
下载目标目录有严格的边界检查,防止路径遍历攻击:
function resolveDownloadTargetDir(entry, spec) {
const safeRoot = resolveSkillToolsRootDir(entry); // ~/.openclaw/tools/<skill>/
const resolved = path.resolve(safeRoot, raw);
if (!isWithinDir(safeRoot, resolved)) {
throw new Error(
`Refusing to install outside the skill tools directory. ` +
`targetDir="${raw}" resolves to "${resolved}". Allowed root: "${safeRoot}".`
);
}
return resolved;
}
打包时也会拒绝包含 symlink 的 Skill,防止符号链接逃逸。
九、分发机制——ClawHub 生态
OpenClaw 有一个配套的 Skill 市场——ClawHub(clawhub.com),类似 npm 之于 Node.js。
clawhub Skill(对,它自己也是一个 Skill)提供了完整的生命周期管理:
clawhub search "postgres backups" # 搜索
clawhub install my-skill # 安装
clawhub update --all # 批量更新
clawhub publish ./my-skill # 发布
Skill 的打包产物是一个 .skill 文件(本质是 zip),包含验证过的目录结构。
十、与同类方案的对比
| 维度 | OpenClaw Skills | Custom GPTs / Prompts | MCP Tools | LangChain Tools |
|---|---|---|---|---|
| 知识注入 | ✅ 三层渐进式 | ✅ 全量加载 | ❌ 无 | ❌ 无 |
| 可执行脚本 | ✅ 内置 | ❌ | ❌ | ✅ 需编码 |
| 依赖声明 | ✅ 声明式 | ❌ | ❌ | ❌ |
| 自动安装 | ✅ 5 种安装器 | ❌ | ❌ | ❌ |
| 平台感知 | ✅ OS/bin/env | ❌ | ❌ | ❌ |
| 上下文优化 | ✅ 按需加载 | ❌ 全量 | ✅ schema 级 | ❌ |
| 安全扫描 | ✅ 内置 | N/A | ❌ | ❌ |
| 社区分发 | ✅ ClawHub | ✅ GPT Store | ❌ | ❌ |
OpenClaw Skills 的独特之处在于它将知识注入、工具集成、依赖管理、安全检查统一在一个声明式的框架内,而不是把这些问题留给开发者逐一解决。
十一、设计哲学与启示
从 OpenClaw Skills 系统中,可以提炼出几个值得借鉴的设计原则:
原则 1:上下文窗口是稀缺资源,要按需分配
不要把所有信息一股脑塞给模型。用元数据做路由,让模型自己决定需要什么深度的信息。这是一种信息的"懒加载"。
原则 2:AI 不只需要知识,还需要工具
纯文本的 Prompt 只能教 AI "知道"——但 scripts/ 和 bin/ 让 AI 能"做到"。一个经过测试的确定性脚本,比让 AI 每次从头生成代码要可靠得多。
原则 3:声明式优于命令式
不是"请安装 Python",而是 requires.bins: ["python3"] + install: [{ kind: "brew", formula: "python" }]。运行时引擎负责"怎么做",Skill 只负责"需要什么"。
原则 4:安全不是事后补丁
从输入校验(brew formula 正则)、路径约束(isWithinDir)、到代码扫描(skill-scanner),安全考量嵌入在了每一层设计中。
原则 5:系统要能自我扩展
skill-creator Skill 赋予了 AI 创建新 Skill 的能力,ClawHub 提供了分发渠道。这种**自举(bootstrapping)**能力让生态可以有机增长。
十二、总结
OpenClaw 的 Skills 系统本质上是一个 为 AI Agent 设计的声明式包管理器:
- 它用 YAML frontmatter 声明能力和依赖
- 用三层渐进式加载精细管理上下文开销
- 用五种安装器自动解决运行时依赖
- 用脚本和二进制提供确定性的执行能力
- 用安全扫描和路径约束防御供应链攻击
- 用 ClawHub 实现社区级的能力分发
在 AI Agent 框架百花齐放的今天,大多数项目都在解决"如何调用工具"的问题。OpenClaw 更进一步——它同时解决了**"怎么知道该用什么工具"、"怎么安装工具"、"怎么在有限上下文中管理几十个工具的知识"**这三个同等重要的问题。
这或许预示了 AI Agent 基础设施的一个方向:不只是工具编排,而是完整的能力生命周期管理。
十三、对 AI 使用者的启发——你不需要写代码,但需要这些思维
前面十二节偏技术实现,但 OpenClaw Skills 系统背后的设计理念,对每一个日常使用 AI 的人都有直接价值。
启发 1:上下文窗口是你最贵的资源,别浪费
很多人把一大堆背景信息、规则、示例全塞进 System Prompt,觉得"给得越多越好"。OpenClaw 的做法恰恰相反——50+ 个 Skill,常驻上下文只放 name + description(每个约 100 tokens),详细指令只在触发时才加载。
你可以这样做:给 AI 的 prompt 也应该分层。把"什么时候用"放在最前面,"怎么用的细节"放在后面或者单独的文件里。不是所有信息都需要一直在场。上下文塞太满,模型反而找不到重点。
启发 2:别让 AI 每次重新发明轮子——给它"预制件"
OpenClaw 的 Skill 不是简单地告诉 AI "你可以查天气",而是直接提供了写好的 Python 脚本、Bash 工具、甚至二进制程序。AI 不需要从头写代码,直接调用即可。
你可以这样做:如果你经常让 AI 做某类重复性任务(生成报告、处理数据、格式转换),与其每次用自然语言描述,不如准备好模板、脚本或 prompt 片段。把"可复用的确定性操作"固化下来,让 AI 做编排和决策,而不是每次都从零开始。
启发 3:自定义指令是刚需,不是可选项
OpenClaw 的核心假设是:模型本身很聪明,但缺少你的领域的程序性知识。它知道 Python 语法,但不知道你公司的 API 怎么调;它知道 SQL,但不知道你的表结构长什么样。
你可以这样做:无论你用 ChatGPT、Claude 还是任何 AI 工具,都应该投入时间构建自己的"Skill 库"——可以是 Custom Instructions、项目级的 CLAUDE.md / .cursorrules、或者 System Prompt 模板。这不是"锦上添花",这是决定 AI 输出质量的关键变量。
启发 4:告诉 AI "什么时候不要用"比"什么时候用"更重要
注意 OpenClaw 的每个 Skill 都有明确的 "When NOT to Use" 部分。比如 weather Skill 会说"历史气象数据不要用我,去用专门的 API"。
你可以这样做:在写给 AI 的指令中,边界条件和排除规则往往比正面描述更有价值。"不要用 xxx 方式实现"、"这种情况走另一个流程"——这些约束能大幅减少 AI 的错误决策。
启发 5:上下文管理是你的责任,不是模型的
OpenClaw 花了大量工程投入来管理上下文:渐进式加载、token 预算、Skill 数量上限(150 个)、单文件大小上限(256KB)。它不指望模型自己"聪明地"处理 10 万 token 的 prompt。
你可以这样做:当你和 AI 长对话时,上下文会逐渐堆积和失焦。主动管理它——定期总结、裁剪无关历史、把核心规则放在 System Prompt 而非第 50 轮对话里。模型的注意力机制不是万能的,越精练的输入得到越精准的输出。
启发 6:声明目标和约束,比描述步骤更高效
OpenClaw 的 Skill 用声明式的 YAML 说"我需要 python3、我需要 OPENAI_API_KEY",运行时自动检查和安装。它不说"请先检查有没有 Python,如果没有就用 Homebrew 安装"。
你可以这样做:给 AI 的指令也一样——声明目标和约束,比描述步骤更好。"用 TypeScript 写一个 REST API,需要鉴权、分页、错误处理" 比 "第一步创建文件,第二步写路由,第三步..." 更能发挥模型的能力。让 AI 决定"怎么做",你负责定义"做成什么样"。
启发 7:安全意识要嵌入工作流,不能事后补
OpenClaw 对社区 Skill 做代码扫描、对安装参数做正则校验、对下载路径做边界检查。这些不是出了事才加的,是设计之初就有的。
你可以这样做:当你让 AI 执行代码、访问文件、调用 API 时,养成审查输出的习惯。特别是让 AI 写 shell 命令、数据库操作、或者处理用户输入时——AI 不会主动考虑安全边界,这是你的责任。
本文基于 OpenClaw 项目(github.com/openclaw/op… 源码分析。 项目 MIT 协议开源,欢迎阅读源码深入了解。