ハーネスエンジニアリングとは、AIエージェントが失敗したときにプロンプトを言い直すのではなく、エージェントが動く環境のほうを変えて同じ失敗を起こさせない取り組みです。Ghosttyの開発者でHashiCorp共同創業者のMitchell Hashimoto氏は、2026年2月5日のブログで「エージェントがミスをしたら、そのミスを二度と起こさない解決策を作る時間を取る」と説明しました。OpenAIで手書きコード0行の開発実験を率い、現在はGoogle CloudにいるRyan Lopopolo氏は、2026年9月の対談で「モデルが成功できる環境にモデルを置くための研究であり実践」と言い、それを怠った状態を「prompt and pray(プロンプトを書いて祈る)」と呼んでいます。
本記事では、定義とプロンプト・コンテキストエンジニアリングとの違い、OpenAIとLangChainが公表した数字、始め方を一次情報から整理します。そのうえで、環境を仕様(Spec)・文脈(Context)・制御(Harness)の三層に分けて設計する方法と、Claude CodeのStopフックで初回の終了前にテストし、失敗時に修正を促す設定を入れた場合と入れない場合を、同じ指示で実行した結果を載せます。
まとめ:ハーネスエンジニアリングの定義・やり方・判断の要点
- 定義:LangChainは「Agent=Model+Harness」とし、モデル以外のすべて(ツール・ファイル・権限・検査・メモリ)をハーネスと呼びます。ハーネスエンジニアリングは、そのハーネスを失敗のたびに直していく営みです。
- コンテキストエンジニアリングとの違い:コンテキストは「何を読ませるか」、ハーネスは「何を許し、何で検査し、いつ止めるか」まで含みます。Thoughtworksは、利用者が作るハーネスをコンテキストエンジニアリングの特定の形と位置づけています。
- 実例:LangChainはモデル(gpt-5.2-codex)を固定したままハーネスだけを変え、Terminal Bench 2.0のスコアを52.8から66.5へ上げました。OpenAIのチームは3人で5か月、手書きコード0行で約100万行を作っています。
- やり方:失敗を記録し、介入をプロンプト→リポジトリの文書→リンター→テスト→評価の順に「左へ」寄せます。まず作るのはツール本体ではなく、AGENTS.mdやCLAUDE.md・テスト・フックといった使い手側のハーネスです。
- 実測:Claude Codeで同じ指示を出すと、フック無しではテストが落ちたまま3ターンで終わり、Stopフック有りではテスト失敗を受けて作業を続け、8ターンで実装の不具合まで直しました(各1回の実行)。
- 外す判断:ハーネスの部品はどれも「今のモデルにはできないこと」の仮定です。モデルが更新されたら、外せる部品を探して減らします。
以下、定義から順に、各社の一次情報と実測で説明します。
ハーネスエンジニアリングの意味と「Agent=Model+Harness」の定義
馬具に由来する「ハーネス」がAIエージェントで指す範囲
ハーネス(harness)はもともと馬具を指す語で、力の強い動物を目的の方向へ働かせるための装具です。AIエージェントの文脈では、モデルの外側にあって、モデルの出力を実際の作業に変える仕組み全体を指します。LangChainのVivek Trivedy氏は2026年3月10日の記事で「Agent = Model + Harness」と定義し、「If you’re not the model, you’re the harness.」と書きました。ファイルシステム、bash、サンドボックス、メモリ、コンテキストの圧縮、Skillsまでがハーネスの部品です。
Google Cloudが2026年9月25日に公開したThe Agent Factoryの要約記事は、例で説明しています。「空はなぜ青いのか」ならモデル単体で答えられますが、「今日はレインコートを着るべきか」は答えられません。ハーネスが質問の意図をくみ取り、気象ツールに問い合わせ、その結果をコンテキストとしてモデルに渡すことで、初めて根拠のある答えになります。Google Antigravityの上でGemini 3.8 Flashを使うなら、Gemini 3.8 Flashがモデル、Antigravityがハーネスです。
Hashimoto・OpenAI・Anthropic・Thoughtworks・LangChain・Googleの定義の違い
この語は2025年11月から2026年9月にかけて、発信元ごとに少しずつ違う意味で使われてきました。どこを強調しているかを並べます。
| 公表日 | 発信元 | 強調点 |
|---|---|---|
| 2025-11-26 | Anthropic | 初期化エージェントと進捗ファイル |
| 2026-02-05 | Mitchell Hashimoto | ミスを再発させない仕組み |
| 2026-02-11 | OpenAI(Lopopolo氏のチーム) | 手書きコード0行の開発環境 |
| 2026-03-04 | Kief Morris(Thoughtworks) | 人はループの「上」で直す |
| 2026-03-10 | LangChain | Agent=Model+Harness |
| 2026-04-02 | Birgitta Böckeler(Thoughtworks) | ガイドとセンサーで制御 |
| 2026-09-25 | Google Cloud | 介入を左へ寄せる(shift left) |
Hashimoto氏のMy AI Adoption Journeyは「Step 5: Engineer the Harness」で、方法を2つ挙げています。エージェントへの暗黙の指示であるAGENTS.mdを改善することと、スクリーンショットの取得や絞り込んだテストの実行のような専用ツールを用意することです。Google Cloudの記事はLopopolo氏を「agent harnessという語を作った人物」と紹介していますが、上の表のとおり同時期に複数の発信があり、誰が最初かは本記事では断定しません。
ツールに組み込まれたハーネスと使い手が足すハーネス
「モデル以外すべて」という定義は広すぎます。Böckeler氏はHarness engineering for coding agent usersで、コーディングエージェントのハーネスの一部はシステムプロンプトや検索の仕組みとして既に組み込まれており、利用者はその外側に自分の用途向けの「outer harness」を作る、と範囲を絞りました。
Claude CodeやCodexを使う開発チームが作り込むのは、この外側です。AGENTS.md・CLAUDE.md、Skills、テスト、CI、権限設定、フックがそれにあたります。Lopopolo氏も、独自のハーネスを作り込みすぎるとフロンティアモデルが進化したときに技術的負債になると指摘し、ファイル読み込み・grep・コマンド実行といった標準ハーネスの基本機能に乗ったうえで、ツールとコンテキストの品質に投資するよう勧めています。エージェントそのものを作る側の部品(ループ・ガードレール・SDKの設定)は、AIハーネスの6部品とSDK別の実装で扱っています。
プロンプト・コンテキスト・ハーネスエンジニアリングの違い
3つは対立する概念ではなく、扱う範囲が順に広がる関係です。直す対象で見分けると混乱しません。
| 呼び方 | 直す対象 | 効く単位 | 典型例 |
|---|---|---|---|
| プロンプト | 1回の指示文 | 1回のやり取り | 役割・出力形式の指定 |
| コンテキスト | モデルに読ませる情報 | 1セッション | RAG・圧縮・メモ |
| ハーネス | 権限・検査・ループ・環境 | プロジェクト全体 | テスト・フック・AGENTS.md |
Anthropicは2025年9月29日の記事で、コンテキストを「収穫逓減する有限の資源」とし、望む結果の確率を最大にする最小のトークン集合を渡すことをコンテキストエンジニアリングの目標に置きました。ハーネスはこれに加えて、何を実行させ、結果をどう検査し、どこで止めるかまで決めます。
発信元によって包含関係の見方は逆になります。LangChainはコンテキスト管理をハーネスの部品の1つとし、Böckeler氏は「コーディングエージェントのユーザーハーネスを作ることは、コンテキストエンジニアリングの特定の形」と書いています。実務上はどちらの見方でも構いません。違いが出るのは、テストやフックのようにモデルに読ませる情報ではなく、モデルの外で決定論的に動く仕組みを設計の対象に含めるかどうかです。読ませる情報の設計手法はコンテキストエンジニアリングとは?プロンプトエンジニアリングとの違いと4つの実装手法で詳しく扱っています。
ハーネスエンジニアリングの実例:OpenAIとLangChainが公表した数字
OpenAIの手書きコード0行の実験:3人・5か月・約100万行
OpenAIのLopopolo氏のチームはHarness engineering: leveraging Codex in an agent-first worldで、Codexだけにコードを書かせて社内向けベータ製品を作った5か月間を報告しました。リポジトリは約100万行、マージされたPRは約1,500件で、当初は3人のエンジニアで1人1日平均3.5件です。7人に増えた後は1人あたりの処理量がむしろ増え、手で書いた場合の約10分の1の時間で作れたとチームは見積もっています。
この数字には前提があります。既存コードの無い新規の社内製品で、業務ドメインごとに Types→Config→Repo→Service→Runtime→UI という層の順序を最初から固定し、逆向きの依存をカスタムリンターと構造テストで禁じていました。人手の後始末も一度は破綻しています。毎週金曜(週の20%)を「AI slop」の片付けに充てていたものの規模に追いつかず、共通ユーティリティを優先するといった機械的な「golden principles」をリポジトリに書き、定期的な掃除の仕組みに置き換えました。大規模な既存コードにこの数字をそのまま当てはめることはできません。
LangChainがモデル固定でTerminal Bench 2.0を52.8から66.5へ上げた方法
「ハーネスだけで成果が変わる」ことを数字で示したのが、LangChainの2026年2月17日の記事です。同社のコーディングエージェントdeepagents-cliは、モデルをgpt-5.2-codexに固定したまま、89タスクのTerminal Bench 2.0で52.8%から66.5%へ13.7ポイント上がり、リーダーボードでTop 30の外からTop 5に入りました。変えたのはシステムプロンプト、ツール、ミドルウェア(モデル呼び出しとツール呼び出しの前後に挟むフック)の3つです。
| 見つけた失敗 | 入れた仕組み |
|---|---|
| 書いたコードを読み返して終える | 終了前に仕様との照合を促す |
| 環境の探索で迷う | 起動時にディレクトリとツールを注入 |
| 同じ壊れた方針を10回以上繰り返す | 同一ファイルの編集回数を数えて警告 |
| 時間切れ | 残り時間の警告を注入 |
推論の深さも調整しています。全工程を最大のxhighで走らせると時間切れが増えて53.9%にとどまり、highでは63.6%でした。計画と最終検証だけをxhighにする「reasoning sandwich」で66.5%に届いています。同じ改善を回していない古いハーネスでClaude Opus 4.6を走らせた結果は59.6%で、記事は「ハーネスはモデルに合わせて調整する」ことを教訓に挙げました。失敗の見つけ方は、実行トレースを複数のエージェントに並列で分析させるSkillです。
DORA 2025が示す「AIは増幅器」という組織側の条件
Googleの2025年版DORAレポートは、AIの主な役割を「増幅器」とし、組織が既に持つ強みと弱みの両方を大きくすると結論しました。投資の効果が大きいのはツールそのものより、その下にある組織の仕組みに取り組んだ場合です。テストが無い、文書が古い、レビューの基準が人の頭の中にしか無いチームでは、エージェントを速くしても壊れたものが速く増えるだけです。ハーネスエンジニアリングの多くは、テスト・CI・文書という従来の開発基盤をエージェントが読める形に整え直す作業になります。
Spec・Context・Harnessの三層で設計する理由と各層の置き場所
「モデル以外すべて」を一度に直そうとすると、手が止まります。直す対象が仕様の書き方なのか、読ませる文書の量なのか、実行後の検査なのかで、打ち手がまったく違うからです。本記事では、エージェントへの問いを3つの層に分けて考えます。業界で合意された分類ではなく、設計の単位として使うための整理です。
| 層 | 決めること | 欠けたときの症状 | Claude Codeでの置き場所 |
|---|---|---|---|
| Spec | 何ができたら完了か | 早すぎる完了宣言 | 仕様書・機能リスト・テスト |
| Context | 何をいつ読ませるか | 指示の見落とし | CLAUDE.md・Skills・サブエージェント |
| Harness | 何を許し何を検査するか | 同じミスの再発 | Hooks・権限モード・CI |
Specを独立させる根拠はBöckeler氏の記事にあります。テストやリンターのような決定論的な検査は規約違反を確実に拾う一方、問題の誤診断・過剰な設計・指示の誤解は確実には拾えません。同氏は「人間が最初に望むものを明確に仕様化していなければ、正しさはどのセンサーの守備範囲にも入らない」と書いています。検査をいくら厚くしても、合否の基準が無ければ判定できません。
Spec層:完了条件の明文化と変更の制限
Anthropicが2025年11月26日に公開した長時間エージェントのハーネスでは、初期化エージェントがユーザーの短い指示を機能要件のJSONへ展開します。claude.aiのクローンの例では機能が200を超えました。後続のエージェントには passes の値だけを変えさせ、「テストを削除・編集することは容認できない」と強い言葉で書き添えています。JSONを選んだのは、Markdownよりもモデルが不適切に書き換えにくいからです。この事例では、指示とJSON形式によって完了条件の不適切な変更を抑えています。書き換えを技術的に防ぐには、別途アクセス権限などで変更を制限する必要があります。
同社の2026年3月24日の続編では、1〜4文の指示を製品仕様に広げるPlannerが加わりました。Plannerを外すと、生成役は仕様を固めないまま作り始め、機能の少ないアプリで終わったといいます。仕様を書く道具には、GitHubのSpec Kit、OpenSpecなどがあり、選び方は仕様駆動開発ツールの比較に、方法論は仕様駆動開発(SDD)の解説にまとめています。
Context層:目次としてのAGENTS.md・CLAUDE.md
OpenAIのチームは、最初に巨大なAGENTS.mdを1つ置く方式を試して失敗しました。巨大な指示が課題やコードを押し出す、すべてが重要だと何も重要でなくなる、記述がすぐ古くなる、1つの塊では鮮度を機械的に検査できない、の4点が理由です。最終的にAGENTS.mdは約100行の「目次」になり、知識の正本は docs/ へ移りました。文書の鮮度と相互リンクは専用のリンターとCIで検査し、実装とずれた文書を探して修正PRを出す「doc-gardening」エージェントを定期的に走らせています。
Claude Codeの公式ドキュメントも同じ方向です。CLAUDE.mdは1ファイル200行未満を目安とし、長いほどコンテキストを消費して指示が守られにくくなると書かれています。v2.1.277以降は、作業ディレクトリとその親に CLAUDE.md・.claude/CLAUDE.md・CLAUDE.local.md のどれも無ければ、AGENTS.mdをプロジェクトの指示として読みます。既定設定では、どれか1つでもあればCLAUDE.md側だけが読まれます。両方を読ませたい場合は、/config の Project instructions を claude-md-and-agents-md に変えます。一部のセッションでは直接読めないため、その場合はCLAUDE.mdから取り込みます。@path 記法で取り込んだ文書は起動時に一緒に読み込まれるため、分割しても節約にはなりません。節約になるのは、特定のパスにだけ効くルールを .claude/rules/ に置いて、該当ファイルを扱うときだけ読ませる場合です。
Lopopolo氏は文書の書き方にも工夫を加えています。Markdownのリンクを文中に混ぜず、対応する段落の直後にまとめて置くと、文脈の散らかりと「lost in the middle」の取りこぼしを減らせるというものです。
Harness層:ガイドとセンサー、計算型と推論型
Böckeler氏は制御を2軸で分類しました。行動の前に方向づける「ガイド(フィードフォワード)」と、行動の後に観測して自己修正を促す「センサー(フィードバック)」の軸。テスト・リンター・型検査のように決定論的でミリ秒〜秒で終わる「計算型」と、AIレビューやLLM-as-judgeのように遅く高価で結果がぶれる「推論型」の軸です。ガイドだけでは効いたかどうかをエージェントが知る手段が無く、センサーだけでは同じミスを繰り返します。
OpenAIのチームは構造化ログや命名規則、ファイルサイズの上限を自作リンターで強制し、エラーメッセージに直し方を書き込みました。センサーの出力がそのまま次の行動へのガイドになる設計です。権限も同じ層に入ります。Claude Codeには6つの権限モードがあり、v2.1.283以降はターミナルとVS Codeの対話セッションで auto(背景の安全チェック付きで自動承認)が初期値になりました。bypassPermissions は公式ドキュメントが隔離されたコンテナとVMに限っています。モードごとの設定はClaude Codeのパーミッションモードの違いと設定方法を参照してください。
ハーネスエンジニアリングのやり方:介入を左へ寄せる5つの手順
Lopopolo氏の言う「shift left」は、エージェントが失敗したときの介入を、開発の流れのより早く・安く・自動化された段階へ移すことです。同氏は、何も変えずにプロンプトを再実行するのが最も単純な介入で、そこからリポジトリの文書、リンター、テスト、上流の評価へと寄せていく、と説明しています。これを手順にすると次のようになります。
- 失敗を記録する:起きた失敗だけを対象にします。Hashimoto氏の定義も「ミスを見つけたら」が起点です。本記事では「同じ指摘を2回したらハーネスへ移す」を目安にします。Böckeler氏も、問題が複数回起きたらガイドとセンサーを改善するよう書いています。
- どこまで左へ寄せられるか決める:繰り返す指示は共有文書へ移し、機械判定できる規約はリンター、振る舞いの条件はテストで検査します。チーム共通のCIやフックに組み込めば、適用漏れを減らせます。機械で判定できるものは機械に寄せます。
- ループ・ツール・メモリを決める:Googleのデモでは、何回反復させてどこで終えるか、どのツールをいつ使わせるか、会話と作業の記憶をいつ取り出し、いつ圧縮するかの3点を設計の判断とし、下の表の3つの型を示しました。
- 完了条件をテストで機械判定させる:完了判定には、エージェントの自己申告だけでなく、テストやチェックの合否を使います。ただし、次の章の実測は初回終了時の失敗通知までで、修正後の合格を完了条件として強制するものではありません。
- モデルの更新ごとに外す:入れた部品が補っている弱点を1行で書いておき、新しいモデルで不要になったものを外します(後述)。
| 型 | 向く作業 | 止める条件 |
|---|---|---|
| 線形 | 検査・ファイル変換・単発の分析 | 反復しない |
| クローズドループ | バグ修正・リファクタリング | テスト全通過か最大5回 |
| 安全対策付き | 長いデバッグ・権限の要る作業 | 危険な操作をフックで遮断 |
3つ目の型では、Agent Development Kit(ADK)のコンテキスト圧縮で古い会話を要約し、独自のフックでシェル操作を実行前に検査して、再帰的な削除、データベースの削除、許可されていないリモートへのgit pushを止めていました。クローズドループに反復の上限を置くのは、無限ループと費用の膨張を防ぐためです。反復の止め方はエージェントループの止まる条件とSDK別の反復上限で比べています。
Claude Code Hooksで終了前検証とループ検知を組み込んだ実測
LangChainがミドルウェアで入れた仕組みは、Claude CodeではHooksで再現できます。HooksはSessionStart・PreToolUse・PostToolUse・Stopなど33種類のイベントにスクリプトを結びつける仕組みで、終了コード2の効き方がイベントごとに違います。
| LangChainの仕組み | Claude Codeのイベント | 使用する終了コードと効果 |
|---|---|---|
| 終了前の検証 | Stop | 2で終了させず作業を続けさせる |
| 同一ファイルの編集回数 | PostToolUse | 2で標準エラーをClaudeに見せる |
| 起動時の環境注入 | SessionStart | 0で標準出力を文脈に注入 |
| 危険な操作の遮断 | PreToolUse | 2でツールの実行を止める |
Stopフックによる初回終了時のテストと修正の促進
次の設定は、フックによる継続中でない場合に終了前のテストを走らせ、失敗なら終了コード2で作業を続けさせるものです。継続後の終了ではテストを省くため、合格を保証しません。PostToolUse側には、後述する編集回数のフックを結びつけています。テストコマンドはPythonのunittest用なので、導入先のテスト構成に合わせて変更し、対象テストが検出・実行されることを先に確認してください。JSONは .claude/settings.json に既存の設定と統合して保存し、2本のスクリプトは .claude/hooks/ に置いて chmod +x で実行権限を付けます。bash・jq・Python 3が必要です。
{
"hooks": {
"PostToolUse": [
{ "matcher": "Write|Edit",
"hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/loop-guard.sh" } ] }
],
"Stop": [
{ "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/verify-before-stop.sh" } ] }
]
}
}
#!/usr/bin/env bash
# Stop:終了前にテストを走らせ、失敗なら終了させずに作業を続けさせる
in=$(cat)
# 2回目以降(フックによる継続中)は止めない=無限ループ防止
[ "$(jq -r '.stop_hook_active' <<<"$in")" = "true" ] && exit 0
cd "${CLAUDE_PROJECT_DIR:-.}" 2>/dev/null || {
echo "検証対象ディレクトリへ移動できないため、テストを実行できませんでした。設定を確認してください。" >&2
exit 2
}
if ! out=$(python3 -m unittest -q 2>&1); then
echo "終了前の検証でテストが失敗しました。仕様と照らして直してから終えてください。" >&2
echo "$out" | tail -n 15 >&2
exit 2
fi
exit 0
stop_hook_active は、フックの指示で作業を続けている最中なら true になる入力値です。このスクリプトは2回目の終了では検証せずに終わらせるので、直しきれなくても止まります。この行を外すと再検証できますが、別途反復回数や時間の上限が必要です。Claude Codeは8回連続で継続した後の次のブロックを無視して応答を終了しますが、連続回数はツール呼び出しのたびにリセットされます(上限は環境変数 CLAUDE_CODE_STOP_HOOK_BLOCK_CAP で変更可)。条件を自然文で書くだけなら、組み込みの /goal コマンドがプロンプト型のStopフックの近道になっています。
フック無し・有りで同じ指示を出した結果
add(a, b) が誤って a - b を返す calc.py と、add(2, 3) == 5 を確かめるテスト1本を用意し、「add関数に1行のdocstringを足して、足したら終了して」とだけ指示しました。Claude Code 2.1.302、モデルはclaude-haiku-5-5、権限モードはacceptEdits、claude -p で各1回実行しています。
| 項目 | フック無し | Stopフック有り |
|---|---|---|
| ターン数 | 3 | 8 |
| 所要時間 | 4.7秒 | 15.2秒 |
| 費用 | 約0.0047ドル | 約0.0073ドル |
| 実装の不具合 | 指摘のみで放置 | a + b に修正 |
| 実行中のフックによるテスト | なし | 修正前に1回・失敗 |
| 実行後に手元で流したテスト | 失敗 | 成功 |
フック無しのClaudeは、docstringを足したうえで「本体は a – b で、docstringの加算と食い違っている。docstringの追加だけを依頼されたので本体は変えていない」と報告して終わりました。不具合に気づいていても、依頼の範囲を守って止まったわけです。フック有りでは、終了しようとした時点でStopフックがテストの失敗を返し、Claudeは「テストは5を期待しているが実装は-1を返す」と読み取って a + b に直しました。
途中、Claude自身がテストを実行しようとしたBashはacceptEditsの範囲外で2回とも拒否されています。それでもテストの失敗をClaudeに伝えられたのは、テストをエージェントの権限ではなくハーネス側のフックで走らせているからです。完了条件(Spec)の判定を、エージェントの自己申告と切り離せます。ただし掲載したスクリプトは継続後の終了では検証を省くため、修正後の合否はセッション内では確かめていません。セッション終了後に両方のディレクトリで python3 -m unittest を流すと、フック無しは失敗(AssertionError: -1 != 5)、フック有りは成功でした。
フックの動作確認では1つ落とし穴があります。Pythonはバイトコードキャッシュの鮮度を、既定では元ファイルの更新時刻とサイズで判定します(Python公式のimportの仕様)。a + b を a - b のように同じ長さで書き換え、更新時刻も同じだと、__pycache__ の古いバイトコードが使われて失敗するはずのテストが通ります。手元で更新時刻をそろえて再現したところ、書き換え後もテストは通り、__pycache__ を消すと失敗しました。フックの動作確認で正常系と異常系を続けて試すときは、__pycache__ を消してから流してください。
注意点が2つあります。1つは、実行が各1回だという点です。モデルの判断は毎回揺れるので、この差を効果量として読まないでください。もう1つは、フックが「依頼されていない修正」まで引き出したことです。テストが仕様の正本になっているチームでは望ましい動きですが、テストが古いリポジトリでは、古い期待値に合わせて正しい実装を書き換えさせる方向にも働きえます(今回は検証していません)。テストを信頼できる状態にしてから入れてください。
同じファイルの編集回数で堂々巡りを検知するPostToolUseフック
#!/usr/bin/env bash
# PostToolUse:同じファイルの編集回数を数え、閾値を超えたら方針の見直しを促す
in=$(cat)
f=$(jq -r '.tool_input.file_path // empty' <<<"$in")
sid=$(jq -r '.session_id // "nosession"' <<<"$in")
[ -z "$f" ] && exit 0
log="${TMPDIR:-/tmp}/edit-count-$sid.log"
echo "$f" >> "$log"
n=$(grep -cxF "$f" "$log")
if [ "$n" -ge "${LOOP_LIMIT:-4}" ]; then
echo "$f を${n}回編集しています。同じ方針の小修正を繰り返していないか確認し、計画を見直してください。" >&2
exit 2
fi
exit 0
フックが受け取るのと同じ形のJSON(session_id と tool_input.file_path)を標準入力に渡して確かめると、同じファイルの1〜3回目は終了コード0、4回目で終了コード2になって警告を標準エラーに出し、別のファイルは0のままでした(bash 5.3.20・jq 1.7.1)。PostToolUseの終了コード2は編集を取り消さず、メッセージをClaudeに見せるだけです。PreToolUseに移すと編集前に遮断できますが、このコードでは拒否した試行も加算されるため、解除条件やカウントのリセットも設計してください。閾値の4は仮の値で、LangChainの記事でも「同じ壊れた方針を10回以上」繰り返したトレースがあったと書かれているだけなので、自分のトレースを見て決めてください。イベントごとの入力項目はClaude Code Hooksの全33イベント一覧と設定方法にまとめています。
モデル更新ごとのハーネス監査と外せる部品
Anthropicの2026年3月の記事は、ハーネスの部品はどれも「モデルが単独ではできないこと」についての仮定を埋め込んだもので、その仮定は間違っていることがあり、モデルが向上すればすぐに古くなる、と書いています。同記事の中でも仮定は2回崩れました。Sonnet 4.5はコンテキストの上限が近いと思い込んで作業を早く切り上げる「context anxiety」を示したためセッション間のリセットが必須でしたが、Opus 4.5ではリセットを外し、Opus 4.6ではスプリント構造も外しています。PlannerとEvaluatorは残しました。
| 構成 | モデル | 課題 | 所要時間 | 費用 |
|---|---|---|---|---|
| 単体エージェント | Opus 4.5 | レトロゲームメーカー | 20分 | 9ドル |
| フルハーネス | Opus 4.5 | レトロゲームメーカー | 6時間 | 200ドル |
| 簡素化したハーネス | Opus 4.6 | ブラウザDAW | 約4時間 | 約124ドル |
3行目は課題(ブラウザで動く音楽制作ソフト)が違うので、1〜2行目とは直接比べられません。単体エージェントの20分・9ドルは安く見えますが、中核の機能が動かないアプリでした。評価役については「使うか使わないかの二択ではない」とし、現行モデルが単独では確実にこなせない課題のときにだけ費用に見合う、と結論しています。LangChainも、ループ検知のような仕組みは今のモデルの弱点に合わせたもので、モデルが良くなればおそらく不要になると明記しました。監査は次の順で進めます。
- 部品ごとに、補っている弱点を1行で書く(例:リセット=context anxiety、編集回数の警告=堂々巡り)。
- その部品を外した構成と外さない構成を、同じ仕様・同じ指示で実行する。
- 時間と費用に加え、同じ基準で最終成果物を検査し、残った不具合の件数を並べる。費用が下がっても不具合が増えたら外しすぎです。
- 仕様と評価基準は最後まで残す。評価役のエージェントは、課題が現行モデルの守備範囲に入るなら外してよい。
- 浮いた予算で、新しいモデルなら扱える部品を足せないか検討する。
in the loopからon the loopへ:人が直す対象の移し方
ThoughtworksのKief Morris氏は2026年3月4日の記事で、エージェントの成果物に不満があるときの2つの直し方を区別しました。成果物を直接直すか、エージェントに直させるのが「in the loop」。その成果物を生んだハーネスを変え、次から望む結果が出るようにするのが「on the loop」です。同氏は、仕様・品質チェック・ワークフローの指示の集まりをハーネスと呼び、それを作って保守する営みをハーネスエンジニアリングと位置づけています。
人の判断が残る領域もあります。Böckeler氏が挙げた誤診断・過剰な設計・指示の誤解は、計算型でも推論型でも確実には捕まりません。仕様そのものと設計判断のレビューは人に残します。仕様が変わったときに設計書とコードの整合をどう保つかは、依存グラフで影響範囲を追う整合性駆動開発(CoDD)の守備範囲です。ハーネスの設計から実装・運用まで外部の支援を検討する場合は、生成AI開発・AI受託開発で相談を受け付けています。
ハーネスエンジニアリングを持ち込まない場面と典型的な失敗
- 一度きりの試作や数十行の修正:その作業のためだけに仕様ファイルや専用フックを新設する費用が、反復による便益を上回るなら追加を見送ります。既存のテストやCIは小さな修正でも実行します。
- まだ同じ失敗が起きていない段階:起きていない失敗まで個別のフックで先回りすると、外すべき仮定が増えるだけです。
- テストが信頼できないリポジトリ:前述の実測では、正しいテストに合わせて実装が変更されました。テストが古い場合は、同じ仕組みが誤った期待値に実装を合わせる方向に働くおそれがあります。先にテストを直します。
- ルールファイルの肥大:OpenAIが最初に失敗したのがこれです。数百行のAGENTS.mdは課題そのものを押し出します。
- 独自ハーネスの作り込み:Lopopolo氏の指摘どおり、モデルが進化したときに負債になります。標準のハーネスに乗り、ツールと文書に投資します。
- 要件がまだ固まらない探索:Specを先に厚く書くと、仕様の書き直しと実装のやり直しが二重に発生します。短い指示で試作し、方向が決まってから仕様に広げます。
エージェント側の自律ループそのものを設計したい場合はAgentic Codingの意味と進め方が入口になります。
よくある質問
ハーネスエンジニアリングとは何ですか?
AIエージェントのミスを、その場のプロンプトの言い直しではなく、指示ファイル・ツール・テスト・フックといった環境の変更で再発させないようにする取り組みです。LangChainの定義ではモデル以外のすべてがハーネスで、Hashimoto氏は2026年2月5日のブログで、AGENTS.mdの改善と専用ツールの用意を方法として挙げました。
コンテキストエンジニアリングとの違いは何ですか?
コンテキストエンジニアリングは、モデルに何をどれだけ読ませるかの設計です。ハーネスエンジニアリングはそれに加えて、権限・テスト・フック・ループの止め方など、モデルの外で動く仕組みまでを扱います。LangChainはコンテキスト管理をハーネスの部品とし、Thoughtworksのベッケラー氏は利用者のハーネス作りをコンテキストエンジニアリングの特定の形と見ています。
ハーネスエンジニアリングの例は?
LangChainは、gpt-5.2-codexを固定したまま、終了前の検証・環境情報の注入・同一ファイルの編集回数の警告・時間予算の注入を足し、Terminal Bench 2.0を52.8%から66.5%に上げました。OpenAIのチームは、約100行のAGENTS.mdと層の依存を禁じる自作リンターで、手書きコード0行のまま約100万行の製品を作っています。
Claude Codeでハーネスエンジニアリングを始めるには何からやればよいですか?
200行未満のCLAUDE.md(またはAGENTS.md)に、エージェントが繰り返した失敗への対策だけを書くところから始めます。次に、初回終了時にテストし、失敗なら修正を促すStopフックか、編集後に構文検査をするPostToolUseフックを1本入れます。権限は対話セッションならautoが初期値で、bypassPermissionsは隔離環境に限ります。
整合性駆動開発(CoDD/coherence-driven development)との関係は?
CoDDは、設計書・コード・テストの依存関係を宣言しておき、変更時に影響範囲を機械的に特定する手法です。本記事の三層で言えば、Spec層の変更をHarness層で検出する部分にあたります。ハーネスが「エージェントの作業」を検査するのに対し、CoDDは「文書とコードのずれ」を検査します。