Hermes Agentのスキルはbundleでまとめて読む|同じslashはbundleが勝つ

Hermes Agentのスキルはbundleでまとめて読む|同じslashはbundleが勝つ

同じ名前のスキルを置いても、/lab-ship は bundle でした。resolve_bundle_command_key("lab-ship")/lab-ship を返し、スキル名の lab-review は None でした。

bundle はスキルを新たに入れません。skill-bundles の YAML が、すでに置いてあるスキルを 1 つの slash へ束ねます。2026 年 9 月 21 日、Hermes Agent v0.21.0 の一時 home で確認しました。本番の home は使っていません。

前回のリポ境界から、呼び方の束ねへ進む

前回の「Hermes Agentのリポ内スキルはtrustしてから読む」では、リポ内スキルをいつ索引へ載せるかを実測しました。今回は、すでに読めるスキルを、毎回並べて叩かない方法を見ます。

時点確認できる範囲
前回完了時リポ内スキルはパス付き trust のあとだけ索引へ載ります
今回開始時複数スキルを毎回 slash で並べる以外の呼び方が未確認です
今回完了後create、欠落のスキップ、同名スキルとの衝突、空 YAML の無視を区別できます

なぜ束ねるのかだけ知りたい場合は次の節まで読めば足ります。コマンドから進みたい場合は「一時環境を用意する」へ飛びます。起動メッセージの中身だけ見る場合は「起動時に載る文面」へ進みます。

なぜ毎回 slash を並べないのか

公式 docs は、先頭でスキルを最大 5 つまで並べられる、と書いています。毎回 /lab-review /lab-pr と打つと、順番も漏れもその場の記憶に依存します。

bundle は別名です。YAML 1 枚が slash 名になります。中のスキルは、プロファイルの skills/ か外部 directory に、先に実体が必要です。無い名前は、作った時点では止まりません。呼び出したときに飛ばします。

私は次の置き方にしています。

毎回使う事実            → Memory
単体の作業手順          → Skill
いつも同時に使う手順    → Bundle(YAML の別名)
リポだけの手順          → リポ内スキル(前回の trust)

公式は、bundle が prompt cache を壊さない、とも書いています。system prompt を書き換えず、そのターンのユーザーメッセージへ本文を載せます。私はここを、スキル本体を増やす場所だとは見ていません。

用語を揃える

用語この回での意味
bundle複数スキルを 1 つの slash に束ねる YAML です
slashCLI や gateway で使う /名前 です
skill-bundlesYAML を置く directory です。home 直下です
instruction束ねたスキルの前に載せる、使い方の一文です
欠落YAML にあるが、実体が無いスキル名です
衝突bundle とスキルが同じ slug になることです
.no-bundled-skills同梱スキルを流し込まない印です

呼び出したあとに何が起きるか

/lab-ship

    ├─ skill-bundles/lab-ship.yaml を読む
    ├─ 同じ slug のスキルがあっても bundle が勝つ
    └─ skills を順に解決する

            ├─ 実体がある → 本文を 1 通のユーザーメッセージへ載せる
            └─ 実体がない → 飛ばす。bundle 自体は失敗しない

create の表示は、YAML に書いた件数です。実体の有無は見ていません。実体は起動時に解決します。

一時環境を用意する

本番の Hermes home は使いません。同名の directory がある場合は上書きせず止めます。

LAB=/tmp/hibanas-skill-bundles-lab-20260921
[ ! -e "$LAB" ] || {
  printf 'already exists: %s\n' "$LAB"
  exit 1
}
mkdir -p "$LAB/skills"
export HERMES_HOME="$LAB"
touch "$LAB/.no-bundled-skills"

今回の実機は Hermes Agent v0.21.0 (2026.8.31) でした。version を先に読みます。

hermes --version

先頭は次のとおりでした。

Hermes Agent v0.21.0 (2026.8.31) · upstream baf7ceea · local 1068df60 (+1 carried commit)

空の一覧は終了コード 0 です。YAML が無いだけです。

hermes bundles list
No bundles installed yet. Create one with:
  hermes bundles create <name> --skill skill1 --skill skill2
Bundles directory: /tmp/hibanas-skill-bundles-lab-20260921/skill-bundles

.no-bundled-skills が無いと、空の home でも同梱スキルが流れ込みます。検査では手元の 2 件だけを見るため、印を先に置きます。

束ねる前にスキル実体を置く

bundle は実体を作りません。先に 2 件置きます。

mkdir -p "$LAB/skills/lab-review" "$LAB/skills/lab-pr"

cat > "$LAB/skills/lab-review/SKILL.md" <<'EOF'
---
name: lab-review
description: Use when reviewing a small lab change before a pull request.
---

# Lab review

