はじめに:なぜHarness Engineeringが必要なのか

Vibe Codingが壁にぶつかる

こんな午後を経験したことがあるかもしれません。Agentに要件を伝えると、数分でコードが出来上がり、動く。もう一つ頼む。それも完成する。これまで二日かかっていた作業が一午後で片付き、生産性が一段上がった実感を得ます。

しばらくすると違和感が出てきます。既存のコードに機能を追加させると、別の機能が壊れる。修正を頼むと直るが、新しいバグが出る。四、五回やり取りを繰り返すうちに、Agentの出力を検査・修正する時間が節約した時間を上回っています。

問題はモデルの能力やpromptの技術にはありません。この二つの軸での改善は天井を押し上げますが、天井そのものをなくすことはできません。この二年でモデルはGPT-4からClaude 3.5 Sonnet、Opus 4.6へと世代を重ね、それぞれ確実に進歩しました。扱えるプロジェクトの規模は大きくなり、自分自身のpromptも精度が上がり、渡すコンテキストも的確になりました。それでも一定期間ごとに、同じ崩壊パターンがより大きなスケールで再現されます。プロジェクトがもう少し大きくなる、イテレーションがもう数回増える、するとまた一つ直すと一つ壊れ、Agentは以前に取り決めた規約を忘れ、出力が期待から乖離し始めます。天井は上がっていますが、天井はまだあります。もっと根本的な構造的制約が作用しています。

注意力が対話の長さとともに減衰する現象は、この構造的制約の具体的な表れの一つです。対話の序盤で設定した制約が、終盤ではAgentの出力に実質的な影響を与えなくなっている可能性があります。

例えば、第5ラウンドでアーキテクチャ上の制約を一つ定めたとします。すべてのAPIレスポンスにerror codeフィールドを含めること。Agentはそのとおり実装しました。対話はさらに十数ラウンド進み、別の機能を議論し、大量のコードが生成されます。第30ラウンドで新しいインターフェースの追加を指示すると、error codeフィールドが消えています。対話を遡ると、あの制約は第5ラウンドの位置にまだ残っています。

原因はattentionメカニズムにあります。LLMがtokenを一つ生成するたびに、attentionメカニズムを通じてcontext内のすべての内容を参照し、各部分に関連性の重みを計算し、その加重情報を総合して選択を行います。この重みの配分は均等ではありません。研究によると、モデルはcontextの先頭と末尾の情報に高い注意を払い、中間部分の想起率は著しく低下します(lost in the middle)。対話が長くなるにつれ、序盤に設定した制約はコード出力や機能議論の間に埋もれ、割り当てられるattention重みが下がり続け、Agentの出力に実質的な影響を与えなくなります。情報はcontextの中にまだ存在していますが、Agentには事実上見えなくなっています。

対話がさらに長くなるとcompactionが発動します。システムが初期の対話を要約に圧縮してスペースを確保する処理です。compactionが起きたことは確認できますが、どの情報が保持されどの情報が捨てられるかは制御できません。第5ラウンドで定義した制約は、要約の中で詳細を失った一文になっているかもしれませんし、要約に含まれていないかもしれません。注意力の減衰は情報があるがAgentが見落とす現象、compactionは情報そのものが削除される現象です。この二つが重なることで、長い対話における意図の整合性は、常に流失し続ける基盤の上に成り立っています。

注意力の減衰とcompactionは、あなたが直面している問題の一部にすぎません。その背後にはより全体的な構図があり、あなたが遭遇したすべての壁を説明でき、同じツールを使っても人によって成果に大きな差が生まれる理由も説明できます。

大多数の開発者のAgent活用体験はあなたと似たものです。体感的には速くなったものの、総合的な生産性向上は1.5倍から2倍の範囲にとどまります。しかし同じツールで、少数の人々はまったく異なる成果を出しています。PingCAPのCTO黄東旭はAIを使ってTiDBのPostgreSQL互換レイヤーをプロダクションレベルに近いコードに書き直しました。Pigsty創設者の冯若航は一人でAIを活用し、460以上の拡張を統合したエンタープライズグレードのPostgreSQLディストリビューションを保守しており、日常的に10のAgentを同時に並行稼働させています。彼らの生産性向上は数十倍単位であり、検証を経てプロダクション投入済みのコードです。

