【ITニュース解説】Our agent said "done" on 15% of tasks while the provider was failing
2026年10月05日に「Dev.to」が公開したITニュース「Our agent said "done" on 15% of tasks while the provider was failing」について初心者にもわかりやすく解説しています。
ITニュース概要
AIエージェントが「完了」と報告したタスクの15%は、実際は未完了だった。原因は、AIモデルではなくプロバイダーがエラー応答を正常に見せかけたため。エージェントは応答の終了をタスク完了と誤認していた。この課題に対し、プロバイダーの応答内容を詳細に検査し、真の完了を判断する仕組みを導入。システム開発では「完了」の厳密な確認が重要だ。
ITニュース解説
AltairというAIエージェントを開発しているチームは、エージェントが「完了した(done)」と報告したタスクの15%が実際には完了していなかったという問題に直面した。これは46のタスクのうち7つに相当する。エージェントがタスクを完了したと判断し、ユーザーにも「うまくいった」と見せかけていたにもかかわらず、その裏では処理が失敗していたのだ。この問題は、AIモデル自体の性能不足によるものではなく、AIモデルの応答を提供する「プロバイダー」と呼ばれるサービス側に原因があったと結論付けられた。
プロバイダーが引き起こした失敗パターンは主に3つあった。 1つ目は、「ゲートウェイのエラーテキスト」という形だ。これは、プロバイダーがHTTP 200という「通信が成功した」ことを示すステータスコードを返しながら、実際にはAIモデルからの回答ではなく、「リクエストを完了できませんでした。後で再試行してください」といった、プロバイダー自身のエラーメッセージを送ってくるケースである。エージェントはHTTP 200を受け取ったため、これをモデルからの正常な回答と判断し、ユーザーにそのエラーメッセージをまるでモデルの回答であるかのように表示してタスクを完了させてしまっていた。
2つ目は、「空のストリーム」というパターンである。プロバイダーはAIモデルからの回答をデータストリームとして少しずつ送ってくるが、このケースではプロバイダーが接続を長時間維持したにもかかわらず、最終的に何のデータも送らずに接続を切断してしまった。エージェントはストリームの終了をタスクの完了と判断するロジックを持っていたため、何の回答も得られないままタスクを「完了」と認識した。
3つ目は、特に複雑なタスクで発生した「モデルの無限ループとストリームの切断」だ。AIモデルが与えられたタスクに対して無限に推論を続け、回答を生成し続けるループ状態に陥ることがあった。このような無限ループを防ぐために、システムには一定の文字数を超えたらストリームを強制的に切断する「ループガード」が設けられていた。エージェントは、このループガードによって途中で切断されたストリームを、モデルからの「最終回答」と誤解し、タスクを完了と見なしていた。
なぜエージェントはこれらの失敗を見抜けなかったのか。エージェントの基本的な動作ロジックは、「モデルから回答が来たら、ツール呼び出しがなければ最終回答と判断しタスクを完了させる」というシンプルなものだった。このロジックでは「モデルが作業を終えた」ことと、「プロバイダーがツール呼び出しを含まない何らかのデータを送ってきた」ことを区別できなかった。さらに、これらの失敗ケースではすべてHTTP 200という「成功」コードが返されていたため、エージェントは通信エラーとは判断せず、再試行したり、バックアップのプロバイダーに切り替えたりすることもなかった。
この問題を検出する上で重要な手がかりとなったのが、プロバイダーがリクエストを処理する際にカウントする「入力トークン数」だった。ログ記録用のプロキシ(代理サーバー)がプロバイダーの入力トークン数を確認したところ、ある「回答」ではわずか4,552トークンしかカウントされていなかったが、エージェントが送ったリクエスト全体の合計は約9,300トークンもあった。これは、プロバイダーがリクエスト全体を半分も読んでいないにもかかわらず、何らかの「回答」を返していたことを示しており、プロバイダー側の不正な挙動を明確に示唆していた。
このような問題を解決するため、チームは新たな検出ロジックを導入した。エージェントは、ツール呼び出しを含まないすべての回答に対して、詳細なチェックを行うようになった。具体的には、ストリームがループガードによって切断された場合、テキストもツール呼び出しもない空の回答の場合、短いメッセージでプロバイダーのエラーを示す特定のフレーズが含まれる場合、そしてプロバイダーがリクエスト全体の半分未満しか読んでいないと判断できる入力トークン数の場合、その回答を不正なものとして判断する。
これらの条件に合致する「不正な回答」が検出された場合、エージェントはそれを通信接続が切れたときと同じように例外として扱い、自動的に再試行したり、設定されている場合はバックアップのプロバイダーに切り替えたりする。この新しい仕組みには、プロバイダーのエラーテキストがユーザーに表示されないよう、回答の最初の160文字程度を一時的に保持する工夫も含まれる。また、エラーフレーズの検出は短い回答でのみ有効とし、無限ループが検出された場合も、一度だけ低い推論レベルで再試行し、それでもループするようであれば正直にエラーとして報告するようにした。
この問題解決策を検討する中で、「タスクが完了した」後に、別のAIモデルを「第二のレビューア」として使って結果をチェックすることも試みられた。レビューアはタスクの内容や関連ファイルを見て、問題点を報告し、エージェントがそれを修正するというものだ。しかし、この方法はあまり効果がなかった。レビューアを使うことでコストが最大3.4倍に跳ね上がるにもかかわらず、実際に修正されたタスクはごくわずかだった。多くの指摘は誤検出であり、無駄なコストだけがかかっていた。この理由は、AIエージェント自体が既に高い精度でタスクを解決できていたことと、レビューアはAIモデルの回答内容しか見ることができず、プロバイダー側で発生したインフラレベルの障害は全く検出できないためである。
別の実験として、あるプロバイダーに対して長期間にわたり、一定間隔で同じ規模のリクエストを送信するテストも行われた。このテストでは、「エラーを回答として偽装する」ような挙動は確認されなかったものの、プロバイダーの応答速度が数時間にわたって大幅に低下する「スラッシュ」現象が確認された。このような状態では、リクエストを再試行しても効果がなく、バックアッププロバイダーへの切り替えが不可欠であることが示唆された。また、リクエストのタイムアウト設定は、「全体のリクエスト時間」に対してではなく、「データが途切れるまでの時間(サイレンス)」に設定する方が、途中で処理が遅くなっても最終的には正常な回答を得られることがわかった。
この経験から得られた最も重要な教訓は、「タスクが完了した」という報告は「要求が受け入れられた」ことを意味せず、その手前で「本当に回答があったのか」をインフラレベルで確認する必要があるということだ。ストリームの終端がタスクの終端であるとは限らず、空の回答、途中で切れた回答、プロバイダーがリクエストを十分に処理していないのに送られてきた回答は、すべて失敗として処理されなければならない。HTTP 200という成功を示すステータスコードも万能ではなく、プロバイダー自身の内部エラーが通常のAIモデルの回答であるかのように送られてくることがある。このような場合、プロバイダーが実際にリクエストをどれだけ処理したかを示す入力トークン数は、信頼できる検出器となる。最終的に、「完了」のチェックはAIモデルを使うような高度な問題ではなく、エンジニアリングによってプロバイダーの応答を細かく検証し、作業後のテストを必ず行い、不正な挙動に対しては正直にエラーを報告する、という地道な対策が最も効果的であることがわかった。プロセスを盲目的に信頼するのではなく、常に結果を測定し、検証することが不可欠である。
ただし、この検出システムにも限界はある。検出に用いるゲートウェイエラーフレーズのリストは完全ではなく、入力トークン数の閾値も特定のデータで調整されたヒューリスティックなものだ。異なるプロバイダーでは、また別の形で失敗する可能性がある。また、「要求が受け入れられたか」という、ユーザーの期待に沿った動作が実現されたかという点については、まだ今後の課題として残っている。今回の対策は「タスクがそもそも完了したか」という問題を解決したに過ぎない。さらに、実験のサンプルサイズが比較的小さく、プロバイダーの負荷状況によって問題の発生頻度が大きく変動するため、一概に結論付けることは難しい側面もある。