211
132

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ハーネスエンジニアリング入門 ── CLAUDE.mdの次に来るAIエージェント制御パラダイム

211
Posted at

本稿では、AIエージェントの出力品質は「構造」で大きく変わるという前提のもと、CLAUDE.mdの次のパラダイムとして注目される「ハーネスエンジニアリング」の概念・構成要素・導入方法を、実運用の経験を交えて解説します。

なぜハーネスが必要になったのか

半年ほど前、筆者はCLAUDE.mdだけでプロジェクトを回していました。
コーディング規約、ディレクトリ構成、技術スタックを書いておけば、AIは概ね期待通りに動きます。
最初のうちは。

問題はプロジェクトが大きくなってから出ました。

  • 品質のばらつき: 同じ「APIエンドポイントを追加して」という指示でも、セッションによってファイル配置やエラーハンドリングの粒度が違う
  • セッション切れの断絶: 昨日の作業の続きを頼むと、前回の設計判断を無視した実装が返ってくる
  • スキル追加の破綻: /deploy /write-test のようなスキルを20個以上追加した結果、実行順序や前提条件の管理が手に負えなくなった
  • ルール違反の見落とし: CLAUDE.mdに「ドメイン層は外部ライブラリをimportしない」と書いても、守られているかは人間がレビューするしかない

つまり、CLAUDE.mdは「お願い」でしかなかったのです。
守らせる仕組みがない。
違反を検知する仕組みもない。
ルールが古くなったことに気づく仕組みもない。

GMOインターネットの平野氏も、ConoHa VPS開発で同様の課題に直面しています。AIの出力品質にばらつきが生じる問題に対し、人の注意力ではなく構造で品質を守るアプローチを採用しました。

これが「ハーネスエンジニアリング」という考え方の出発点です。

馬具のハーネスとAIのハーネス

「ハーネス(harness)」の原義は馬具です。
馬の体に装着し、騎手の意図した方向に力を伝える道具です。

ここで重要なのは、馬具は馬の脚力を削ぐものではないということです。
むしろ逆です。
馬具があるからこそ、馬は全力で走れます。
方向の制御を馬具に任せることで、馬は「走る」ことに集中できるからです。

馬具なしの馬は、どこに走るかわからない。
馬具ありの馬は、全力で正しい方向に走れる。

AIエージェントも同じです。
ハーネスなしのAIは、どんな設計判断をするか予測できない。
ハーネスありのAIは、制約の範囲内で最大限の創造性を発揮できます。

ソフトウェア開発における「テストハーネス」も同じ語源です。テスト対象の実行環境を構造的に制御し、結果を検証可能にする仕組み。ハーネスエンジニアリングは、この考え方をAIエージェントの行動制御に拡張したものです。

CLAUDE.md → AGENTS.md → ハーネス:進化の実体験

AIエージェント制御は3段階で進化してきました。
各段階で何ができるようになり、何が足りなかったのかを振り返ります。

第1段階: CLAUDE.mdの時代(2025年前半)

プロジェクトルートにCLAUDE.mdを置き、技術スタックとコーディング規約を書く。
これだけで、AIの出力は劇的に改善されました。

# CLAUDE.md
## 技術スタック
- Next.js 15 (App Router)
- TypeScript 5.x
- Prisma + PostgreSQL

## 規約
- コンポーネントは src/components/ に配置
- APIルートは src/app/api/ に配置
- 型定義は src/types/ に集約

できるようになったこと: AIが技術スタックを把握し、規約に沿ったコードを生成する。

足りなかったこと: ルールは「お願い」止まり。セッションが切れると前回の文脈が消える。複数人で開発すると、CLAUDE.mdの解釈がエージェントによって微妙にずれる。

第2段階: AGENTS.md + ルール分離の時代(2025年中盤)

CLAUDE.mdが肥大化し、1ファイルでは管理しきれなくなりました。
.claude/rules/ にルールを分離する構成が登場します。また、AGENTS.mdはクロスツールのオープン標準として策定され、エージェントに向けた指示(どのファイルを読むべきか、どのツールを使うべきか等)を宣言的に記述する仕組みです。特定ツールに依存しない点が特徴で、Claude Code以外のエージェントツールからも参照できます。

