Skip to content

技能系統 Skills

源码版本v2026.7.20

職責

Skill 是比 Tool 更高階的能力單元:一段可複用的、帶 frontmatter 的流程(類似 agentskills.io 規範),按領域歸類在 skills/<category>/ 下。與工具 (tool) 的「靜態函式」不同,技能可被學習閉環建立、改寫、精煉,是 agent「越用越聰明」的載體。技能透過 skills_tool 暴露給主迴圈呼叫。

設計動機

為什麼 skill 要按 category 分目錄而不是平鋪?技能數量會隨使用增長(使用者加的、hub 同步的、學習循環生成的都在 ~/.hermes/skills/),平鋪後 skills_list 回傳的列表很快變成雜訊。category 讓 progressive disclosure 第一層只暴露「這有一組 research 技能」而不是 50 條具體技能名。每個 SKILL.md 是單檔案即定義(帶 frontmatter),搭配 skills/<category>/<skill>/references/ 的子檔案做按需載入,token 不會一次性爆。

bundle 是另一層封裝:把多個技能用一個 slash 命令載入,因為「後端開發」這種場景要同時掛上 code review、TDD、PR 三個技能,逐個 /skill 太碎。

關鍵檔案

  • skills/ 目錄 — 按領域分組(apple、computer-use、research、software-development、yuanbao…),每個技能長這樣:
skills/
├── my-skill/
│   ├── SKILL.md           # 主指令(必需)
│   ├── references/        # 支撐文件
│   │   ├── api.md
│   │   └── examples.md
│   ├── templates/         # 輸出模板
│   └── assets/            # 附件(agentskills.io 標準)
└── category/
    └── another-skill/
        └── SKILL.md

SKILL.md 頂部是 YAML frontmatter(name/description/version/platforms/prerequisites…),下面是正文指令。name 限 64 字元、description 限 1024,這兩個欄位是 progressive disclosure 第一層 skills_list 唯一回傳的內容,保 token。

  • skills_tool — 把技能作為工具暴露給主迴圈。它註冊了兩個工具:
python
registry.register(
    name="skills_list",
    toolset="skills",
    schema=SKILLS_LIST_SCHEMA,
    handler=lambda args, **kw: skills_list(
        category=args.get("category"), task_id=kw.get("task_id")
    ),
    check_fn=check_skills_requirements,
    emoji="📚",
)

registry.register(
    name="skill_view",
    toolset="skills",
    schema=SKILL_VIEW_SCHEMA,
    handler=_skill_view_with_bump,
    check_fn=check_skills_requirements,
    emoji="📚",
)

skills_list 只回傳 name + description + category(第一層 progressive disclosure);skill_view 載入完整 SKILL.md(第二層);reference/template 等支撐檔案按需 skill_view(name, file_path="references/api.md") 拉(第三層)。_skill_view_with_bump 在成功後呼叫 bump_view / bump_use 更新使用計數,curator 的 stale 計時器據此清理沒人用的技能。

  • skill_manager_tool — 技能管理(列表/查看/啟用)
  • skills_hub — 技能中心同步(agentskills.io 相容)
  • skills_sync — 本地與遠端技能同步
  • skill_bundles — 技能束打包,注入到提示 (prompt)。bundle 是 ~/.hermes/skill-bundles/*.yaml 裡的小檔案:
yaml
name: backend-dev
description: Backend feature work — code review, testing, PR workflow.
skills:
  - github-code-review
  - test-driven-development
  - github-pr-workflow
instruction: |
  Optional extra guidance to inject above the skill bodies.

/<bundle-name> 呼叫 build_bundle_invocation_message 把所有成員技能的 SKILL.md 拼進一則 user message。bundle 與 skill 同名時 bundle 優先——使用者顯式起了同名就是想覆蓋那條碰巧撞名的技能。缺失的成員技能不報錯,只在結果裡附「哪些被跳過」的提示。

  • skill_preprocessing — 技能內容預處理。負責替換 ${HERMES_SKILL_DIR} / ${HERMES_SESSION_ID} 模板變數,以及執行 !date +%Y-%m-%d`` 這種內嵌 shell snippet。內嵌 shell 失敗回傳 [inline-shell error: ...] 標記而不是拋例外,一個壞 snippet 不會拖垮整條技能訊息。
  • 技能節點與邊:125-193build_skill_nodes / build_edges,把技能組織成學習圖

資料流

  1. 啟動期 skill_preprocessing(agent/skill_preprocessing.py)掃描 skills/<category>/,讀 frontmatter。
  2. skill_bundles(agent/skill_bundles.py)把相關技能打包,經 build_turn_context:268 注入本輪提示。
  3. provider 決定呼叫某技能 → tool_call skillstools/skills_tool.py 載入並執行該技能的流程。
  4. 執行結果回填主迴圈。
  5. 學習閉環在背景審視本輪,可能:

邊界與失敗

  • 路徑穿越:skill name 會被拼接到 ~/.hermes/skills/ 上找檔案,_skill_lookup_path_error 拒絕 .. 段、絕對路徑、Windows 磁碟代號。否則 name="../outside" 能讀到 skills 目錄之外的檔案。
  • prompt 注入:SKILL.md 內容裡有「ignore previous instructions」「system prompt:」「]]>」等模式會被 _INJECTION_PATTERNS 標記。第三方技能(從 hub 同步的)是不可信內容,主迴圈載入時要 sanitize。
  • bundle 缺成員:build_bundle_invocation_message 對缺失/停用的成員技能只記到 missing / disabled 列表裡,不報錯——bundle 是寬容載入,少幾個不影響其餘技能。
  • 快取陳舊:掃描 skills/ 是 O(#dirs) stat,簽名包含目錄 mtime + disabled 集合 + 平台。但單檔案 SKILL.md 的就地編輯只 bump 自身 mtime,目錄簽名看不到,所以額外加了 30s TTL 兜底。

小結

技能 = 可演化的高階流程,frontmatter 描述、檔案即定義、學習閉環可改寫。它與工具的關係:工具是技能流程裡呼叫的原子,技能是「怎麼組合工具完成一類任務」的知識。技能的演化機制見學習閉環

非官方社群學習站,內容以 MIT 授權的 NousResearch/hermes-agent 原始碼為依據。