Read the diff and list defects.
EOF

cat > "$LAB/skills/lab-pr/SKILL.md" <<'EOF'
---
name: lab-pr
description: Use when opening a lab pull request after review is done.
---

# Lab PR

Open a pull request with the reviewed change.
EOF

hermes skills list

表の本体は次の 2 行でした。hub は 0、builtin は 0、local は 2 です。

│ lab-pr     │          │ local  │ local │ enabled │
│ lab-review │          │ local  │ local │ enabled │

説明は 60 文字以内です。前回の新規作成と同じ制約です。

bundle を 1 枚作る

hermes bundles create lab-ship \
  --skill lab-review \
  --skill lab-pr \
  --description 'Lab review then open a pull request.' \
  --instruction 'Review first. Open the pull request only after review.'
Created bundle:
/tmp/hibanas-skill-bundles-lab-20260921/skill-bundles/lab-ship.yaml
  Invoke with: /lab-ship  (loads 2 skills)

実機の Created bundle: のあとは改行です。パスは次の行に出ます。終了コードは 0 です。

hermes bundles list
hermes bundles show lab-ship

一覧は 1 件、Skills 列は 2、説明は create で渡した文面です。show の本体は次のとおりでした。

/lab-ship  lab-ship
  Lab review then open a pull request.
  File: /tmp/hibanas-skill-bundles-lab-20260921/skill-bundles/lab-ship.yaml
  Skills (2):
    - lab-review
    - lab-pr
  Instruction:
    Review first. Open the pull request only after review.

YAML は 163 バイトでした。中身は次のとおりです。

name: lab-ship
skills:
- lab-review
- lab-pr
description: Lab review then open a pull request.
instruction: Review first. Open the pull request only after review.

対話セッションでは /lab-ship で呼びます。今回は CLI と Python で、同じ解決を見ます。

無いスキルは作った時点では止まらない

hermes bundles create lab-gap \
  --skill lab-review \
  --skill lab-missing \
  --description 'Includes a skill that is not installed.'

ここでも loads 2 skills と出ます。終了コードは 0 です。YAML は 102 バイトで、lab-missing が残ります。show も Skills (2) です。

実体の解決は起動時です。Install directory は hermes --version の該当行を使います。ユーザー名付きの絶対パスはコマンドへ埋めません。

install_dir=$(hermes --version | awk -F': ' '/^Install directory:/{print $2}')
"$install_dir/venv/bin/python" - <<'PY'
import os
os.environ["HERMES_HOME"] = "/tmp/hibanas-skill-bundles-lab-20260921"
from agent.skill_bundles import build_bundle_invocation_message
msg, loaded, missing = build_bundle_invocation_message(
    "/lab-gap", user_instruction="check the gap"
)
print("loaded", loaded)
print("missing", missing)
print("msg_len", len(msg))
print("HEAD")
print("\n".join(msg.splitlines()[:8]))
PY
loaded ['lab-review']
missing ['lab-missing']
msg_len 710
HEAD
[IMPORTANT: The user has invoked the "lab-gap" skill bundle, loading 1 skills together. Treat every skill below as active guidance for this turn.]

Bundle: lab-gap
Skills loaded: lab-review
Skills missing (skipped): lab-missing

User instruction: check the gap

create は 2 件、起動は 1 件です。飛ばした名前はメッセージに残ります。bundle 自体は落ちません。私は、未導入の名前を YAML に残したまま運用しません。show の件数と、起動時の loaded を別物として見ます。

同じ slug なら bundle が勝つ

mkdir -p "$LAB/skills/lab-ship"
cat > "$LAB/skills/lab-ship/SKILL.md" <<'EOF'
---
name: lab-ship
description: Use when shipping a lab change without loading a bundle.
---

# Lab ship skill

This is a skill with the same slug as the bundle.
EOF

hermes skills list

local は 3 件になります。lab-ship スキルも enabled です。bundle 側は変わりません。

"$install_dir/venv/bin/python" - <<'PY'
import os
os.environ["HERMES_HOME"] = "/tmp/hibanas-skill-bundles-lab-20260921"
from agent.skill_bundles import resolve_bundle_command_key
print("resolve lab-ship", resolve_bundle_command_key("lab-ship"))
print("resolve /lab-ship", resolve_bundle_command_key("/lab-ship"))
print("resolve lab-review", resolve_bundle_command_key("lab-review"))
PY
resolve lab-ship /lab-ship
resolve /lab-ship None
resolve lab-review None

引数は先頭スラッシュ無しです。/lab-ship を渡すと None になります。スキル名の lab-review も None です。公式 docs の「bundle が個別スキルに勝つ」は、この戻り値と一致します。同じ slash をスキル用に残したい場合は、bundle 名を変えます。