同じモデル、同じツールで、数十倍の差がつく。その差はエンジニアリング制度にあります。Agentを大規模に活用できているチームはすべて、Agentの構造的特性に対応した closed-loop control 体系を構築しています。規約で曖昧な意図を精確な入力に変換し、自動化された検証で毎回の出力をチェックし、継続的な改善で体系そのものの劣化を防いでいます。業界ではこの方法論を harness engineering と呼んでいます。

なぜHarnessが必要なのか

Harnessの必要性は、実行者としてのAgentと人間との構造的な差異に由来します。この差異を理解すれば、自分がぶつかっている壁を一つ一つ診断でき、現在のエンジニアリングプラクティスが本当の問題を解決しているかどうかも判断できます。

Agentの構造的特性

Agentの挙動は二層の技術アーキテクチャで決まります。下層はLLMで、すべての入力内容に基づいて最も確率の高い次のtokenを逐次生成します。tokenを一つ生成するたびに、モデルはattentionメカニズムを通じて入力全体を参照し、各部分に関連性の重みを計算し、加重情報を総合して選択を行います。上層はAgentic Loopで、LLMが外部世界と対話できるようにする仕組みです。Agentは指令を受け取り、次のアクションを推論し、ツールを呼び出し(ファイル読み取り、コマンド実行、API呼び出し)、ツールの返却結果を観察し、再び推論し、再びアクションを取ります。このサイクルはタスクが完了するまで続きます。各ステップの入出力はすべて context window に追記されます。

この二層のアーキテクチャから、実行者としてのAgentの五つの構造的特性を導出できます。各特性はアーキテクチャの内在的属性であり、モデル能力の向上によって消えるものではありません。

忠実な実行

Agentは与えられた入力を忠実に実行します。明確で完全なspecを与えれば、高品質な出力が得られます。曖昧な記述を与えれば、各曖昧点がそれぞれランダムな判断にコンパイルされます。

これはLLMの動作原理の直接的な帰結です。出力は入力によって完全に決定され、モデルが処理するのはあなたが実際に提供した文字列であり、あなたの頭の中にある意図ではありません。あなたの意図はテキストとしてcontextに投入された部分だけが出力に影響します。Agentに「検索機能を追加して」と伝えたとき、検索対象は記事タイトルだけか全文か、結果はどの順序で並べるか、キーワードが空のときは何を表示するか。明示されなかった各ポイントについて、Agentは現在のcontextで最も確率の高い方案で埋め、忠実に実行します。これらの選択はあなたの意図から乖離しているかもしれませんが、出力を確認するまでそれを知ることはできません。

人間のプログラマーが同じ曖昧な要件に直面した場合、ビジネス上の常識で空白を補ったり、既存コードで類似機能がどう実装されているか確認したり、直接聞きに来たりします。Agentはこれらの補完ステップをすべてスキップし、曖昧な入力から確定的な出力を直接生成します。

チーム内にはドキュメント化されていない暗黙知が大量に存在し、Agentはこれらの知識にまったくアクセスできません。あるモジュールがなぜ特定のデザインパターンを採用しているのか、あるAPIのエラー処理が共通のerror handlerを使わず独自のロジックを持つ理由、ある顧客のデータフォーマットにどのような既知の異常があり互換対応が必要か。人間のプログラマーはcode review、スタンドアップ、日常の協業を通じてこれらの知識を徐々に吸収します。contextに書き込まれた知識だけがAgentの世界に存在し、出力されるコードは明示的に提供されなかったすべての知識を機能的に正しく無視します。

あなたの指示が十分に明確だったかどうかは、出力を見た後にしか判断できません。どれだけの暗黙知を提供し忘れたかは、あなた自身にもわかりません。open-loop control の下では、一つ一つの漏れが出力における不確実性の源になります。

有限な処理容量

Agentのワーキングメモリにはハード上限があり、実効容量は公称値をはるかに下回ります。情報は多ければ多いほど良いという直感は誤りです。