project/
├── CLAUDE.md              # プロジェクト全体の方針(簡潔に)
├── AGENTS.md              # エージェント向けの指示書(クロスツール標準)
└── .claude/
    └── rules/
        ├── architecture.md    # アーキテクチャ制約
        ├── testing.md         # テスト方針
        └── security.md        # セキュリティ要件

できるようになったこと: ルールの関心分離。エージェントが参照するコンテキスト量を必要最小限に制御できる。AGENTS.mdにより、ツールを問わずエージェントへの指示を標準化できる。

足りなかったこと: ルールを書いても、守らせる強制力がない。セッション間の記憶が途切れる問題は未解決。スキルの実行手順がエージェント任せで、品質がばらつく。

第3段階: ハーネスエンジニアリング(2025年後半〜)

ルール定義だけでは不十分だと気づき、実行・検証・記憶の仕組みを統合します。
これがハーネスです。

段階 対象 制御方法 持続性 違反検知
プロンプト 単一の応答 テキスト指示 なし なし
コンテキスト 単一セッション ファイル配置 セッション内 なし
ハーネス 複数セッション 構造的制約 永続的 自動

ハーネスはコンテキストエンジニアリングを置き換えるのではなく、包含します。
CLAUDE.mdもAGENTS.mdもハーネスの一部です。
それに加えて、スキル・フック・メモリ・検証ループという層を重ねたのがハーネスです。

ハーネスなし vs ハーネスあり: Before/After

同じタスク「ユーザー認証APIを追加する」を、ハーネスなし/ありで実行した場合の違いを示します。

Before: CLAUDE.mdのみ

指示: 「ユーザー認証APIを実装して」

結果:
- src/app/api/auth/route.ts にJWT認証を実装 ← OK
- パスワードを平文でログに出力 ← セキュリティ違反
- エラーレスポンスの形式が既存APIと不一致 ← 規約違反
- テストなし ← 基準未達
- 前回のセッションで決めた「認証はNextAuth.js」の方針を無視 ← 文脈断絶

5つの成果物のうち、問題なしは1つだけです。
しかも問題に気づくのは、人間がレビューしたときです。

After: ハーネスあり

指示: 「ユーザー認証APIを実装して」

実行される制御:
1. [メモリ] progress.mdから前回の決定事項を読み込み → NextAuth.js採用を認識
2. [スキル] /add-feature の手順に従い、型定義→ロジック→API→テストの順で実装
3. [フック] ファイル保存時にBiomeで自動フォーマット
4. [フック] console.logやセキュリティ違反パターンを即時検出
5. [フィードバック] タスク完了前にtypecheck + テスト実行 → 型エラー0件、テスト全パス
6. [メモリ] progress.mdを更新、次のセッションに引き継ぎ

結果:
- NextAuth.jsで実装(前回の方針を反映) ← OK
- セキュリティ要件準拠 ← OK
- エラーレスポンス形式が統一 ← OK
- テストカバレッジ基準達成 ← OK
- 進捗ファイル更新済み ← OK

違いは明白です。
ハーネスなしでは「良い出力が出ることを祈る」運用です。
ハーネスありでは「悪い出力が出にくい構造」になっています。

ハーネスの5つの構成要素

ハーネスは以下の5要素で構成されます。

1. ルール(Rules)

CLAUDE.md.claude/rules/ に配置する行動規範です。
エージェントが従うべき制約を宣言的に記述します。

# .claude/rules/architecture.md
- src/domain/ 配下のファイルは外部ライブラリを直接importしない
- APIレスポンスの型は src/types/ に定義する
- コンポーネントは1ファイル200行以内に収める

ルールはハーネスの土台ですが、ルールだけでは「守られているか」を検証できません。
GMOの事例では、12カテゴリ48ルールを管理しています。
この規模になると、人間のレビューだけでは限界があります。

2. スキル(Skills)

再利用可能な手順書です。
/deploy /write-test のようなコマンドとして定義し、エージェントに特定の手順を実行させます。

# .claude/skills/write-test/SKILL.md
1. 対象ファイルのexportされた関数を列挙する
2. 各関数に対してVitestのテストケースを作成する
3. 正常系・異常系・境界値の3パターンを含める
4. `npm run test` で全テストが通ることを確認する

