AIに頼んだコードが後半で雑になる理由と、チームで実践したハーネス設計という解決策
この記事の対象者
- Claude CodeやChatGPTを使って日常的に開発しているエンジニア
- AIに実装を任せてみたが、後半の品質が落ちると感じている人
- チームの開発フローにAIをうまく組み込みたいと考えている人
- 「プロンプトをうまく書く」以外のアプローチを知りたい人
AIに「これ実装して」と頼むと、最初は丁寧なコードが出てきます。でも会話が長くなるにつれて、後半はコピペだらけ・ハードコードだらけになっていきます。そういう経験はありませんか。
これは気のせいでも、プロンプトの書き方が悪いわけでもありません。AIの構造的な問題です。
今回は、Anthropicが提唱する「ハーネス設計」という考え方と、それを自分たちのチームの開発フローに実際に取り込んだ事例を紹介します。
AIには2つの根本的な問題がある
問題① コンテキスト不安(品質劣化)
AIには処理できる情報量に上限(トークン上限)があります。会話が長くなるにつれてその上限に近づき、「早く終わらせよう」とでも言うかのように実装が雑になっていきます。
- 序盤:丁寧な型定義・コンポーネント分割・一貫した命名
- 後半:コピペ・重複コード・ハードコード多発
Anthropicはこの現象を「コンテキスト不安」と呼んでいます。そしてこれは、プロンプトの工夫で解決できる問題ではありません。構造レベルで対処する必要があります。
問題② 自己評価バイアス
AIに「この実装、問題ないですか?」と聞くと「完璧です!」と返ってくることが多いです。でも実際にはバグだらけだったりします。
これは作るときと同じ思考・同じ文脈で評価するため、自分の盲点に気づけないからです。人間でも自分で書いたコードのバグは自分では見つけにくいです。だからコードレビューが存在します。AIにも「別の目」が必要です。
ハーネス設計とは何か
Anthropicはこの2つの問題に対して「ハーネス設計」というアプローチを提唱しています。
ハーネスとは馬具のことです。AIを強力な暴れ馬に見立て、檻に閉じ込めるのではなく、力を殺さずに目的地へ導く道具として設計する、という考え方です。
具体的には3つの馬具に対応しています。
| 馬具 | 役割 | 具体例 |
|---|---|---|
| 轡(くつわ) | 行動制限 | ファイル読み取りは自動許可、書き込み・実行は人間が承認 |
| 鞍(くら) | 記憶の管理 | プロジェクトルールは永続保存、作業ログは都度リセット |
| 手綱(たづな) | フィードバック | 評価結果を次の実装に自動で反映するループ |
3つのAIに役割分担させる
ハーネス設計の核心は、AIを1体で使わずに3つの役割に分けることです。人間の開発チームと同じ構成になります。
📋 プランナー → ⚙️ ジェネレーター ↔ 🔍 エバリュエーター (PM役・企画) (エンジニア役・実装) (QA役・評価)
- プランナー:曖昧な要件を具体的な仕様に変換する。詳細すぎる指示はNG(カスケードエラーの原因になる)
- ジェネレーター:仕様をもとに実装する。実装前に「これを作ります」と宣言(スプリント契約)してから始める
- エバリュエーター:独立した別のAIが実際にブラウザを操作して検証し、フィードバックを返す。ジェネレーターが修正→また評価、のループを繰り返す
なぜ評価者を分けるのか
同じAIに評価させると、作るときと同じ思考で評価するため自分の盲点が見えません。「完璧です!」と言いながらバグが残る、いわゆる自画自賛ループです。
一方、新しい会話(別コンテキスト)で評価させると、先入観なく客観的に見られます。 同じモデルでもコンテキストを分ければ「別の目」になれます。
これは画像生成で使われるGAN(敵対的生成ネットワーク)と同じ発想です。「作る側」と「批評する側」が競い合うことで品質が上がります。Anthropicの報告では5〜15回のループで品質が大幅に向上したとされています。
補足として、Claude CodeのAgentツールでサブエージェントを呼び出すと、そのエージェントは完全に独立した新しいコンテキストで起動します。実装者が何を考えて実装したかを、評価者は物理的に知る手段がありません。これがハーネス設計の「評価者分離」を自然に実現しています。
自分たちの開発フローへの適用
ここからが実践の話です。上記のハーネス設計の思想を、実際のバグ修正フローに取り込みました。
実装方法:Claude Codeのスキルとして定義する
Claude Codeには「スキル」という仕組みがあります。SKILL.md というMarkdownファイルにフローの手順を定義しておくと、Claude Codeがそれを読み込んで手順通りに動いてくれます。
.claude/
└── skills/
└── bug-fix/ ← スキルの名前
└── SKILL.md ← フローの手順を定義するファイル
SKILL.mdの中には「Step 1でこのエージェントを呼ぶ、Step 2でこのエージェントを呼ぶ」という手順を書くだけです。各ステップで呼び出すエージェントも .claude/agents/ 配下に個別に定義します。
.claude/
├── skills/
│ └── bug-fix/
│ └── SKILL.md ← フロー全体の司令塔
└── agents/
├── issue-fetcher.md ← Issue情報を取得する役割
├── code-investigator.md ← コードを調査する役割
├── plan-reviewer.md ← 修正計画を作る役割
├── implementer.md ← 実装する役割
├── db-preparator.md ← テストデータを準備する役割
├── frontend-evaluator.md ← 独立して評価する役割
└── pr-creator.md ← PRを作成する役割
それぞれのエージェントは独立した別のコンテキストで起動します。つまり、実装エージェントが「何を考えて実装したか」を評価エージェントは知りません。渡された情報だけを見て判断するため、自己評価バイアスが構造的に排除されます。
フロー全体像
この構成で実現したバグ修正フローは以下のとおりです。
① Issue取得・分析(プランナー)
↓
② コード調査・修正計画の作成(プランナー)
↓
③ 人間が修正計画を承認 ← ここで人間が介入
↓
④ 実装・テスト・Lint(ジェネレーター)
↓
⑤ 操作確認用のテストデータを確認・準備(サポート役)
↓
⑥ 独立した評価エージェントがブラウザで動作確認(エバリュエーター)
↓
❌ FAIL → ④に差し戻し、ループ
✅ PASS ↓
⑦ 人間が最終確認 ← ここで人間が介入
↓
⑧ PR作成
SKILL.mdにこのフローを定義しておくことで、「IssueのURLを渡す」という一言だけでフロー全体が自動で動きます。エンジニアが介入するのは③修正計画の承認と⑦最終確認の2箇所だけになります。
各ステップの詳細
① Issue取得・分析
GitHubのIssue番号またはURLを受け取り、Issue本文・ラベル・関連リンクを取得して「課題サマリー」を生成します。何を直すべきかを整理するのがこのステップの目的です。
② コード調査・修正計画の作成
課題サマリーをもとに、関連する仕様書・実装ファイル・テストファイルを調査します。どのファイルのどの部分を変更すべきかを特定し、修正計画として出力します。
③ 人間が修正計画を承認
ここが最初の人間介入ポイントです。 AIが出した修正計画をエンジニアが確認し、方向性が正しければ承認します。この承認がなければ実装に進みません。
「何を直すか」に合意してから実装を始めることで、実装後の大幅な手戻りを防ぎます。
④ 実装・テスト・Lint(ジェネレーター)
承認済みの修正計画をもとに、ジェネレーターエージェントが実装を行います。実装完了後はテスト・Lintを実行し、基本的な品質チェックを通過したことを確認します。
実装完了レポートには「操作確認手順」も含めます。次のステップでテストデータを準備するための情報です。
⑤ テストデータの確認・準備(サポート役)
評価エージェントが動作確認をするためには、DBに適切なテストデータが存在している必要があります。
このステップでは専用のエージェントが以下を行います。
- 必要なデータがDBに存在するか確認する
- 存在しない場合のみ、最小限のデータを作成する
- 「確認画面URL・ログイン情報・操作手順・期待する結果」を含む再現可能な操作手順を出力する
毎回データを作り直すのではなく、「なければ作る」という設計がポイントです。
⑥ 独立した評価エージェントが動作確認(エバリュエーター)
ここがハーネス設計の核心です。実装エージェントとは完全に独立した別のエージェントが起動し、以下の4つの観点で評価します。
- 動作確認:指定された操作手順通りに画面が動くか(Playwrightでブラウザを自動操作)
- 仕様書との照合:修正計画・仕様書の内容と実装が一致しているか
- コード品質:既存コードとの整合性・コーディング規約の遵守
- UI整合性:画面崩れ・表示の不整合がないか
評価結果は PASS / FAIL で返します。
- PASS:次のステップ(人間確認)へ進む
- FAIL:差し戻し理由を添えて④(実装エージェント)に戻す。PASSが出るまでこのループを繰り返す
評価エージェントは実装エージェントが「何を意図して実装したか」を知りません。渡された情報と実際の動作だけを見て判断するため、自己評価バイアスが構造的に排除されています。
⑦ 人間が最終確認
ここが2番目の人間介入ポイントです。 評価エージェントがPASSを出した後、エンジニアが実際に画面を操作して確認します。
問題がなければ「PR作成してください」と一言伝えるだけで次のステップに進みます。問題があれば④に差し戻し、同じブランチに追加コミットとして積みます。
⑧ PR作成
承認済み修正計画・実装完了レポート・評価レポートをもとに、コミット・プッシュ・PR作成を自動で行います。
設計のポイントまとめ
人間が介入するのは2箇所だけ
修正計画の承認(③)と最終確認(⑦)のみ。それ以外はAIが自律的に回します。評価者がPASSを出すまで人間確認に進まない、という品質ゲートが自動化されています。
評価者は独立したコンテキストで起動する
実装エージェントと評価エージェントは別々のAgentとして起動するため、実装者の「意図」を評価者は引き継ぎません。実装の良し悪しだけを見て判断できます。
テストデータの準備を自動化する
「データが存在するか確認し、なければ作成する」という役割のエージェントを挟むことで、評価が常に再現可能になります。手動でテストデータを用意する手間がなくなります。
FAILループで品質を担保する
評価エージェントがFAILを出したら、フィードバックを実装エージェントに渡して差し戻します。PASSが出るまでこのループを繰り返すことで、人間が確認する前に一定の品質が担保されます。
旧フローとの違い
| 旧フロー | 新フロー(ハーネス設計) | |
|---|---|---|
| 評価 | 実装エージェント自身が確認 | 独立した評価エージェントが確認 |
| 人間確認のタイミング | 実装直後 | 評価エージェントPASS後のみ |
| テストデータ | 手動で準備 | 自動で確認・準備 |
| 品質ゲート | なし | 評価ループで自動担保 |
スライドで全体を振り返る
以下のスライドで今回の内容をまとめています。スペースキーまたは矢印キーでページを送れます。
まとめ 道具はある、設計は自分たちでする
Claude CodeはPlaywright MCPやAgentツールなど、ハーネス設計を実現するための道具を提供しています。しかし「どう分業させるか」「評価基準を何にするか」「どこで人間が介入するか」は自分たちで設計する必要があります。
いきなり完全なフローを作る必要はありません。
まずは例として、AIに何か実装させたら → 新しい会話を開いて「この基準で評価して」と貼り付けるだけです。
同じモデルでもコンテキストを分ければ「別の目」になれます。
強い馬には良い馬具を。AIの力を最大限に引き出すのは、プロンプトの工夫ではなく設計の力です。
参考:Anthropic Engineering Blog「Harness Design for Long-Running Apps」