起動時に載る文面

同じ関数へ、存在する 2 件の bundle を渡します。

"$install_dir/venv/bin/python" - <<'PY'
import os
os.environ["HERMES_HOME"] = "/tmp/hibanas-skill-bundles-lab-20260921"
from agent.skill_bundles import build_bundle_invocation_message
msg, loaded, missing = build_bundle_invocation_message(
    "/lab-ship", user_instruction="refactor the auth middleware"
)
print("loaded", loaded)
print("missing", missing)
print("msg_len", len(msg))
print("HEAD")
print("\n".join(msg.splitlines()[:12]))
PY
loaded ['lab-review', 'lab-pr']
missing []
msg_len 1224
HEAD
[IMPORTANT: The user has invoked the "lab-ship" skill bundle, loading 2 skills together. Treat every skill below as active guidance for this turn.]

Bundle: lab-ship
Skills loaded: lab-review, lab-pr

Bundle instruction: Review first. Open the pull request only after review.

User instruction: refactor the auth middleware

1224 文字のあとに、各スキルの SKILL.md がそのまま続きます。instruction はスキル本文より前です。ユーザーの続きの文は User instruction です。system prompt 側は触りません。

キーは resolve が返す /lab-ship です。slug の lab-shipbuild_bundle_invocation_message へ渡すと、戻り値は None でした。

既存名は —force が無いと止まる

ここから先は、失敗する CLI だけ見たい場合の節です。

hermes bundles create lab-ship --skill lab-review
echo "dup_exit=$?"
hermes bundles show no-such
echo "show_missing_exit=$?"
Bundle already exists at
/tmp/hibanas-skill-bundles-lab-20260921/skill-bundles/lab-ship.yaml
Pass --force to overwrite.

重複の終了コードは 1 です。Created bundle: と同様、パスの前で改行されます。

Bundle 'no-such' not found.

無い名前の show も終了コード 1 です。空の list が 0 なことと混ぜないでください。

上書きするときだけ --force を付けます。今回の検査では、元の 2 件へ戻してから測っています。

空の skills は一覧に出ない

手書き YAML の落ち方だけ見たい場合の節です。

cat > "$LAB/skill-bundles/lab-empty.yaml" <<'EOF'
name: lab-empty
skills: []
description: empty skills list
EOF

hermes bundles reload
hermes bundles show lab-empty
echo "show_empty_exit=$?"

reload は No changes. 2 bundle(s) loaded. でした。show は Bundle 'lab-empty' not found. で終了コード 1 です。ファイルは 58 バイト残ります。

venv の Python で build_bundle_invocation_message を読むと、先に次の 1 行が出ます。

Bundle /tmp/hibanas-skill-bundles-lab-20260921/skill-bundles/lab-empty.yaml has no skills list; skipping

空配列は、壊れた YAML としては扱いません。索引から外します。私は空の skills を置きません。

一時環境を片付ける

今回作ったパスだけを消します。別のパスなら止めます。

case "$LAB" in
  /tmp/hibanas-skill-bundles-lab-20260921)
    test -f "$LAB/skill-bundles/lab-ship.yaml"
    ;;
  *)
    printf 'unexpected LAB path\n' >&2
    exit 1
    ;;
esac

rm -rf -- "$LAB"
unset HERMES_HOME
test ! -e "$LAB" && printf 'cleanup: OK\n'

この cleanup は記事用の一時 home 向けです。本番 home では実行しません。

私は、同時に使う手順だけを bundle へ置きます。slash 名はスキルと被らせません。YAML の件数と、起動時の loaded がずれたら、欠落を先に直します。

よくあるエラー

症状原因対応
create が loads 2 skills なのに 1 件しか載らないcreate は YAML の件数だけを数えるためです起動時の loaded と missing を見ます
同じ slash でスキル単体が呼ばれない同じ slug では bundle が勝つためですbundle 名を変えます
resolve が None先頭スラッシュ付き、またはスキル名を渡しているためですslug だけを渡します
既存名の create が 1 で終わる--force が無いためです別名にするか、上書きするときだけ --force を付けます
空 YAML が一覧に出ないskills が空だと索引から外れるためです1 件以上の実名を書きます
本番の bundle が増えるHERMES_HOME を向けていないためです検査は一時 directory で行い、本番 home は使いません

出典

資料確認した内容
Hermes Agent Skills Systembundle の場所、YAML、欠落は致命ではないこと、同名では bundle が勝つこと、prompt cache を壊さないこと
Agent Skills 仕様SKILL.md の公開形式
一時directoryの実測YAML 163 バイトと 102 バイト、起動メッセージ 1224 文字と 710 文字、空 YAML 58 バイト、重複 create の終了コード 1
この記事をシェア