意図アラインメント:Vibe Codingはなぜ失敗するのか

「発注者」として他のチームに仕事を外注した経験があれば、ソフトウェア開発であれ自宅のリフォームであれ、おそらく一つ明確な実感をお持ちでしょう。どれほど優秀な外注チームを迎えても、外注タスクの推進は遅く、苦痛を伴います。ボトルネックは外注チームの能力にあるのではなく、チームがあなたの意図を完全に理解しているかどうかにあるからです。異なる人間の間で意図をアラインメントすることは極めて困難な作業であり、どんな些細な見落としや偏差、あるいは単純な「常識」の理解の違いでさえ、致命的な結果を招きかねません。AI Codingという営みは、ソフトウェア開発というよりも、むしろ技術力の高いソフトウェア外注を雇ったことに近いものです。構造化された手段を通じて、自分の意図を可能な限り損失なくAgentに伝達しなければ、望む結果を得ることはできません。本章ではこの問題の診断から始め、情報の階層化と構造化された次元の方法論フレームワークを確立し、そのフレームワークを使ってAgentが実行できるspecをイテレーティブに作成する方法を示し、最後に実際のプロジェクトワークフローですべてを結びつけます。

対話モードの三つの構造的失敗

おそらく、こんな段階を経験したことがあるでしょう。Agentを開き、自然言語で要件を伝えると、数分でコードが出てきます。動かしてみて、二回ほど修正すれば使えるようになります。どんどん多くのタスクをAgentに任せるようになり、以前なら二日かかっていたものを一午後で片付けられるようになります。Vibe Codingの初期体験は確かに素晴らしいものです。

問題は一度に現れるわけではありません。

五回目の対話で、ある制約を伝えました。「すべてのAPIレスポンスにはerror codeフィールドを含めること。」Agentはその通りに実装しました。ところが二十回目の対話で新しいインターフェースの追加を依頼すると、生成されたコードからerror codeフィールドが消えていました。テスト時にようやくこの問題に気づきます。対話履歴を遡ると、その制約はまだそこにあります。しかし間に十五回分の別の機能に関する議論が挟まっていました。Agentが二十回目のコードを生成した時点で、五回目のその制約は注意力の配分において優先度が低くなっていたのです。

これはVibe Codingの最も一般的な失敗パターンの一つです。初期の指示が後続の対話内容によって、Agentの有効な注意力の範囲から押し出されてしまいます。あなた自身はその制約を覚えていて、Agentも覚えていると暗黙に期待します。しかしAgentの注意力は対話全体に均等に分配されているわけではありません。研究によると、LLMは長文を処理する際に冒頭と末尾への注目度が高く、中間部分が無視されやすい傾向があります(この現象はlost in the middleと呼ばれています)。あなたの制約が大量のコード出力と後続の議論に挟まれていた場合、Agentは実質的にそれを「見えていない」可能性があります。

二つ目の失敗パターンはより目立ちにくいものです。最初はSQLiteをストレージに使うと伝え、途中で並行書き込みのサポートが必要になり、PostgreSQLに変更すると言い直しました。あなたにとっては明確な意思決定の変更であり、後の指示が前の指示を上書きするものです。しかしAgentが見ているのは、タイムライン上の二つの意思決定ポイントではありません。Agentが見ているのはフラットなtoken列であり、その中に「SQLiteを使う」と「PostgreSQLを使う」という二つの指示が同時に存在しており、どちらがもう一方より優先度が高いという情報はありません。

結果として、Agentは後続のコードで二つのデータベースの書き方を混在させるかもしれません。接続プールの設定はPostgreSQLに従っているのに、あるヘルパースクリプトではまだSQLiteのAPIを呼び出しています。さらに厄介なのは、レビュー時にこの種の問題を発見しにくいことです。各コードを個別に見ればどれも妥当であり、矛盾は全体を俯瞰してはじめて見えてくるからです。

人間にとって、対話にはタイムラインがあり、コンテキストがあり、暗黙の優先順位関係があります。後から言ったことが先に言ったことを上書きする、これは人間同士のコミュニケーションの基本的なデフォルトです。LLMにとって、こうした暗黙のルールは存在しません。対話全体がtokenの列であり、前のものと後のものは注意力メカニズムにおいて同等の地位にあります。二つの指示が矛盾した場合、Agentにはどちらに従うべきかを判断する信頼できるメカニズムがありません。

三つ目の失敗パターンは対話の長さに直接関係しています。Agentとの対話が十分に長くなり、contextが上限に近づくと、Claude CodeやCodexといったツールは自動的にある処理を行います。それがcompactionです。システムが初期の対話を要約に圧縮し、重要だと判断した内容だけを残して、新しい対話のための空間を確保します。

compactionの問題は、何が重要で何が重要でないかを決めるのがシステムであって、あなたではないということです。対話の前半で二十分かけて説明したアーキテクチャ上の制約が、compaction後に一文に圧縮されるかもしれませんし、完全に消えてしまうかもしれません。しかも「先ほど言及されたある制約がcontextから削除されました」という通知は一切ありません。あなたは対話を続け、要件を伝え続け、Agentはコードを生成し続けます。出力されたコードがその制約に違反していることに気づいて、はじめて情報が失われたと認識するのです。

