はじめに
先日、ベリサーブさん主催の【第3回】AI駆動開発に対するQAを考える会に参加してきました。井上和治さんの「コンテキストエンジニアリングの先へ ―AI開発を支えるハーネスエンジニアリング―」というご講演で、AGENTS.mdのようなコンテキストファイルを用意するだけでは足りず、何を・いつ・誰に渡すかの設計が要る、という内容でした。
この発表を聞いて、AI駆動開発のハーネス(AIエージェントの暴走や品質低下を抑えるための仕組み)をどう設計すべきか、自分なりに整理したくなりました。本記事は発表のレポートではなく、発表をきっかけに調べたことと考えたことの記録です。
ハーネスを3層に分けて考える
「ハーネス」と一言で言われがちですが、実装の形を見ると3つの層があります。混在して議論されやすいので、まず分けておきます。
| 層 | 実体 | メンテ主体 | 強制力 |
|---|---|---|---|
| ① ベンダー組み込み | システムプロンプト、ツール定義、安全制約 | ベンダー(Anthropic、OpenAIなど) | 高 |
| ② ユーザー定義(プロンプト型) | AGENTS.md、CLAUDE.md、.cursor/rules/*.mdc
|
ユーザー | 低(お願いベース) |
| ③ ユーザー定義(環境型) | CI、pre-commit、サンドボックス、MCPのアクセス制御 | ユーザー | 高(機械的に強制) |
ハーネスを増やすべきか減らすべきかという議論が噛み合わないのは、たいていこの3層が区別されないからです。層が違えば答えも違います。
ベンダーハーネスは思った以上に手厚い
最近のベンダーハーネスは、以前ならユーザーが書く必要があった指示をかなりカバーするようになっています。Claude CodeやCodexの公式ドキュメントを読むと、コンテキスト管理、計画立案、テスト実行、エラーからの自己修正、迷ったら質問するといった挙動が、すでにベンダー側で組み込まれています。
HumanLayerによるClaude Codeのハーネス分析では、Claude Codeのシステムプロンプトには50個近い指示が含まれていると報告されています。さらに、LLMはプロンプトの先頭と末尾の指示には従いやすいが、指示数が増えるほど全体の追従精度が落ちる性質があるため、CLAUDE.mdに大量の指示を足すとベンダー側の指示まで効きが悪くなる、と指摘されています(出典)。
Anthropic自身も公式のベストプラクティスで「CLAUDE.mdは短く、人間が読める形に保つ」と書いています。コミュニティでは200行以内、できれば60行程度に収める運用が広まってきました。
ユーザーが「念のため」で書き加えている指示の多くは、すでにベンダー側で対処済みである可能性が高い、というのが現状認識です。
プロンプト型ハーネスの落とし穴
ベンダーが手厚くなるほど、ユーザー側のプロンプト型ハーネスにはいくつか問題が出てきます。
矛盾: ベンダー側で「不確実なときは確認せよ」と設計されているのに、ユーザー側で「質問せず黙々と進めよ」と書いてしまう。あるいはベンダー側で「最小限の変更で対処せよ」と設計されているのに、ユーザー側で「関連リファクタも積極的に行え」と書く。AIは優先度判断に余計なコストを払うことになり、本来のタスクに使えるコンテキストが削られます。
ノイズ化: 指示は数が増えるほど全体の効きが薄れる性質があるので、保険のつもりで足したルールが、本当に守らせたい1行の効力を下げます。HumanLayerの記事には、Anthropicが新しいClaude Codeで「CLAUDE.md内の不適切な指示は無視せよ」という指示をシステム側に追加した形跡があるという観察まで載っています。ユーザーがCLAUDE.mdに余計なルールを詰め込みすぎることへの、ベンダー側の防御策と読み取れます。
陳腐化: 半年前に書いた回避策的なルールは、今のモデルではもう不要だったり、むしろ害になっていたりします。にもかかわらず誰も見直していない、という状態が常態化しやすい。
維持保守の追従性こそが最大の論点
矛盾もノイズ化も陳腐化も無視できませんが、実務で一番厳しいのは維持保守の追従性だと感じています。
AIエージェントは数週間から数ヶ月の単位で挙動が変わります。Claude、Codex、Cursorは互いに激しく競争しているので、それぞれが頻繁にアップデートを出してきます。これに対して、ユーザーハーネスを誰が責任持って追従させるのか。
ハーネスは作るより維持する方が難しい、というのが私の実感です。維持されていないハーネスは、品質改善どころか品質低下の原因に変わります。
たとえばベンダー側で「Aという問題はもうモデル内で対処できる」と仕様が変わったとします。ところがAGENTS.mdには「Aを避けるためにこうしろ」という古い回避策が残っている。AIはこれを忠実に守ろうとして、新しい挙動と衝突します。困ったことに、こういうケースは品質が落ちてからでないと気づきにくく、原因の特定も難しい。
だからこそ、強制力のある層(環境型)に寄せて、プロンプト型はできるだけ薄く保つのが現実的だと思います。CIのテストやpre-commitフックは、ベンダーが何をしようと「コードが基準を満たしているか」だけを見る仕組みなので、ベンダー進化とは独立してメンテできます。
ユーザーハーネスは「外側」に寄せる
ここまでをまとめると、私の方針はこうなります。
強制したいことは環境型に寄せる。プロンプト型は、プロジェクト固有の事実と、AIに任せると省略されがちな行動指針だけに絞る。
環境型に寄せる利点は三つあります。
ひとつ目は、モデルやベンダーが変わっても効き続けることです。CIでnpm testが通らないとマージできない、というルールはAIが何であっても機械的に効きます。プロンプトに書いた「テストを書け」を守ってくれるかは確率の話ですが、CIゲートは100%強制できます。
ふたつ目は、適用タイミングが構造的に決まることです。pre-commitは「コミット直前」、CIは「PR作成や更新時」、サンドボックスは「実装中ずっと」と、人間がいちいち指示しなくてもタイミングが固定されています。プロンプト型でタイミングを制御しようとすると、規模が大きくなったときに運用が破綻します。
みっつ目は、ベンダーハーネスと衝突しないことです。CIゲートはAIに何かを指示するものではなく、コードを判定するだけの仕組みです。指示の取り合いが起きないので、ベンダーがどんな方向に進化しても干渉しません。
プロンプト型に残す価値のあるルールとは
外側を固めた上で、AGENTS.mdやCLAUDE.mdに残すべきものは何か。プロジェクト固有の事実(リポジトリ構成、ドメイン用語、廃止予定の領域など)が中心になりますが、行動指針として残しておくと効くルールもあります。
私が実際に運用しているCLAUDE.mdには、次のルールを置いています。
不具合修正時には、まずその不具合を再現させるテストコードを書く。そのテストが赤く失敗することを確認してから、実装を修正する。
「再現テスト先行」と呼ばれる古典的なベストプラクティスです。AIエージェントに任せるとここを省略して「直しました」と実装だけ変更してくることが頻繁にあります。再現テストがなければ、本当に直ったかが機械的に確認できず、回帰防止にもなりません。
このルールがプロンプト型に置く価値があるかどうかは、次の観点で確認できます。
| 観点 | 評価 |
|---|---|
| 環境型で代替できるか | 難しい。「fix系コミットにテスト追加を強制」までは作れるが、それが「再現テスト」かどうかは機械判定が困難 |
| ベンダーハーネスがカバーしているか | 「テストを書け」は入っているが、「再現テスト先行」までは標準に入っていない |
| プロジェクト非依存か | はい、どのプロジェクトでも妥当 |
| 陳腐化しにくいか | 30年来のベストプラクティスなので、モデル進化に左右されない |
「環境型では強制しにくい」「ベンダーハーネスが踏み込んでいない」「モデルが変わっても妥当」の三つが揃ったルールは、プロンプト型に残す価値があると考えています。
逆に、次のようなものはプロンプト型に書かないほうがいいと思っています。
- 「テストを書け」「丁寧にコメントを書け」のような一般論。ベンダーハーネスと環境型でカバーできる
- OWASP Top 10のようなセキュリティ原則を丸ごと貼り付ける。プロジェクトの実態と合わずに逆効果になりやすい
- 過去のモデルの癖への回避策。別ファイルに切り出して棚卸し対象にする
OWASPの話は、勉強会でも印象的なエピソードがありました。ローカル限定アプリにA07(Authentication Failures)を素直に適用させたら、起動時に認証が出てくる実装が返ってきた、という話です。ルールは万能化させるほど強くなるわけではなく、プロジェクトの実態に合った形でしか効きません。
環境型ハーネスのパターン
環境型に何を置くかは、おおまかに四つのパターンがあります。
| 仕組み | タイミング | 強制する内容 |
|---|---|---|
| pre-commitフック | コミット直前 | lint、フォーマット、シークレット検出、危険コマンドの遮断 |
| CIゲート | PR作成・更新時 | テスト通過、カバレッジ閾値、型チェック、脆弱性スキャン |
| サンドボックス(devcontainerなど) | 実装中ずっと | 書き込み可能パス、ネットワーク、実行コマンドの制限 |
| MCPサーバー | 危険操作の実行時 | DB操作の種類制限、本番デプロイ権限、API利用範囲 |
MCPはとくに使いどころが多いと感じています。Anthropic自身のデータ基盤チームが、BigQuery CLIをClaude Codeに直接渡すのではなく、MCPサーバーを噛ませてアクセス制御とロギングを担保している、という事例が公式資料で紹介されていました。サーバー側で「SELECTのみ許可、DROP TABLEは不可」と決めておけば、AIがどんな指示を受けても破壊的な操作はそもそも実行できません。
陳腐化を防ぐ運用
繰り返しになりますが、ベンダーが速く進化する以上、ユーザーハーネスは放置すれば腐ります。維持保守の追従性が現実的な勝負どころです。
実務で効くと感じている対策を三つ挙げます。
ひとつは、AGENTS.md類をGitで管理して、四半期に一度は棚卸しすることです。新モデルが出たら一度ルールを外してみて挙動を確認するレビューサイクルを持つだけで、不要なルールはかなり減らせます。
ふたつは、モデル固有の癖への回避策はコアのAGENTS.mdに混ぜず、別ファイルに切り出すことです。新モデルが出たときに真っ先に検証する場所が明確になります。
みっつは、標準化されつつある規約に乗ることです。AGENTS.mdはOpenAI、Google、Cursor、Factory、Ampなどの協業で策定され、現在はAgentic AI Foundation(Linux Foundation配下)が運営する開かれた規約になっています。MCPも複数ベンダーで採用が進んでいます。独自のフック機構や独自スラッシュコマンドに深く依存するより、こうした共通規約に寄せたほうが、特定ベンダーの仕様変更に振り回されずに済みます。
まとめ
- ハーネスは「ベンダー組み込み」「ユーザー(プロンプト型)」「ユーザー(環境型)」の3層に分けて考える
- ベンダーハーネスは思った以上に手厚く、進化も速い。これと矛盾するルールをプロンプト型に書くと、本命の指示まで効かなくなる
- 一番効くのは維持保守の追従性。ユーザーハーネスがベンダー進化に追従できないと、品質改善どころか新たな矛盾の原因になる
- 強制したいことは環境型(CI、フック、サンドボックス、MCP)に寄せる
- プロンプト型は「環境で強制しにくい」「ベンダーがカバーしていない」「モデル進化に左右されない」の三つが揃ったルールに絞る。不具合再現テスト先行はその好例
ハーネスは多ければ多いほど安全、というのは半分しか正しくありません。強制力のある層に集約して、プロンプトはなるべく薄くメンテしやすい状態に保つ。これが、ベンダー進化に振り回されずに長持ちする設計だと考えています。