OpenClaw Skills 加载机制:源码级调研(更新与注册路径)
OpenClaw Skills 加载机制调研报告
0. 执行摘要
- 本报告结论全部基于仓库源码(
/root/githubrepo/openclaw)中的实现与测试。 - 结论要点:
- Skills 的运行时发现核心在
loadSkillEntries(),统一扫描多类目录并按固定优先级覆盖同名 skill。 - “下载的 skill”和“本地自开发 skill”在 OpenClaw 核心里没有单独类型;本质都通过“目录中存在
SKILL.md”被发现。 - 启用/禁用主要由
skills.entries.<skillKey>.enabled、skills.allowBundled、metadata 条件(OS/bin/env/config)、插件启用状态共同决定。 - 会话中使用 skill snapshot(快照),并通过 watcher / 远端节点变化触发版本刷新。
- Skills 的运行时发现核心在
1. 仓库更新到最新代码(任务 1)
1.1 本地状态检查
- 分支:
main(跟踪origin/main) - 工作区:干净(
git status --porcelain=v1 -b仅显示## main...origin/main)
1.2 安全更新尝试
- 已执行:
git fetch --prune origingit pull --rebase origin main
- 结果:两条命令均失败,错误一致:
fatal: unable to access 'https://github.com/openclaw/openclaw.git/': Couldn't connect to server
- 本地比较(基于本地
origin/main引用):git rev-list --left-right --count HEAD...origin/main返回0 0
1.3 结论
- 未确认 当前仓库已同步“远端最新”代码。
- 原因:网络不可达导致 fetch/pull 无法完成;
0 0仅说明本地HEAD与本地缓存的origin/main一致。
2. Skills 运行时如何发现与加载(内置、下载、自开发)
2.1 统一发现入口
核心函数:src/agents/skills/workspace.ts 的 loadSkillEntries()。
它会依次收集以下来源并调用 loadSkillsFromDir():
openclaw-extra- 来自
skills.load.extraDirs - 以及插件 manifest 声明的 skills 目录(见 2.4)
- 来自
openclaw-bundled- 内置 skills 目录(见 4.1)
openclaw-managed- 默认
CONFIG_DIR/skills,通常是~/.openclaw/skills
- 默认
agents-skills-personal~/.agents/skills
agents-skills-project<workspace>/.agents/skills
openclaw-workspace<workspace>/skills
发现条件:
- 目录级别只接受直接子目录里存在
SKILL.md的候选。 - 支持根目录就是单 skill(根下直接
SKILL.md)。 - 支持“嵌套 skills 根”启发式(检测
<dir>/skills/*/SKILL.md)。
2.2 优先级(同名 skill 覆盖)
源码注释明确:
extra < bundled < managed < agents-skills-personal < agents-skills-project < workspace
实现上用 Map<string, Skill>,按上面顺序 set(),后写覆盖前写。
2.3 解析与过滤
每个 skill 条目会读取并解析 frontmatter:
parseFrontmatter()->resolveOpenClawMetadata()->resolveSkillInvocationPolicy()
最终过滤由 shouldIncludeSkill() 决定,关键条件:
skills.entries.<skillKey>.enabled === false则禁用skills.allowBundled只限制 bundled skillsmetadata.openclaw.os与当前/远端可用平台匹配metadata.openclaw.requires(bins/anyBins/env/config)满足metadata.openclaw.always === true可跳过其他 requirement gate
2.4 插件 skills 的发现
入口:resolvePluginSkillDirs()(src/agents/skills/plugin-skills.ts)
- 从插件 manifest registry 读取每个插件声明的
skills路径(相对插件根目录) - 仅当插件启用(
resolveEnableState)且 memory slot 规则允许(resolveMemorySlotDecision)时纳入 - 解析出的目录并入
extraDirs,作为openclaw-extra来源参与加载
2.5 运行时注入与快照
- 构建快照:
buildWorkspaceSkillSnapshot() - 写入系统提示词:
formatSkillsForPrompt(...)产出<available_skills>...block - 会话保存:
skillsSnapshot(含prompt/skills/version/skillFilter) - 执行前注入环境变量:
- 有 snapshot:
applySkillEnvOverridesFromSnapshot() - 无 snapshot:
applySkillEnvOverrides()
- 有 snapshot:
3. 下载 skill 与本地自定义 skill 如何注册/启用
3.1 结论(源码层面)
在 OpenClaw 核心实现里,“下载 skill”和“自开发 skill”没有不同注册协议:
- 只要某个扫描路径下存在
skillDir/SKILL.md,就会被发现。 - 所以“注册”本质是“放到被扫描目录”。
3.2 常见路径与注册方式
- 本地自开发(最直接):放到
<workspace>/skills/<name>/SKILL.md - 共享/托管:放到
~/.openclaw/skills/<name>/SKILL.md(openclaw-managed) - 插件携带:在
openclaw.plugin.json声明skills目录,且插件被启用
3.3 启用/禁用手段
- 全局/按 skill 配置:
skills.entries.<skillKey>.enabled - 内置 skills 白名单:
skills.allowBundled - metadata 依赖满足与否:OS/bin/env/config
- agent 级 allowlist:
agents.list[].skills - slash command 暴露:frontmatter
user-invocable(默认 true) - 是否注入模型提示词:
disable-model-invocation(true 时只保留用户调用能力)
3.4 关于“下载”动作本身
openclawCLI 的skills子命令目前是list/info/check;未见“从注册中心拉取 skill 包”的内置命令。- UI/RPC 的
skills.install是执行 metadata 里的 install spec(brew/node/go/uv/download),主要是安装 skill 依赖,不等于从外部技能市场下载 skill 定义。 - 代码中仅给出提示:
npx clawhub用于 search/install/sync skills。
4. 内置 skills 与外部 skills 的路径、优先级、差异
4.1 内置(bundled)路径解析
resolveBundledSkillsDir() 解析顺序:
OPENCLAW_BUNDLED_SKILLS_DIR环境变量- 可执行文件同级
skills/(bun compile 场景) <packageRoot>/skills(npm/dev 场景)- 以当前模块向上最多 6 层寻找
skills/
4.2 外部 skills 路径
- managed:
CONFIG_DIR/skills(默认~/.openclaw/skills) - workspace:
<workspace>/skills - agents personal/project:
~/.agents/skills、<workspace>/.agents/skills - extraDirs:
skills.load.extraDirs - plugin skills:插件 manifest 声明目录(合并到 extra)
4.3 关键差异
allowBundled仅作用于 bundled;不影响 workspace/managed/extra。- plugin skills 要先通过插件启用逻辑。
- 同名覆盖时,workspace 优先级最高,extra 最低。
5. 相关配置项、命令入口、关键代码路径
5.1 配置项(openclaw.json)
skills.allowBundledskills.load.extraDirsskills.load.watchskills.load.watchDebounceMsskills.install.preferBrewskills.install.nodeManagerskills.limits.*skills.entries.<skillKey>.enabled/apiKey/env/configagents.list[].skills(agent 级技能 allowlist)plugins.entries.<id>.enabled(影响 plugin-shipped skills 是否纳入)
5.2 命令/接口入口
- CLI:
openclaw skills list|info|check - Gateway RPC:
skills.statusskills.binsskills.installskills.update
- Agent 运行入口:
commands/agent.ts内构建skillsSnapshot - Auto-reply 入口:
auto-reply/reply/session-updates.ts(首轮/版本变化时刷新 snapshot)
5.3 关键源码证据(文件 + 函数/模块)
src/agents/skills/workspace.tsloadSkillEntriesbuildWorkspaceSkillSnapshotbuildWorkspaceSkillsPromptbuildWorkspaceSkillCommandSpecssyncSkillsToWorkspace
src/agents/skills/config.tsshouldIncludeSkillresolveSkillConfigresolveBundledAllowlistisBundledSkillAllowed
src/agents/skills/frontmatter.tsresolveOpenClawMetadataresolveSkillInvocationPolicyresolveSkillKey
src/agents/skills/plugin-skills.tsresolvePluginSkillDirs
src/agents/skills/bundled-dir.tsresolveBundledSkillsDir
src/agents/skills/refresh.tsensureSkillsWatcherbumpSkillsSnapshotVersiongetSkillsSnapshotVersion
src/agents/skills/env-overrides.tsapplySkillEnvOverridesapplySkillEnvOverridesFromSnapshot
src/agents/skills-install.tsinstallSkill
src/agents/skills-install-download.tsinstallDownloadSpec
src/commands/agent.tsbuildWorkspaceSkillSnapshot调用链(新会话/无 snapshot 时)
src/auto-reply/reply/session-updates.tsensureSkillsWatcher+ snapshot 刷新逻辑
src/auto-reply/skill-commands.tslistSkillCommandsForWorkspaceresolveSkillCommandInvocation
src/gateway/server-methods/skills.tsskills.statusskills.binsskills.installskills.update
src/plugins/manifest.ts/src/plugins/manifest-registry.ts- 插件
skills字段读取与注册
- 插件
6. 未确认项(明确标注)
- 未确认:远端最新代码是否已同步
- 原因:当前环境无法连接 GitHub,fetch/pull 失败。
- 未确认:
loadSkillsFromDir()的底层解析细节- 原因:该函数来自外部依赖
@mariozechner/pi-coding-agent;本次报告仅以本仓库调用方式为证据。
- 原因:该函数来自外部依赖
- 未确认:ClawHub 下载流程内部实现
- 原因:本仓库仅提示使用
npx clawhub,未包含其完整下载实现源码。
- 原因:本仓库仅提示使用
本文由作者按照 CC BY 4.0 进行授权