Claude Codeでskillを数十本と増えてきたところで、あんまり上手く適切なskillが起動しない感覚があった。
スキルというのはClaude Codeに手順書を持たせる仕組みで、SKILL.md に「何をするか」と「いつ使うか」を書いておくと、会話の流れからモデルが勝手に選んで起動してくれる。
はずだった。。。
skillsが増える程に、起動して欲しいスキルがあまり呼ばれていなくて、だいたい普通にファイルを読み書きして終わっていた。ということにClaudeを問いただして気付いた。
まず公式を読んだ
自分の勘で直す前に一次情報を読むようにしている。今回読んだのは3本。
嘘です、、、さらっと読んだだけでちゃんと読んでくれたのはClaude君です(ありがとう)
まずはdescription
overviewに、起動の判定に何が使われるかがはっきり書いてある。
The description is what Claude matches your request against when determining whether to trigger the Skill, so it must say both what the Skill does and when to use it.
(Agent Skills)
読み込まれるタイミングも決まっていて、起動前にcontextに乗るのは名前と説明文だけ。
At startup, only the metadata (name and description) from all Skills is pre-loaded. Claude reads SKILL.md only when the Skill becomes relevant, and reads additional files only as needed.
(Skill authoring best practices)
Claude Code側の説明も同じ。
In a regular session, skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked.
(Claude Code / Skills)
つまり検索もランキングも挟まらない。説明文を読んだモデルの判断だけで決まるということだと思う。
本数のせいではなさそう
数十本は多すぎるのかなと疑ったけど、公式の想定はもっと多かった。
The description is critical for skill selection: Claude uses it to choose the right Skill from potentially 100+ available Skills.
(Skill authoring best practices)
100本超から1本選ぶ前提で書かれているので、数の問題ではなさそう。(ってことはskillを探すskill以前の問題もきっとありそう...)
ただし長さには上限がある。
Put the key use case first: the combined description and when_to_use text is truncated at 1,536 characters in the skill listing to reduce context usage.
(Claude Code / Skills)
大事なことを先頭に書け、とわざわざ書いてある。
「上手く起動しないとき」についての記述は無さそう?
読んだ3本のどこにも、「スキルが起動しないときどうするか」という節は無かった(と思う)。代わりに示されているのは2つだった。
ひとつはdescriptionの書き方。三人称で書く、具体的な語を入れる、何をするかといつ使うかを両方書く。
Always write in third person. The description is injected into the system prompt, and inconsistent point-of-view can cause discovery problems.
(Skill authoring best practices)
もうひとつが評価と観察。こっちが自分には刺さった。
Create evaluations BEFORE writing extensive documentation. This ensures your Skill solves real problems rather than documenting imagined ones.
(Skill authoring best practices)
スキルを配ったあとに聞くべき問いも、具体的に書かれている。
Ask: Does the Skill activate when expected? Are instructions clear? What's missing?
(Skill authoring best practices)
Iterate based on these observations rather than assumptions.
(Skill authoring best practices)
descriptionの書き方のほうは、多分割とちゃんとやっていたと思う。やっていなかったのは、観察する方だった。
計測してみる
「意図したスキルが発火しない」を、「選べない」のか、「選びにいかない」のか、の2つに分けて測った。
| |
測り方 |
結果 |
| 識別 |
「この発話にどのスキルを使う?」と聞く |
ほぼ取り違えない |
| 自発起動 |
発話をそのまま渡して起動するか見る |
半分強しか起動しない |
聞けば当たる。聞かなければ起動しない。
外したケースを見に行ったら、スキルを使わずにファイルを直接読み書きして作業を終えていた。descriptionが読めていないんじゃなくて、着手する前に「使えるものがあったかな」と確かめる段階がそもそも無かった。ということなのだろう。
これで、descriptionをいくら磨いても動かない理由に辿り着けた。聞けば選べるなら、判断の材料は足りている(はず)。足りないのは探しにいく動作の方だ。
スキルを探すスキルを作った
作ったのは skill-find というスキル。中身は手順だけで、選ぶ基準は持たせていない。
- 会話を起点に発火して、スキルの置き場を実際に一覧して、今あるものを確かめる
- 依頼の語とその言い換えで、各スキルの「いつ使うか」を検索して候補を集める
- 候補の「使わない場面」「〜ならこっち」の行を読む
- skillを起動する
起動時に読み込まれた説明文は記憶であって実体じゃない。スキルは増えるし、文字数で切られる以上、一覧に全文が載っている保証もない。だから毎回、実際にファイルを読ませる。
検索は候補を漏らさず拾うための網であって、選ぶ手段じゃない。一致した数が多い順に採らせないようにした。公式が「選ぶ材料はdescription」と書いている以上、その上に自前の採点を重ねてもノイズが増えるだけだと思う。
あと、該当が無かったらそのことを1行だけ言って普通に作業を進める、と書いた。これを書いておかないと「該当するスキルがありませんでした」と報告して止まる。止まられても困るので....
同時に起動するのは1本だけにしている。これは Claude Code の仕様の都合で、起動したスキルの本文は会話にそのまま残り、あとから読み直されない。
When you or Claude invoke a skill, the rendered SKILL.md content enters the conversation as a single message and stays there across later turns...Claude Code does not re-read the skill file on later turns.
(Claude Code / Skills)
2本分の手順が並んだまま残ると、どっちに従っているのか曖昧になる。なので直列に通す。取り込んでからリンクを張る、みたいに2本要る依頼は当然あるので、そのときは残りを先に書き出してから1本目を起動して、終わったら通し直す。
作っただけでは起動しなかった
で、skill-findを作ってから数日、それ自体も結局あんまり起動しなかった。
「使う前にskill-findを通してね」とルールに書いても、自分で「これは明らかにあのスキルだ」と思った場面では通らない。その「明らかに」が当てにならないから作ったはずなんだけどなー
なので門を置いた。スキルが起動する直前に走る検査(PreToolUseフック)を入れて、skill-findを経由していない起動を止めるようにした。
止まりっぱなしになると困るので、逃げ道を3つ入れてある。
- skill-find自身はいつでも通す。止められてもskill-findを起動すれば必ず先に進める
- 同じスキルを続けて止めたら通す。判断が合っていたのに止め続けられるのは邪魔なだけ
- 検査自体がエラーになったら素通しする。仕組みの不具合で作業が止まるのが一番よくない
これでようやく通るようになった。
門にも穴があった
ここまで作ってから、まだ抜けがあることに気づいた。
この門が効くのは、スキルを起動しようとした瞬間だけ。2本目を呼ぼうとすれば止まるけど、呼ぶこと自体を忘れたら何も起きない。取り込んでからリンクを張る、みたいに2本要る依頼で、1本目が終わった時点で満足して終わるパターンが残っていた。
skill-findの手順には「残りを先に書き出してから1本目を起動する」と書いてあるけど、書き出した予定を後で実行するかどうかは、結局こちらの継続性に委ねられている。それはさっき「当てにならない」と結論づけたものそのものだ。
なので、会話を終える直前にもう1つ検査を置いた。残りを書き出すときの形を決めておいて、それが消化されていなければ会話を終わらせない。
PENDING-SKILLS: hoge-skill, fuga-skill
1本目の結果を見て2本目が要らなくなることもあるので、PENDING-SKILLS: none と書けばその場で取り下げられる。止まるのも1回だけにしてある。
仕組みを足すと、その仕組みの穴が次の課題になる。この対応もめっちゃ良いとは思ってはない。
学びや気付きなど
今回は「選べるか」と「選びにいくか」が別の問題だった。公式のチェックリストも、説明文の質と "Does the Skill activate when expected?" を別々の問いとして置いている。
もう一つは、ルールに書くことと、守られる経路に置くことは全然違うんだなと思った。ルールに1行足しただけではダメな場合もあって、起動の直前に検査/門を置いて改善できた。
改善自体も生成AI先生でする
実はこういう仕組みは、Claude先生自身に作ってもらってClaude先生自身にメンテさせている。
この前提だと、最初はメンテが大変なのだが、段々と噛み合ってきて良い感じになる気がしている。
AIに作らせてAIにメンテさせているので、そこまで工数をとっている訳でもない。この仕組みを持続するための工夫は、実行記録。
どういう経緯で何をして、実際運用してどうだったのかを残してあるので、それをベースにして定期的にAIに改善活動をしてもらっている。下手に人力でファイル修正などをしてコンテキストが失われるのは良くないので基本すべてClaude先生との対話を通してFBや改善活動をしている。