Agentのワーキングメモリの全体が context window です。あなたの指示、コードファイル、対話履歴、ツールの返却結果、すべての情報が一つのtokenシーケンスに連結されてモデルに送られます。このシーケンスには長さの上限があり、現在の主要モデルでは128Kから1M tokensの範囲です。一見すると十分に大きく見えます。しかし公称容量と実効容量は別物です。前述のとおり、attentionのcontext上での配分は均等ではなく、先頭と末尾の注意度が高く、中間部分の想起率は著しく低下します。情報が増えるほど、各情報に割り当てられるattention重みは少なくなります。ある臨界点を超えると、情報を追加する効果はむしろ負になり、重要な制約がノイズの中に埋もれます。公称128K tokensのウィンドウで、実効的に活用できる部分は半分以下かもしれません。

この制約が特に顕著に現れるシナリオが二つあります。

一つ目は大規模タスクです。小さなタスクは数ファイル、一つの機能に関わるだけで、関連情報がすべて実効的な注意範囲内に収まるため、Agentはよい結果を出します。大規模タスクではデータベーススキーマ、API契約、フロントエンドの状態管理、権限モデルを同時に考慮する必要があり、関連情報の総量が実効容量を超え、Agentはあちらを立てればこちらが立たない状態に陥ります。人間のプログラマーはシステム全体の永続的なメンタルモデルを持ち、局所のコードを扱いながらグローバルな一貫性を維持できます。Agentは毎回、限られたウィンドウの中でゼロから理解を構築し、収まりきらない部分は無視されます。

二つ目は長い推論チェーンです。Agentic Loopの各ステップがcontextに内容を追加するため、ウィンドウ内の情報は増え続けます。第5ステップで行ったインターフェース設計の判断は、第50ステップの時点ではウィンドウの遠端に押しやられ、割り当てられるattention重みは低くなっています。Agentが前半で採用したデザインパターンが後半で知らないうちに別のパターンに置き換わり、本人は前後の矛盾に気づきません。

open-loop control の下では、二つの失敗モードの間で板挟みになります。情報を少なく渡せばAgentは必要なコンテキストを欠き、多く渡せば重要な情報がノイズに埋もれる。現在どちらの状態にあるかを確実に判断する手段がありません。

記憶の蓄積がない

Agentの記憶はセッション境界で途切れます。セッションはあなたが指示を出した時点から始まり、タスク完了またはセッション終了で閉じます。セッション中はすべての情報が context window に蓄積されます。セッション終了後、contextはクリアされ、次のセッションは白紙から始まります。昨日20分かけて教えたアーキテクチャ規約、踏んだ地雷、取り決めたインターフェース仕様。今日はすべてゼロに戻っています。100回目のセッションと1回目のセッションの出発点はまったく同じです。

人間のチームにおける知識の蓄積はまったく異なります。プログラマーはプロジェクトに長く携わるほど、プロジェクトへの理解が深まります。アーキテクチャ判断の歴史的経緯、各モジュールの脆弱な箇所、特定のビジネスシナリオにおける処理慣行。これらの知識の大部分はドキュメントに書かれたことがなく、チームメンバーの頭の中にあり、code review、スタンドアップ、日常の協業を通じて自然に伝達・更新されています。Agentを中心とした開発には、この自然な蓄積プロセスが欠けています。

知識をドキュメントとして外部化することで補うことは可能ですが、ドキュメント自体も継続的なメンテナンスが必要です。人間の頭の中の知識はプロジェクトの進化に伴い自動的に更新されます。モジュールをリファクタリングすれば、そのモジュールに対する理解も同時に更新されます。ドキュメントは自動的には更新されません。三ヶ月前に書いたアーキテクチャドキュメントは、誰かが明示的にメンテナンスしなければ、すでに実際のコードと整合していない可能性があります。古くなったドキュメントはドキュメントがないよりも厄介です。Agentに誤った情報を提供し、Agentはその誤った情報に忠実に従って実行するからです。

結果への無自覚

Agentの目的関数は、現在の指示に対する充足度です。機能追加を頼めば追加し、バグ修正を頼めば修正する。目的はそこで完結します。コードの長期的な保守性、技術的負債の蓄積度合い、アーキテクチャの一貫性。これらの次元はAgentの最適化目標に含まれていません。人間のプログラマーは三ヶ月後に自分がこのコードを保守することを想像し、可読性のために短期的な効率を犠牲にすることがあります。Agentの各実行は独立しており、現在のタスクの完了がすべての目標です。

