前回(AIを「地頭が良く自信過剰な新人」として扱ってみた)で、AIは経験を蓄積できないから、経験で覚えるはずだったことを外部に明文化する必要がある、と書きました。その「明文化」を支える仕組みが、ハーネスと呼ばれるものです。

便利なので、つい作り込みたくなります。でも、ハーネスを作ること自体が目的になってしまうと、本末転倒だなと感じています。今回は、ハーネスとどう付き合うかを整理しておきます。

ひとつ前提として置いておきたいのは、「失敗しないエージェント」を作るより「失敗から立ち直れるエージェント」を作るほうが現実的ということ。AIは確率的に間違えますし、長い文脈で手順が抜けることもあります。完璧を目指すより、間違えても気付いて直せる仕組みを作るほうが、結果的にうまく回る気がしています。

ハーネスとは

広く言えば、AIを取り巻くスキャフォールディング全体── システムプロンプト、ツール、実行環境、設定ファイル── を指す言葉として使われています。

Claude Codeに限って言えば、主に3つのレイヤーがあります。

  • CLAUDE.md: プロンプトに毎回読み込まれる指示
  • skills: 必要なときに発火する手順書
  • hooks: イベント時に機械的に実行される仕組み

これらに、ツール権限の設定(settings.json)やMCPサーバーなども加わりますが、まずはこの3つの使い分けが肝かなと思います。

なお、「ハーネス」という言葉は、広い意味(skillsを含む全体)で使われたり、狭い意味(skillsと区別したガードレールや基盤部分)で使われたりします。この記事では基本的に広い意味で使っていますが、後半で「下限を上げる仕組みと上限を上げる仕組み」を分けて語る場面では、狭い意味でも使います。文脈で読み分けてください。

強制力の階段

3つの違いを、強制力の強さで見ると分かりやすいです。

仕組み 性質 強制力
CLAUDE.md 自然言語の指示 弱(確率的)
skills 必要時の知識注入 中(発火すれば効く)
hooks 機械的な実行 強(確実)

CLAUDE.mdに「必ず」と書いても、確率を上げるだけで100%ではありません。skillsはそもそも発火するかがモデル判断。hooksは確実に実行されますが、柔軟性は失います。

なので使い分けの基本は、「毎回伝えたいか、特定のときだけか」と「指示で足りるか、強制が必要か」の2軸で考えると整理しやすいかなと思います。

  • 毎回伝えたい、指示で守ってもらえれば足りる → CLAUDE.md
  • 特定のタスクのときだけ濃く効かせたい → skills
  • 守られないと事故になる、強制したい → hooks

下限を上げるか、上限を上げるか

強制力とは別の切り口で、何のための仕組みかで分けることもできます。

ハーネス(狭義)は、品質の上限ではなく下限を上げる装置です。事故や失敗を防いで、最悪の結果を底上げする。AIの出力を「壊れない範囲」に自動で収束させる、制約と検証の仕組み、と言ってもいいかもしれません。
ただし、下限が上がることで、平均品質は大きく改善する。これがハーネスを書く価値の本体だと思っています。

一方、skillsは天井を上げうる装置。良い方向へ導く役割を担います。Railsの良い書き方、テストの書き方、PRの書き方── こういうノウハウがskillsに溜まっていくと、AIの「良いときの結果」が伸びる。

CLAUDE.mdは両方の役割を持つことが多いです。やってはいけないことも、推奨される書き方も書ける。

意識すると整理しやすいのは、この2つは性質が違うということ。下限を上げる仕組みは「事故が起きたら困る」発想で、安全側に倒すのが基本。上限を上げる仕組みは「もっと良くしたい」発想で、過剰に書くと逆効果になることもあります(古いベストプラクティスが新モデルの邪魔をするなど)。

ハーネスの4機能

ハーネスの中身をもう少し分解すると、4つの機能に分けられそうです。

  1. Inform(通知): 何をすべきか、何をしてはいけないかを伝える
  2. Constrain(制約): できないようにする、選択肢を絞る
  3. Verify(検証): アウトプットが正しいかチェックする
  4. Correct(修正): 失敗を検知して直す、フィードバックループを回す

