文章

OpenClaw Skills 加载机制:源码级调研(更新与注册路径)

OpenClaw Skills 加载机制调研报告

0. 执行摘要

  • 本报告结论全部基于仓库源码(/root/githubrepo/openclaw)中的实现与测试。
  • 结论要点:
    • Skills 的运行时发现核心在 loadSkillEntries(),统一扫描多类目录并按固定优先级覆盖同名 skill。
    • “下载的 skill”和“本地自开发 skill”在 OpenClaw 核心里没有单独类型;本质都通过“目录中存在 SKILL.md”被发现。
    • 启用/禁用主要由 skills.entries.<skillKey>.enabledskills.allowBundled、metadata 条件(OS/bin/env/config)、插件启用状态共同决定。
    • 会话中使用 skill snapshot(快照),并通过 watcher / 远端节点变化触发版本刷新。

1. 仓库更新到最新代码(任务 1)

1.1 本地状态检查

  • 分支:main(跟踪 origin/main
  • 工作区:干净(git status --porcelain=v1 -b 仅显示 ## main...origin/main

1.2 安全更新尝试

  • 已执行:
    • git fetch --prune origin
    • git 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.tsloadSkillEntries()

它会依次收集以下来源并调用 loadSkillsFromDir()

  1. openclaw-extra
    • 来自 skills.load.extraDirs
    • 以及插件 manifest 声明的 skills 目录(见 2.4)
  2. openclaw-bundled
    • 内置 skills 目录(见 4.1)
  3. openclaw-managed
    • 默认 CONFIG_DIR/skills,通常是 ~/.openclaw/skills
  4. agents-skills-personal
    • ~/.agents/skills
  5. agents-skills-project
    • <workspace>/.agents/skills
  6. 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 skills
  • metadata.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()

3. 下载 skill 与本地自定义 skill 如何注册/启用

3.1 结论(源码层面)

在 OpenClaw 核心实现里,“下载 skill”和“自开发 skill”没有不同注册协议

  • 只要某个扫描路径下存在 skillDir/SKILL.md,就会被发现。
  • 所以“注册”本质是“放到被扫描目录”。

3.2 常见路径与注册方式

  • 本地自开发(最直接):放到 <workspace>/skills/<name>/SKILL.md
  • 共享/托管:放到 ~/.openclaw/skills/<name>/SKILL.mdopenclaw-managed
  • 插件携带:在 openclaw.plugin.json 声明 skills 目录,且插件被启用

3.3 启用/禁用手段

  1. 全局/按 skill 配置:skills.entries.<skillKey>.enabled
  2. 内置 skills 白名单:skills.allowBundled
  3. metadata 依赖满足与否:OS/bin/env/config
  4. agent 级 allowlist:agents.list[].skills
  5. slash command 暴露:frontmatter user-invocable(默认 true)
  6. 是否注入模型提示词:disable-model-invocation(true 时只保留用户调用能力)

3.4 关于“下载”动作本身

  • openclaw CLI 的 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() 解析顺序:

  1. OPENCLAW_BUNDLED_SKILLS_DIR 环境变量
  2. 可执行文件同级 skills/(bun compile 场景)
  3. <packageRoot>/skills(npm/dev 场景)
  4. 以当前模块向上最多 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.allowBundled
  • skills.load.extraDirs
  • skills.load.watch
  • skills.load.watchDebounceMs
  • skills.install.preferBrew
  • skills.install.nodeManager
  • skills.limits.*
  • skills.entries.<skillKey>.enabled/apiKey/env/config
  • agents.list[].skills(agent 级技能 allowlist)
  • plugins.entries.<id>.enabled(影响 plugin-shipped skills 是否纳入)

5.2 命令/接口入口

  • CLI:openclaw skills list|info|check
  • Gateway RPC:
    • skills.status
    • skills.bins
    • skills.install
    • skills.update
  • Agent 运行入口:commands/agent.ts 内构建 skillsSnapshot
  • Auto-reply 入口:auto-reply/reply/session-updates.ts(首轮/版本变化时刷新 snapshot)

5.3 关键源码证据(文件 + 函数/模块)

  1. src/agents/skills/workspace.ts
    • loadSkillEntries
    • buildWorkspaceSkillSnapshot
    • buildWorkspaceSkillsPrompt
    • buildWorkspaceSkillCommandSpecs
    • syncSkillsToWorkspace
  2. src/agents/skills/config.ts
    • shouldIncludeSkill
    • resolveSkillConfig
    • resolveBundledAllowlist
    • isBundledSkillAllowed
  3. src/agents/skills/frontmatter.ts
    • resolveOpenClawMetadata
    • resolveSkillInvocationPolicy
    • resolveSkillKey
  4. src/agents/skills/plugin-skills.ts
    • resolvePluginSkillDirs
  5. src/agents/skills/bundled-dir.ts
    • resolveBundledSkillsDir
  6. src/agents/skills/refresh.ts
    • ensureSkillsWatcher
    • bumpSkillsSnapshotVersion
    • getSkillsSnapshotVersion
  7. src/agents/skills/env-overrides.ts
    • applySkillEnvOverrides
    • applySkillEnvOverridesFromSnapshot
  8. src/agents/skills-install.ts
    • installSkill
  9. src/agents/skills-install-download.ts
    • installDownloadSpec
  10. src/commands/agent.ts
    • buildWorkspaceSkillSnapshot 调用链(新会话/无 snapshot 时)
  11. src/auto-reply/reply/session-updates.ts
    • ensureSkillsWatcher + snapshot 刷新逻辑
  12. src/auto-reply/skill-commands.ts
    • listSkillCommandsForWorkspace
    • resolveSkillCommandInvocation
  13. src/gateway/server-methods/skills.ts
    • skills.status
    • skills.bins
    • skills.install
    • skills.update
  14. src/plugins/manifest.ts / src/plugins/manifest-registry.ts
    • 插件 skills 字段读取与注册

6. 未确认项(明确标注)

  1. 未确认:远端最新代码是否已同步
    • 原因:当前环境无法连接 GitHub,fetch/pull 失败。
  2. 未确认:loadSkillsFromDir() 的底层解析细节
    • 原因:该函数来自外部依赖 @mariozechner/pi-coding-agent;本次报告仅以本仓库调用方式为证据。
  3. 未确认:ClawHub 下载流程内部实现
    • 原因:本仓库仅提示使用 npx clawhub,未包含其完整下载实现源码。
本文由作者按照 CC BY 4.0 进行授权