この特性は自己強化ループを生みます。Agentは新しいコードを生成する際、コードベースに既存のパターンを参照します。以前急ぎで書いたworkaroundは、Agentから見ればプロジェクトで確立された実装パターンであり、新しいコードに忠実にコピーされます。マージされたコードは以降の生成の参照セットとなり、悪いパターンが繰り返しコピー・増幅されます。人間のチームが同規模の技術的負債を蓄積するには通常数ヶ月から一年かかりますが、Agentを中心としたチームでは数週間でその水準に達する可能性があります。システムの中にリファクタリングや品質改善を推進する内在的な力は存在しません。

Agentはすべてのタスクに同等の注意と速度で取り組みます。表示ページの文言修正と決済処理のコアロジック変更は、実行レベルではまったく同じです。人間は高リスクな操作に直面すると本能的にペースを落とし、確認ステップを増やし、同僚に一緒に見てもらいます。Agentはすべてのタスクを一律に扱います。高リスクな操作は大量の低リスク操作の中に紛れ、同じ速度で処理されます。

高スループット・ゼロ限界コスト

前述の四つの特性は、人間の実行速度であればすべて管理可能な問題です。すべてのPRをレビューする時間があり、新しいセッションの開始時に重要な規約を教え直す時間があり、曖昧な規約が期待から乖離した実装を生んだことに気づいて修正する時間があります。人間のプログラマーの出力速度は、それ自体がエラー抑制メカニズムです。出力が遅ければ、偏差の蓄積も遅く、偏差が拡散する前に発見・修正する時間があります。コードレビュー、アーキテクチャ評価、結合テスト。これらの下流工程のリズムは、人間の出力速度と自然に合致しています。

Agentの出力速度は人間の10倍から100倍です。さらに、容易に並列インスタンス化できます。2番目、10番目、100番目のAgentインスタンスを起動するコストはほぼゼロであり、採用、研修、コミュニケーション調整は不要です。

この特性それ自体は新しい問題の種類を生みませんが、前述の四つの特性の影響を一桁から二桁増幅します。曖昧な規約を人間のプログラマーが実行した場合、修正が必要な偏差は二つ三つで、一つずつ対処できます。同じ規約をAgentに渡すと、一時間以内にそれぞれ異なる偏差を持つ数十の実装が生まれる可能性があります。記憶の不在は一日に二、三セッションなら不便ですが、一日に数十セッションになると深刻な知識の断絶になります。結果への無自覚は人間の速度で技術的負債を蓄積するには数ヶ月かかりますが、100倍速では数週間で同規模に達します。

100倍速は、出力とレビューのリズムの均衡を壊します。レビューは一行ずつの確認からサンプルチェックに退化します。偏差は人間が発見する前に、その後の数十回のコミットによって固定化され、コードベースの中で新たな既成事実になります。最後の防衛線である人間によるレビューが、100倍の出力の前に崩壊します。100倍の出力を100倍の速度でレビューすることは不可能です。open-loop control はAgentの速度と規模の下では完全に機能しなくなります。

Harnessの本質

五つの特性が共通して指し示す要求があります。人間の実行者が本来備えている能力を代替する、外部の、自動化された、Agentから独立したフィードバックメカニズムが必要です。このメカニズムは二つの原則で構成されます。

closed-loop control は、毎回の実行を確実にします。閉ループは二つのことを行います。一つ目は、規約で「何が正しいか」を定義し、あなたの頭の中の意図をAgentが対照・実行できる精確な記述に変換することです。一つの規約には、意図(何をするか、なぜするか)、受入条件(何をもって正しいとするか)、制約(変更の境界はどこか、何を変えてはいけないか)が含まれます。規約があれば、Agentの出力は予測不能なランダムから、検査可能な有限集合に変わります。二つ目は、検証で「正しくできたか」を確認することです。検証はAgentから独立した自動化チェック機構であり、偏差が発生した時点で捕捉・修正します。最終納品時に人間の目で発見するのではありません。規約と検証が feedback loop を構成し、偏差は即座に発見・修正されます。

持続的な改善は、閉ループそのものの劣化を防ぎます。規約、テスト、プロセスドキュメントは、人間の実行者が本来備えているビジネス常識、プロジェクトの記憶、品質意識を代替するためにAgentに提供する外部知識体系です。記憶の蓄積がないことを論じた際にすでに重要な問題を指摘しました。外部化された知識は自動的には更新されません。三ヶ月前に書いたspecが誰にもメンテナンスされていなければ、すでに現在のコードと整合していない可能性があります。