CLAUDE.mdは主に1(Inform)と少しの2(Constrain)を担います。「こうしてください」「これはやらないでください」を伝える。前提が絞られるので、品質の下限が上がる。

2以降(Constrain、Verify、Correct)は、運用しながら育てていく領域です。私の場合、skillsに「Specでカバレッジを上げる」を入れたので、検証と修正が自動で回るようになりました。RuboCopも同じ発想です。lintで検出して、AIに直させる。

「失敗から立ち直れるエージェント」というのは、要するにこの4機能、特にVerifyとCorrectのループが回っている状態のことかなと思います。完璧を目指すのではなく、間違えても気付いて直せる設計。

いずれは検証・修正をhooksで繋げた方が強制力が働くので良いのかなと思いつつも、現状CLAUDE.mdとskillsで回っているので急いではいません。

CLAUDE.mdに書くこと

毎回読まれる前提で、そのプロジェクトで作業する人(AI)が知っておくべきことを書く場所です。
私が今書いているのは、こんな項目です。

  • 言語、フレームワーク、ミドルウェア、外部連携先
  • 開発環境、よく使うコマンド
  • ファイル構成、ルーティング、データベース、テストデータの場所
  • 共通のコーディング規約(言語固有のものはskills側)
  • ドメインの概要(詳細は別ファイルに分ける)
  • やってはいけないこと
  • タスク完了の定義
  • 学習を関連skillに追記するルール

「新人エンジニアに渡すREADMEとオンボーディング資料」のイメージです。読めば理解して大半は従ってくれるけど、強制力はない。
注意したいのは、「絶対に」「必ず」を多用しすぎないこと。全部が最重要だと、優先順位が付けられなくなって、結局効きが悪くなります。

skillsに書くこと

特定のタスクが来たときに発火する、手順書とノウハウの集まりです。
私が用意しているのは、こんなものです。

  • git-commit、create-pr、update-pr のような定型操作
  • rails、rspec、nuxt、github-actions のような技術スタック別のベストプラクティス

CLAUDE.mdとの違いは、毎回読まれるか、必要なときだけ読まれるかです。Railsの細かい作法をCLAUDE.mdに書くと、Nuxt関連のタスクのときも毎回読まれて無駄になります。skillsに分けておけば、Railsのタスクのときだけ濃く効きます。

skillsはAIに書かせて、私はレビューするだけにしています。気をつけてレビューしているのは、descriptionが適切に書けているか。これが適切でないと、必要なときに発火しません。「いつ使うべきか」が描写の中で明確になっているかが鍵です。

ハーネス自体をAIに書かせるのは、ハーネス作りが目的化しないためにも有効かなと思っています。手を動かす時間を最小化しつつ、レビューで質は担保する。

hooksに書くこと

機械的に実行される仕組みなので、ここに置くのは「指示で守られないと困るもの」だけにしています。
候補としてあるのは、こんなものです。

  • 危険コマンド(rm -rfなど)の実行前確認
  • 機密ファイル(.env、*.keyなど)の読み取り・コミット禁止
  • git push –force の確認
  • 編集後の自動lint、自動テスト

私はまだhooksをほとんど使っていません。理由は、現状CLAUDE.mdとskillsで困っていないから。事故が起きてヒヤッとしたら、そのときにhooksに格上げする予定です。
最初からhooksで縛りすぎるのは過剰設計だと思っています。柔軟性を奪うので、本当に必要な部分だけに使う。

どこに置くか

設置場所は、誰と共有したいかで決まるかなと思います。

個人開発: グローバル(ローカルマシン全体で共通)に置く

~/.claude/CLAUDE.md~/.claude/skills/ に置いています。プロジェクトをまたいで使い回せる内容(個人の好み、よく使う言語のベストプラクティスなど)はここに集約。