Claude Codeの最新版では、スキルの定義場所が .claude/commands/*.md から .claude/skills/<name>/SKILL.md に移行しています。新規作成の場合は .claude/skills/ を使用してください。

スキルの本質は「手順の標準化」です。
エージェントが毎回異なるアプローチを取る問題を、構造的に解消します。
「テストを書いて」という曖昧な指示が、常に同じ品質基準で実行されるようになります。

3. フック(Hooks)

イベント駆動の自動実行トリガーです。
Claude Codeでは hooks 設定で、特定のタイミングに処理を差し込めます。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/format.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm run test"
          }
        ]
      }
    ]
  }
}

公式ドキュメントに基づく補足です。matcherの内側に hooks 配列を持ち、各ハンドラには type フィールドが必要です。matcherにはClaude Codeのツール名(Edit, Write, Bash 等)を指定します。Stop イベントはmatcherをサポートしません。また、hookコマンドにはstdin経由でJSON(tool_input にファイルパス等を含む)が渡されるため、フォーマッタ等の実行はシェルスクリプトでJSONをパースして処理するのが定石です。

フックの価値は、ルール違反の検知タイミングを「事後レビュー」から「即時」に変えることです。
ファイルを編集した瞬間にフォーマッタが走り、タスク完了時にテストが実行される。
人間が気づく前に、構造が違反を捕まえます。

4. メモリ(Memory)

セッション間で持続するコンテキストです。
進捗ファイル、意思決定ログ、学習記録などが該当します。

# progress.md
## 2026-03-22
- [x] ユーザー認証API実装(NextAuth.js)
- [x] JWTトークン発行・検証
- [ ] パスワードリセット機能

## 意思決定ログ
- 2026-03-20: ORMはPrismaを採用(理由: 型安全性とマイグレーション管理)
- 2026-03-21: 認証はNextAuth.jsを使用(理由: App Router対応、OAuth統合の容易さ)

## 次のセッションで対応すること
- パスワードリセットのメール送信処理
- rate limiting の追加

メモリがなければ、セッションが切れるたびに文脈がリセットされます。
前回決めた設計方針を無視した実装が返ってくる原因は、ほとんどがこれです。

メモリの形式には注意が必要です。Markdownは人間にとって読みやすい反面、エージェントが勝手にタスクを完了にする、意思決定ログを改変するといった問題が起きやすくなります。構造的な整合性を重視する場合は、JSON形式での管理も検討してください。

5. フィードバックループ(Feedback Loop)

エージェントの出力を自動検証する多層構造です。

検出対象 応答速度
型チェック 構文エラー、型不整合 数秒 tsc --noEmit
リンター コード品質、パターン違反 数秒 Biome, ESLint
ユニットテスト ロジックの誤り 数十秒 Vitest, Jest
構造テスト アーキテクチャ違反 数十秒 dependency-cruiser
E2Eテスト 統合・UI不整合 数分 Playwright

フィードバックが速いほど、エージェントの軌道修正も速くなります。
TypeScriptの型チェックは最速のフィードバック層です。
型エラーが出れば、エージェントは数秒で問題を認識して修正に入ります。

GMOの事例では、architecture.test.ts に23条件の構造テストを実装し、アーキテクチャ違反をCI以前に自動検出しています。

everything-claude-code の設計を読み解く

everything-claude-code(GitHub 100K+ stars)は、ハーネス設計の集大成ともいえるリポジトリです。
自らを「agent harness performance optimization system」と説明しています。

なぜ10万スターを超えたのか。
単なるCLAUDE.mdのテンプレート集ではなく、ハーネスの5要素すべてを網羅した実行可能なシステムだからです。

ディレクトリ構成と各要素の対応

everything-claude-code/
├── CLAUDE.md                # [ルール] プロジェクト概要・基本方針
├── AGENTS.md                # [ルール] 28エージェントの役割定義
├── rules/                   # [ルール] 言語別の詳細制約
│   ├── typescript/          #   TypeScript固有のルール
│   ├── python/              #   Python固有のルール
│   ├── rust/                #   Rust固有のルール
│   └── common/              #   全言語共通ルール
├── skills/                  # [スキル] 125個以上のワークフロー定義(2026年3月23日時点)
│   ├── tdd-workflow/        #   TDD手順
│   ├── deep-research/       #   リサーチ手順
│   ├── security-review/     #   セキュリティレビュー手順
│   └── continuous-learning/ #   学習パターン自動抽出
├── agents/                  # [スキル] 28個の専門エージェント定義
│   ├── planner.md           #   設計・計画担当
│   ├── code-reviewer.md     #   コードレビュー担当
│   ├── tdd-guide.md         #   TDD実行担当
│   └── harness-optimizer.md #   ハーネス自体の最適化担当
├── hooks/hooks.json         # [フック] 25以上のイベントトリガー
├── contexts/                # [メモリ] セッション永続コンテキスト
│   ├── dev.md               #   開発用コンテキスト
│   ├── research.md          #   リサーチ用コンテキスト
│   └── review.md            #   レビュー用コンテキスト
└── tests/                   # [フィードバック] 自動検証スイート

注目すべき設計パターン

1. フックの多層防御

hooks.jsonには25以上のフックが定義されています。
特に注目すべきは、その多層構造です。

PreToolUse(ツール実行前):
  - git hook bypass の阻止(--no-verify を許さない)
  - linter設定ファイルの改変を阻止(ルール弱体化の防止)
  - セキュリティモニタリング
  - MCP サーバーのヘルスチェック

PostToolUse(ツール実行後):
  - 自動フォーマット
  - TypeScript型チェック
  - console.log残留の警告
  - 品質ゲートチェック

Stop(タスク完了時):
  - セッション状態の永続化
  - 学習パターンの自動抽出
  - コスト(トークン使用量)の記録

「ファイル編集後に自動フォーマット」程度のフックは多くの人が設定しています。
ECCが突出しているのは、エージェントがルールを迂回する行動自体を阻止するフックを持っている点です。
--no-verify でgit hookを飛ばそうとする行動や、ESLintの設定を緩めてエラーを消そうとする行動を、構造的にブロックします。

2. 自己最適化の仕組み

harness-optimizer というエージェントが存在します。
これはハーネス自体の設定を分析し、改善提案を行う専門エージェントです。
さらに continuous-learning スキルが、セッションごとにパターンを自動抽出し、ハーネスの知識ベースを継続的に更新します。

ハーネスが自分自身を改善する。
これは静的なCLAUDE.mdテンプレートとの根本的な違いです。

3. 段階的な強度設定

ECCのフックには minimal standard strict の3段階のモードがあります。
すべてのフックが常時有効ではなく、プロジェクトの成熟度に応じて強度を調整できる設計です。

導入の段階的アプローチ

いきなり全部入りは失敗します。ECCのような完成形を初日から導入すると、フックの嵐でエージェントの応答が遅くなり、設定の管理に追われ、本来の開発が進みません。痛みを感じたところから順に追加するのが正解です。

ステップ1: CLAUDE.mdを書く(Day 1)

まだ持っていないなら、ここからです。
プロジェクトの技術スタック、コーディング規約、ディレクトリ構造を記述します。

# CLAUDE.md
## 技術スタック
- Next.js 15 (App Router)
- TypeScript 5.x
- Prisma + PostgreSQL

## 規約
- コンポーネントは src/components/ に配置
- APIルートは src/app/api/ に配置
- 型定義は src/types/ に集約

筆者の経験では、所要時間は30分程度です。
これだけでAIの出力品質は筆者の体感で大幅に改善しました。

ステップ2: 最初の痛みが出たらスキルを追加(Week 1〜2)

「テストの書き方が毎回違う」「デプロイ手順を毎回説明している」と感じたら、その作業をスキル化します。

# .claude/skills/add-feature/SKILL.md
1. src/types/ に型定義を追加する
2. src/domain/ にビジネスロジックを実装する
3. src/app/api/ にAPIルートを作成する
4. テストを書いて実行する
5. 進捗ファイルを更新する

最初は2〜3個で十分です。
「何度も同じ説明をしている」作業から優先的にスキル化します。

ステップ3: ルール違反が気になったらフックを設定(Week 2〜4)

「フォーマットが崩れたまま出力される」「テストを書き忘れる」と感じたら、フックの出番です。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/format.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npm run typecheck && npm run test"
          }
        ]
      }
    ]
  }
}

まずはこの2つだけ設定します。

  • ファイル編集後の自動フォーマット(Edit|Write にマッチ)
  • タスク完了前の型チェック+テスト実行(Stop はmatcher不要)

これだけで「テストを書き忘れた」「型エラーが残っている」が構造的に防がれます。

ステップ4: セッション切れで困ったらメモリを構築(Week 2〜4)

「昨日の続きを頼んだのに、前回の決定を無視された」と感じたら、メモリを導入します。

# progress.md
## 現在の状態
- 実装済み: [機能A, 機能B]
- 作業中: [機能C]
- 未着手: [機能D, 機能E]

## 意思決定ログ
- 2026-03-20: ORMはPrismaを採用(理由: 型安全性)
- 2026-03-21: 認証はNextAuth.jsを使用(理由: App Router対応)

CLAUDE.mdに「セッション開始時にprogress.mdを読むこと」と追記します。

ステップ5: 同じ違反が繰り返されたらルールを昇格(継続的)

GMOの事例で紹介されている「エスカレーションラダー」の考え方です。

レベル 方式 いつ昇格するか
L1 ドキュメント CLAUDE.mdにパターンを記載 初回の違反
L2 AI検証 CLAUDE.mdでルール参照、AIレビュー 同じ違反が3回発生
L3 ツール検証 Biome, dependency-cruiserで機械的に検査 AI検証をすり抜ける
L4 構造テスト architecture.test.tsで不変条件をテスト ビジネスクリティカルな制約

最初からL4を目指す必要はありません。
同じ違反が3回発生したら、1段階上のレベルに昇格させる
この「3回ルール」でルールの強度を段階的に上げていきます。

GMOの事例では、この昇格を「エスカレーショントラッカー」で管理しています。週次で違反を集計し、繰り返し発生するパターンを自動的にCI検証に昇格させる仕組みです。

ハーネスの限界と今後

ハーネスエンジニアリングは万能ではありません。

現時点の限界

初期コストと保守コスト: ルール体系・スキル・フックの設計には時間が必要です。さらに厄介なのは保守です。設定したルールは放置すると実態と乖離していきます。GMOの事例では90日間隔のパターン鮮度チェックを推奨しています。

過剰なハーネスは逆効果: フックを増やしすぎると、ファイルを1つ編集するたびに5つの検証が走り、エージェントの応答が極端に遅くなります。ハーネスの設計自体に、コスト意識が求められます。

エージェントの能力限界は超えられない: ハーネスはエージェントの出力方向を制御しますが、エージェント自体ができないことを可能にはしません。複雑な設計判断や、ドメイン知識が必要な意思決定は、依然として人間の役割です。

「ハーネス = 信頼しないこと」ではない

よくある誤解に触れておきます。
ハーネスはAIを信頼しないための仕組みではありません。

優秀な人間エンジニアも、git戦略・CI/CD・コードレビューという「構造」の中で最高のパフォーマンスを発揮します。
lint設定やテスト自動化は、エンジニアを信頼していないから導入するのではありません。
むしろ、構造的な支援があるからこそ、人は本質的な問題解決に集中できます。

AIエージェントも同じです。

今後の展望

ツール側の組み込み対応: Claude CodeのHooks機能、Kiro CLIのステアリングファイルのように、エージェントツール自体がハーネスの概念を取り込み始めています。ECCのような外部プラグインで実現していた機能が、ツール本体に吸収されていくでしょう。

ハーネスの共有と標準化: ECCの10万スターが示すように、良いハーネス設計はコミュニティの共有知になりつつあります。言語別・フレームワーク別のハーネステンプレートが整備されていく流れは加速するでしょう。

自己進化するハーネス: ECCの continuous-learning スキルのように、セッションからパターンを自動抽出し、ハーネス自体を継続的に改善する仕組みが一般化していくと考えます。静的な設定ファイルから、学習する制御システムへの進化です。

まとめ

ハーネスエンジニアリングの要点を整理します。

  • AIエージェントの品質は「賢さ」ではなく「構造」で守る
  • CLAUDE.mdは出発点だが、それだけでは「お願い」にすぎない
  • ルール・スキル・フック・メモリ・フィードバックループの5要素で制御する
  • いきなり全部入りにせず、痛みを感じたところから段階的に追加する
  • 同じ違反が3回起きたら、ルールの強度を1段階上げる
  • ハーネス自体の保守(鮮度管理・過剰検証の排除)も忘れない

馬具が馬の全力疾走を可能にするように、ハーネスはAIエージェントの能力を最大限に引き出す構造です。
「どう指示するか」から「どう制約するか」へ。
この発想の転換が、AIとの協働開発を次の段階に進めます。

参考リンク

211
132
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
211
132

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?