目录

把 OpenClaw 的 165 个 skill 挂进 Hermes:external_dirs 打通与 skill 库单一事实源治理

一次『发布博客』牵出的 skill 库治理:从重复造轮子、方向搞反,到用 skills.external_dirs 把 OpenClaw 的 165 个 skill 默认挂进 Hermes,并定下『单一事实源』

把 OpenClaw 的 165 个 skill 挂进 Hermes:external_dirs 打通与 skill 库单一事实源治理

家里的 AI 数字工厂同时跑着两套 skill 体系:Hermes(策略脑/沉淀中枢)和 OpenClaw(执行编排)。它们各有一棵 skill 树,最终喂给同一个会话。这段时间我踩了一串"重复造轮子 → 方向搞反 → 硬要重写 → 才发现权威在别处"的坑,最后用一个 skills.external_dirs 配置项把两边打通了。这篇把全过程和定下的治理原则记下来。

现象:我在 Hermes 侧又造了个轮子

起因很简单:发一篇博客到 oklife.me。我习惯性用 Hermes 侧的 blog-publish-oklifeme skill(把写好的技术文章收尾发布:入库、封面图、定点提交、线上验收)。

发完我顺手往这个 skill 里加了一块"Obsidian 副本回填"的内容——Obsidian 副本落哪个目录、怎么登记月度索引、路径大小写坑……结果这些逻辑,OpenClaw 的 blog-pipeline skill 里全都有(它写着"Obsidian 优先:所有编辑在 Obsidian,Hugo 复制是最后一步",还有 route_to_directory 目录路由 + 路径检查清单)。

我等于把 OpenClaw 权威 skill 已经拥有的东西,又抄进了一个次要的 Hermes skill。两份并存,日后必分叉。

纠正①:工作流方向我搞反了

第一处错:我把流程说成"先在站点写完,再回填 Obsidian 一份"。

反了。正确方向是:

Obsidian 先成稿 + 你审查 → 没问题才 cp 到 Hugo content/ → 发布。

Obsidian 那份是给审查用的落点(先写它方便过目),站点是下游产物。“站点写完再回填 Obsidian"是反模式。

纠正②:不该重写,该指向权威

第二处错:我不仅搞反了方向,还动手重写了 Hermes 的 blog-publish-oklifeme。但正确的动作是指向 OpenClaw 的 blog-pipeline——它才是这套流程的权威。

所以我把 Hermes 那个 skill 从 93 行瘦到 34 行的薄指针:只保留 Hermes 侧独有的实操速记(生封面默认走云端 Agnes 不碰 GPU、提交只定点 git add、线上验收会被 EdgeOne WAF 拦 curl 交浏览器确认),其余"成稿/审查/门控/路由/索引”全指 OpenClaw,一句"不内建那套,避免和权威分叉"。

原则:OpenClaw 拥有 agent 工作流;Hermes 侧重叠的 skill 必须是薄指针,不是副本。 能指向就不复制。

纠正③:OpenClaw 那 165 个我全都能用

第三处认知:我之前只盯着 blog-pipeline 一个,说"用那个"。其实整个 /home/oklife/.openclaw/skills/ 目录——165 个 skill——我都读得到:能读指令、能按 SKILL.md 操作、能跑它们的脚本。

边界也说清:

  • 纯脚本/指令型(agnes-image、obsidian-*、sn-* 数据分析、web-scraper…)→ 我完全能自己驱动。
  • 依赖 OpenClaw 运行时(blog-pipeline 里 spawn 子 agent、HITL sessions_yield 门控、agent_scaffold)→ 我能读文档 + 跑其中独立脚本,但"spawn 子 agent / yield 阻塞"是 OpenClaw 的活,我在 Hermes 里是模拟或交还,不能原样调。

落地:一条 external_dirs 把两棵 skill 树打通

要让 OpenClaw 的 165 个 skill 变成"默认可调用",官方口子就是 Hermes config 里的 skills.external_dirs(一个额外扫描目录的列表,支持 ~/${VAR})。

用 CLI 设(config 受保护,别手改文件;列表值用 JSON 数组字符串):

hermes config set skills.external_dirs '["/home/oklife/.openclaw/skills"]'
# ✓ Set skills.external_dirs = ['/home/oklife/.openclaw/skills']

验证解析成了真列表(不是被当成标量字符串):

hermes config get skills.external_dirs
# - /home/oklife/.openclaw/skills
hermes config check     # Config version: 51 ✓

落盘后的 YAML:

skills:
  external_dirs:
    - /home/oklife/.openclaw/skills

关键坑:下一会话才生效。 会话的 available-skills 列表在开局时固定,改完不能说"现在就有了"——得开新会话才载入这 165 个。

三条代价,别忽略

挂上外部目录不是免费的,三条要认清:

  1. 上下文膨胀:+165 个 skill 的 name+描述会灌进每个会话(原来 ~30 个 → 约 195)。能接受就留着;嫌重可以只 symlink 常用那几十个进精选子目录,再指它。
  2. 同名冲突:两边都有 agnes-image/comfyui/blog-publish-oklifeme 等。skill_view("comfyui") 可能歧义——一般主目录(~/.hermes/skills)优先。歧义时先查清你读的到底是哪个目录的 SKILL.md。
  3. 写风险(最重要):external_dirs 没有写保护,目录可被 Hermes 进程写、auto-curator 也可能碰。所以纪律是——对 OpenClaw skill 只 skill_view 只读,绝不 skill_manage/编辑/删除;要改 OpenClaw skill,告诉用户(它归 OpenClaw 系统),别静默改。

原则沉淀:skill 库单一事实源

把这套定成规矩,我 codify 进了一个 Hermes skill(skill-library-governance),核心就四条:

  • OpenClaw = 权威(agent 工作流:blog-pipeline、门控发布、子 agent 编排);Hermes = 薄镜像/指针。
  • 写任何 Hermes skill 前先搜 OpenClaw(ls + grep -rli 概念),权威已有就指向,不重造。
  • external_dirs 打通 + 只读纪律(可写无保护,别手滑改了 OpenClaw 库)。
  • 列表配置走 CLI(hermes config set … '[...]' + get + check),不手改 config。

经验教训

  1. 动手往 Hermes skill 里加东西前,先搜 OpenClaw——我这次就是没搜,重抄了 blog-pipeline 已有的路由/索引逻辑。
  2. 方向搞反要认:Obsidian 是成稿+审查点,站点是发布产物;“站点写完回填 Obsidian"是反模式。
  3. 重复就瘦成指针,别删:保留一个 Hermes 轻量入口,但内容只指权威、不重复。
  4. 挂外部目录想清楚三条代价(膨胀 / 冲突 / 写风险),并把"只读"定成硬纪律。

一句话收尾:两棵 skill 树,一个事实源(OpenClaw)、一棵薄镜像(Hermes)、一条 external_dirs 桥、一套只读纪律——工厂的 skill 层才算治理到位。