これは前述の注意力の減衰とは異なります。注意力の減衰は、情報がまだcontextの中にあるものの、Agentが気づかなかったということです。compactionは、情報が直接削除されており、Agentが注意を払おうにも払えないということです。一方は「見えにくい」、もう一方は「見えない」です。

これら三つの失敗パターンは異なる現象に見えます。制約の無視、指示の矛盾、情報の喪失。しかし共通の根本原因があります。

あなたの意図は対話の中に存在しています。そして対話は、膨張し、自己矛盾し、能動的に内容を破棄する媒体です。対話が一回進むたびに、初期の意図はさらに遠くへ押しやられます。対話が十分に長くなると、システムは一部の内容を能動的に削除さえします。あなたとAgentの間の意図アラインメントは、絶えず流失する基盤の上に成り立っているのです。

Context制約下の情報アーキテクチャ

序章で述べたように、Agentには三つの構造的特徴があります。非決定性、永続的な記憶の欠如、自己検証の不能です。「意図をAgentにどう伝えるか」という具体的な問題に対して、最も核心的な制約はそのうち二つの組み合わせです。contextの有限性(永続的な記憶の欠如の延長)と、注意力の不均一性(情報の実際の受信品質に影響する要因)です。

もしこの二つの制約が存在しなければ、意図アラインメントは単純な問題になります。プロジェクトのすべてのドキュメント、すべてのコード、git履歴全体、設計議論の記録のすべてをAgentに渡せば、それをすべて消化し、完璧に実行します。プロジェクト開始時に一度アラインメントを取るだけで済みます。

現実にはそれはできません。現在の主流モデルのcontext windowは128Kから1Mトークンまで幅があり、一見すると大きく見えます。しかし中規模のプロジェクトでは、数万行のコードにドキュメントと設定ファイルを加えるだけで数十万トークンに簡単に達します。さらに対話履歴とAgent自身の思考プロセスが加わると、空間はすぐに逼迫します。そして前述したように、情報がcontext windowの範囲内にあっても、注意力の分布は均一ではありません。追加する情報が増えるほど、各情報が実際に得られる注意力は減少します。この関係は線形ではありません。ある閾値を超えると、情報を追加してもアラインメントの助けにならないどころか、むしろ妨げになります。本当に重要な情報がノイズに埋もれてしまうからです。

Ryanは自身のAI agentプラットフォームAnyClaw の開発中、最初に直面したのがまさにこの問題でした。同一のcontext内で複数の機能ポイントを扱うと、機能間の情報が互いに干渉することに気づいたのです。ある機能のspecに記載されたモジュール名、変数名、設計制約が、別の機能の実装に「漏れ出す」現象が起きました。Agentの注意力が複数の機能ポイント間を行き来し、各機能に割り当てられる有効な注意力が不足していました。彼はこう述べています。「コンテキストウィンドウがどんどん大きくなっているとはいえ、冗長な情報が多すぎると注意力が散漫になり、ドリフトが起きる。」

この問題は小規模プロジェクトでは目立たないかもしれません。数百行のコード、二、三個のモジュールであれば、すべての情報を合わせてもcontextのごく一部しか占めず、Agentの注意力は十分に余裕があります。しかしプロジェクトが一定の規模に達すると、数千行のコード、数十のモジュール、複数の関心事にまたがるようになると、同じ現象が観察され始めます。Agentは作業中に「注意が逸れ」始め、前の制約が後の情報に押し出され、出力があなたの期待から外れていきます。

この制約が、意図アラインメントをコミュニケーションの問題から工学的な問題へと変えます。すべての意図を一度にAgentに流し込んで、すべてを消化してくれることを期待するわけにはいきません。一連の設計上の意思決定が必要です。どの情報をcontextに入れ、どれを外に置くか。どの情報を冒頭に(注意力が高い位置に)配置し、どれを後方に置くか。どの情報を毎回ロードし、どれを現在のタスクで使う時だけロードするか。どの粒度の情報をAgentに与えるか。粗すぎると正確に理解できず、細かすぎると注意力が分散します。

これらの意思決定を合わせると、一つの情報アーキテクチャを構成します。このアーキテクチャの目標は、有限のcontextと不均一な注意力の下で、Agentが各実行段階で本当に必要な意図情報を受け取れるようにすることです。

現在コミュニティで主流のspec駆動開発フレームワークは、方法論の面では大きな違いがありますが、この点において驚くほど一致した設計判断をしています。いずれもcontextにロードする情報に対して厳格な制限を設けているのです。OpenSpecはプロジェクトコンテキストを50KBに制限しています。AILock-Stepは200行に制限しています。BMADは毎回現在のステップのドキュメントのみをロードし、複数ステップの同時ロードを禁止しています。Spec Kitは各フェーズでそのフェーズに必要な成果物のみをロードします。四つの独立して進化したシステムが、ほぼ同じ意思決定をしています。これは、context管理がこの分野において避けて通れない核心的な問題であることを示しています。

以降の内容は、この情報アーキテクチャを中心に展開します。次のセクションでは最も基本的なステップから始めます。意図を対話から外部化してドキュメントにし、構造によって曖昧さを排除することです。

results matching ""

    No results matching ""