ここで記憶の不在と結果への無自覚という二つの特性が重なり、危険な組み合わせが生まれます。Agentは毎回のセッションでこれらのドキュメントからやり直しますが、ドキュメントが古くなっているかどうかを判断する能力がありません。同時に、ドキュメントの妥当性を自ら疑うこともしません。古くなったspecがAgentに現在の要件から乖離したコードを生成させ、そのコードがマージされると後続のAgentの参照基準になり、偏差が閉ループの保護の下で制度化されます。閉ループは本来品質を保障するはずですが、このシナリオではかえって誤りを固定化してしまいます。

そのため閉ループには対になる原則が必要です。規約、テスト、プロセスドキュメントはすべて、プロジェクトの進化に合わせて継続的に更新・反復される必要があります。改善は閉ループの外にある追加作業ではなく、閉ループが生き続けるための必要条件です。

closed-loop control と持続的な改善。これが本書における harness engineering の完全な定義です。一つのAGENTS.mdファイルでもなく、ツールセットでもなく、Agentの構造的特性に対応して設計されたエンジニアリング体系です。

この定義は業界の既存の実践と一致しています。HashiCorp共同創業者のMitchell Hashimotoが harness engineering という言葉を最初に使い、その核となる手法はAGENTS.mdでAgentの挙動を導き、プログラマブルなツールでAgentの出力を自己検証させることでした。OpenAIは三人チームが百万行のコードを生成した事例でharnessを「Agentを取り囲む完全なシステム」と定義しました。Martin Fowlerはharnessをguides(前方制御)とsensors(フィードバック制御)に分解しました。これらの実践はすべて正しいことをしています。AGENTS.mdは規約の一形態であり、検証ツールは閉ループの一構成要素であり、Fowlerの分解は閉ループ構造の一つの表現です。本書が提供するのは、これらの実践の背後にある分析フレームワークです。各コンポーネントがどの構造的課題に対応しているかを理解し、自分の体系が十分かどうかを判断し、新しいシナリオに直面したときにどう調整すべきかを知るためのものです。

全書ロードマップ

全書は生産性の階段に沿って展開し、各巻が一つの飛躍段階に対応します。

第一巻は信頼性を解決します。Agentの前に座って一問一答するスタイルは変わりませんが、出力は運任せからエンジニアリング的なデリバリーに変わります。規約の章では、曖昧な意図をAgentが精確に実行できる入力に変える方法を扱います。検証の章では、自動化手段で出力が意図に合致していることを証明する方法を扱います。この二章を習得すれば、単一のインタラクション層で閉ループが確立されます。

第二巻は規模を解決します。閉ループが確立されて初めて、Agentに自律的な実行を任せることが可能になります。閉ループのない自律実行はYOLO modeであり、破綻は確実です。第四章では長時間の実行におけるコンテキスト管理とクロスセッションメモリを扱い、一つのAgentが重要な情報を失わずに複雑なタスクを継続的に推進できるようにします。第五章ではマルチAgentの並列処理に拡張し、分離と統合の問題を解決します。あなたの役割はリアルタイムのオペレーターからタスクの設計者・検収者へと変わります。

第三巻は組織を解決します。個人の効率がボトルネックでなくなった後、ボトルネックはチームレベルに移行します。分業、プロセス、役割定義はすべて人間の実行速度を前提に設計されており、Agent時代のリズムに合わせて再設計する必要があります。第一巻と第二巻で確立したエンジニアリングプラクティスが組織レベルの協働の基盤インフラとなります。この基盤インフラなしには、チームレベルのAgent協働は成り立ちません。

三種類の読者がそれぞれ異なる入口から始められます。エンジニアで、自分でコードを書くスタイルからAgentにコードを書かせるスタイルへ移行中であれば、第一巻から始めて生産性の階段を順に上ってください。プロダクトマネージャーやプログラミング初学者で、すでにvibe codingで動くプロダクトを作った経験があれば、第一巻の規約と検証がすぐに役立ちます。技術リーダーで、チームのAIトランスフォーメーションを推進中であれば、まず第三巻で組織レベルの課題を把握し、その後第一巻と第二巻に戻って組織変革を支えるエンジニアリング基盤を理解するのがよいでしょう。


Harness Engineering Playbook · AgentsZone Community

results matching ""

    No results matching ""