最初は ~/.claude/projects/-Users-xxx-yyy-zzz/ の下(プロジェクト固有の場所)に書かれていることもありましたが、プロジェクト依存ではないskillだったので、グローバルに移動してもらいました。AIに「これはプロジェクト固有じゃないから、グローバルに移して」と頼めば、移動してくれます。

業務(チーム共有): リポジトリ内に置く

<project>/.claude/CLAUDE.md<project>/.claude/skills/ に置いて、リポジトリにコミットしています。これでチームメンバー全員が同じハーネスでAIを使える。

業務のCLAUDE.mdをグローバル(自分のローカルマシン)に置くと、自分しか恩恵を受けません。ハーネスは資産なので、チームで共有するのが基本かなと思います。コードレビューでハーネスも見直せる、という副次的な効果もあります。
これも、CLAUDE.mdに「チームで共有すべき内容はリポジトリ側に書く」というルールを入れておけば、AIが適切に書いてくれます。

業務(プロダクト横断、会社全体): 別リポジトリ + settings.jsonで参照

複数のプロダクトで共通して使いたいハーネス(会社共通のコーディング規約、社内ツールの使い方、セキュリティガイドラインなど)は、専用の別リポジトリに置く方法を検討中です。

各プロダクトの settings.json から、そのリポジトリを参照するように設定する。これで「会社共通のルール」を一元管理しつつ、「プロダクト固有の事情」はリポジトリ内のCLAUDE.mdで補える、という二層構造になります。

これがうまく回ると、新しいプロダクトを立ち上げるときも、最低限のハーネスがすぐ揃う。

ローカル専用にしたい設定(個人の検証用、機密情報を含むもの)は、.local.json のような形でgitignoreに入れる選択肢もあります。

学習を蓄積する仕組み

前回も書きましたが、私がやっている運用として、指摘が終わった後に「学習できることはありましたか?」と聞くようにしています。

これでAIが気付きを言語化して、関連するファイルに追記してくれます。CLAUDE.mdに以下のようなルールを書いておけば、自動でskillsなどに溜まっていきます。

- 学習(フィードバック保存)の際は、メモリファイルだけでなく、関連するスキルファイル(`.claude/skills/`)、`CLAUDE.md`、`.github/copilot-instructions.md`、`.coderabbit.yaml` にも追記する

CLAUDE.mdだけでなく、他のAIツール(GitHub Copilot、CodeRabbitなど)の設定ファイルも一緒に更新してもらえるので、複数のAIで一貫した挙動になります。

そして、指摘をskillsに学習させ、リポジトリに入れているので、ハーネスの更新サイクルが回っている状態になります。気付きが個人の頭の中に留まらず、チーム全員のAIに反映される。Verify(検証)で見つかった問題が、Correct(修正)を経て、Inform(通知)に戻ってくる感じです。

ハーネスを最初から完璧に作る必要はなく、運用しながら育てていくという発想です。気付きや、事故が起きたとき、ヒヤッとしたとき、その都度追加していく。
これは新人の指導でも同じだと思います。最初から完璧なマニュアルを渡すのではなく、現場で気付いたことをマニュアルに追記していく。

ガードレールについて

ローカル開発でも、いくつかのガードレールは意識しておきたいです。事故ってからでは遅い領域があるので。

優先度高め:

  • 機密ファイルの読み取り・コミット禁止
  • git push –force の確認(チーム開発で特に重要)
  • マイグレーションのrollback確認

中くらい:

  • 環境を変更するコマンド(npm install -gなど)の確認
  • gitのconfig変更
  • ビルド成果物への直接編集

これらをCLAUDE.mdに書くか、hooksに置くかは、事故の重大さ次第です。「やらないでください」で済むものはCLAUDE.md、「物理的に止めたい」ものはhooksです。

ガードレールが多すぎると、モデルの注意が分散して効きが悪くなったり、ルール遵守を優先して本来の良い判断を放棄したり、CLAUDE.mdが肥大化して大事な情報が埋もれたり── 結果として「安全だけど凡庸」な出力になりがちです。
新人にマニュアルを100ページ渡したら、新人は萎縮して凡庸な仕事しかできなくなる、というのに似ています。

ハーネス作りが目的にならないように

ここが一番大事かもしれません。
ハーネスを書く作業は、それ自体が楽しいです。整理すると気持ちいいし、仕組みが整うと達成感がある。何より、自分でコントロールできる作業なので、AIの出力品質を上げる(コントロールが難しい)より手応えがあります。

でも、ハーネスを作り込むのに時間を使った結果、本来やるべき仕事の成果が出ないのでは、本末転倒だなと思います。

気をつけたいパターン:

  • 過剰設計: 起きてもいない事故を全部防ごうとして、ガードレールを増やしすぎる
  • 早すぎる最適化: モデルがやがてできるようになることを、先回りして補おうとする
  • メンテされない遺産: 作ったまま使われていないskillが残り続ける
  • コレクター化: 「skillが10個できた」を成果と勘違いする
  • 評価なき改善: 効果を測らずに作り込み続ける

本来の目的は、AIで良いアウトプットを出すこと、そしてその先の仕事の成果です。ハーネスはそのための手段にすぎません。

最小構成から始めて、必要になったら追加する。定期的に棚卸しして、使われていないものは消す。「ハーネスの完成度」より「AIの出力品質」を見る。

書く作業自体もAIに任せて、自分はレビューに徹する。それくらい肩の力を抜いた付き合い方の方が、長続きするのかなと思います。

チームでハーネスを展開するときも、内容によっては意見が分かれることがあります。少人数なら、議論しすぎずにどんどん入れて運用で淘汰するのが合理的かもしれません。使われないものは消えていきますし、合わないものは指摘で直っていきます。

新人にマニュアルを渡すのも、本来は新人が良い仕事をするためのはずです。マニュアル作りが目的になったら本末転倒。同じことかなと思います。

モデルが進化したら

モデルがバージョンアップすると、ハーネスの一部は不要になることもあります。「いきなりコード書かずに計画を立てて」みたいな能力補完のためのパッチは、モデルが賢くなれば緩めても大丈夫になるかもしれません。

一方、ドメイン知識、コーディング規約、安全のためのガードレール── これらはモデルに依存しない価値を持つので、新モデルでも残せます。

なので、モデルが変わったときは「全部作り直し」ではなく、「少し棚卸ししてみる」くらいの感覚かなと思います。大半はそのまま使えますが、たまに「あ、これもう要らないかも」というのが出てくる。それを見つけて整理する程度の作業です。
これも、最初から作り込みすぎていなければ、棚卸しの手間も少なく済みます。

まとめ

ハーネスは、AIに経験を持たせるための仕組み。3層に分けて、強制力に応じて使い分ける。

  • CLAUDE.md: プロジェクトの文脈と作法
  • skills: 特定タスクの手順書
  • hooks: 守られないと困るものの強制

書くときの判断軸は、「毎回必要か、特定のときか」と「指示で足りるか、強制が必要か」。設置場所の判断軸は、「誰と共有したいか」。

そして一番大事なのは、ハーネスを作ることが目的にならないこと。ハーネス作りに時間を使いすぎて、本来の仕事の成果が出ないのでは本末転倒です。最小から始めて、運用しながら育てる。書く作業自体もAIに任せていい。

これも振り返ってみると、特に新しい話ではないなと感じます。ドキュメントを整備する。チェックリストを作る。危険な操作には鍵をかける── いつものエンジニアリングと同じです。

違いがあるとしたら、3つあるかなと思います。

  • ループが早い: 指摘が即座にハーネスに反映され、次のタスクから挙動が変わる
  • 知識が共有できる: ハーネスをコミットすれば、チーム全員のAIが同じように振る舞う
  • 再現性がある: 暗黙知ではなく明文化されたルールなので、誰が作業しても同じ結果になりやすい

道具がAIになっても、付き合い方の基本はあまり変わらない。ただ、ループの速さと共有のしやすさが、エンジニアリングの仕方を少し進化させているのかな、という感覚があります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です