リカバリ戦略
エージェントに対して、問題が発生した際の明示的な計画を提供します。出力の検証やツールのエラーのキャッチによって失敗を検出し、調整を伴う再試行、代替パスへのフォールバック、部分的なアクションのロールバック、またはエスカレーションを行います。無限ループやコストの急増を防ぐために再試行回数を制限し、アクションを冪等(べきとう)にし、一時的な失敗と永続的な失敗を区別します。目標は、クラッシュやサイレントな誤り(誤った結果をそのまま出力すること)を避け、段階的に機能を縮小(グレースフルデグラデーション)させることです。
課題
エージェントは常に失敗に直面します。ツールのタイムアウト、APIのエラー、モデルによる不正な形式の出力、計画の行き詰まり、そして複数ステップのワークフローによる部分的な副作用の残存などです。明示的なリカバリパスがなければ、エージェントは最初のエラーでクラッシュするか、さらに悪いことには、不正なデータに基づいて処理を強行し、自信ありげに誤った結果をサイレントに出力してしまいます。単純な再試行ループは状況を悪化させ、失敗している依存先に負荷をかけ続け、トークンを浪費し、無限に回り続けます。難しいのは、単一のエラーをキャッチすることではなく、それがどのような種類の失敗であるかを判断し、どのアクションをとるのが安全かを決定することです。
適用対象
このパターンは、外部ツールの呼び出し、複数ステップの計画の実行、または部分的な完了が発生し得る重要なアクションを実行するすべてのエージェントで使用します。これは、人間がリアルタイムで監視しない長期実行型または自律型のワークフローや、盲目的な再試行によって処理が重複する可能性がある副作用を伴うアクション(支払い、書き込み、メール送信など)において最も重要です。このパターンは、何らかの規約(コントラクト)に照らして出力を検証できること、および少なくとも一部の操作を冪等にできるか、または補償トランザクションを実行できることを前提としています。1回限りの読み取り専用で、リスクの低いプロンプトにはあまり適していません。
解決策
リカバリを、エージェントの通常の実行を囲むレイヤーとして、第一級の制御ループとして扱います。すべてのツール呼び出しとモデル出力は検証ゲートを通過します。例外やタイムアウトをキャッチし、出力を信頼する前にスキーマや規約(コントラクト)に照らしてチェックします。失敗した場合は、それを分類します。一時的な失敗(タイムアウト、レート制限、5xxエラーなど)に対しては、指数バックオフとジッターを伴う制限付きの再試行を行います。これは、重複リクエストが無害になるよう、理想的には冪等な操作に対して行います。永続的な失敗(無効な引数、認証エラー、規約違反など)は、再試行をスキップして、別のツール、よりシンプルな計画、またはフォールバック回答などの代替手段に直接移行します。\n\n進捗が重要な場合は、状態のチェックポイントを作成し、エージェントが最初からやり直すのではなく、最後に正常だったステップから再開できるようにします。あるステップですでに副作用が発生しており、それ以上進められない場合は、補償アクションを実行してロールバックします(注文のキャンセル、下書きの削除、課金の取り消しなど)。ループ全体を、最大試行回数、最大実時間、コスト上限などの厳格な予算(バジェット)で囲み、失敗し続ける依存先への呼び出しを停止するサーキットブレーカーも導入します。すべてのリカバリ手段が尽きた場合は、推測で動くのではなく、対応に必要な十分なコンテキストとともに、人間または監視エージェントに失敗を明確にエスカレーションします。
コンポーネント
メリット
- エージェントは、クラッシュしたり自信ありげにゴミデータを返したりする代わりに、部分的な結果やフォールバック結果、および明確なステータスを出力します。
- 試行回数、時間、コストに対する厳格な制限により、制御不能な再試行ループが失敗している依存先に対して予算を浪費するのを防ぎます。
- 補償アクションとチェックポイントにより、ワークフローが途中で停止した場合でも、外部システムとタスクの状態の一貫性が維持されます。
- リカバリに失敗した場合、エージェントは推測で動くのではなく、人間や監視者が対応するために十分なコンテキストを提供して引き継ぎます。
リスク
- 負荷がかかっている依存先に対する過剰な再試行は負荷を増大させ、一時的な不具合を連鎖的なシステム障害へと発展させる可能性があります。
- リクエストキーを使用しない場合、冪等ではないアクションを再試行すると、二重課金、二重送信、または二重書き込みが発生する可能性があります。
- 性急すぎるフォールバックはシステム的な障害を隠蔽してしまうため、壊れたツールが正常に動作しているように見えながら、裏ですべての結果の品質を低下させる原因になります。
- ロールバックロジックは不完全であることが多く、それ自体が失敗することもあるため、検出が困難な不整合な状態にシステムが取り残される可能性があります。
非推奨のケース
- 副作用がなく、複数ステップの計画もない低リスクのプロンプトの場合、単純な「再試行または失敗」で十分であり、完全なリカバリ機構はオーバーヘッドになります。
- 失敗の原因がタスクの実行が本質的に不可能であること(権限不足、非推奨のAPIなど)である場合、再試行やフォールバックは時間の無駄です。速やかに失敗(フェイルファスト)させ、エスカレーションしてください。
- 副作用が不可逆であり、冪等にできない場合は、それをまたぐ自動再試行は行わないでください。代わりに、確認や人間の承認を求めるようにします。
テクノロジー
事例
- 調査エージェントの検索ツールが503エラーを返した際、エージェントはバックオフを伴う再試行を行い、3回目の試行で成功し、実行をクラッシュさせることなく処理を継続します。
- コード生成エージェントがスキーマ検証に失敗するJSONを生成した際、検証ゲートはそれを拒否し、不正な形式のデータを後続の処理に渡す代わりに、エラー内容を含めて再プロンプトを実行します。
- 予約エージェントがフライトを予約したものの、ホテルの予約ステップで永続的な失敗が発生した際、補償ハンドラーは中途半端な予約状態のまま放置するのではなく、フライトの予約をキャンセルしてエスカレーションします。
本番環境での実績
- コンテキスト
- 57日間にわたり観察されたシングルオペレーター、ローカルファーストのOpenClawデプロイメント(161セッション / 2,776ターン)。エージェント自身のトラジェクトリトレースから集計。
- シナリオ
- 自律的なターンにおけるエラー、中断、タイムアウトは、再試行/バックオフおよびモデルフォールバックチェーンによって吸収され、エージェントは実行を継続します。
- テクノロジー
- 指数バックオフとジッターを伴う retryAsync、runWithModelFallback、中断(abort)の伝播、および再実行ループに対するcron自己保護。
- 負荷
- 2,942回のターミナルターン。52件のエラー、126件の中断、120件のタイムアウト、31件のプロンプトエラーを観測。
- 結果
- 2,942ターン全体で1.77%のターミナルエラー率。リカバリプリミティブが一時的な失敗を吸収し、デプロイメントは98.8%のセッション成功率を維持しました。シングルオペレーター、ローカルファーストのデプロイメント。
KPI
- リカバリ成功率
- 人間の介入なしに、再試行またはフォールバックによって自動的に解決された失敗の割合。健全な状態では、この値は高く安定しており、気づかないうちに低下することはありません。
- 成功タスクあたりの平均試行回数
- 成功するまでに必要な試行回数。この値の増加に注意してください。増加している場合は、真のリカバリではなく、依存先の品質低下を示唆しています。
- 無限ループ/予算超過率
- 実行が再試行、時間、またはコストの上限に達する頻度。これは稀であるべきであり、急増している場合は制限値や分類の調整が必要です。
- 補償完了率
- 失敗した複数ステップのワークフローのうち、一貫した状態で終了した割合。目標は、孤立した副作用を残さない完全なロールバックです。
観察された失敗パターン
- 試行回数の上限がない、または高すぎる場合、エージェントは永続的な失敗を無限に再試行し続け、コストを浪費して一向に進捗が得られなくなります。
- 永続的なエラーを一時的なものとして扱うと再試行が無駄になり、一時的なエラーを永続的なものとして扱うと、早期に諦めすぎて不要なフォールバックを誘発します。
- フォールバックパスが、リカバリが発生したというシグナルなしに、もっともらしいが誤った回答を返すと、後続のコンシューマーがその不正な出力を信頼してしまいます。
- 書き込みや外部アクションの後、補償処理が実行される前にエージェントが失敗し、重複したレコードや宙に浮いたレコードが残ってしまいます。
得られた教訓
- 再試行、フォールバック、エスカレーションの決定は、一時的なものか永続的なものかによって決まります。バックオフ曲線を調整する前に、明確な分類に投資してください。
- 冪等性キーは、リスクのある再試行を安全なものに変えます。後から重複排除を付け足すのではなく、最初からそれを考慮して設計してください。
- 試行回数、時間、コストに対する厳格な上限設定は必須です。これらがないエージェントは、最終的に無限に実行され続ける方法を見つけ出してしまいます。
- すべての再試行、フォールバック、補償処理をログに記録し、サイレントな品質低下が突然のインシデントではなく、メトリクスとして表面化するようにします。
FAQ
- 単に try/except と再試行ループを追加することと、何が違うのですか?
- Try/except は単一のエラーを処理します。一方、リカバリ戦略は、失敗の種類を判断し、厳格な予算制限のもとで再試行、フォールバック、ロールバック、エスカレーションの中から選択します。本質は例外処理ではなく、制御ロジックと冪等性にあります。
- 再試行は何回まで許可すべきですか?
- 少数です。通常は、指数バックオフとジッターを伴う小さな固定上限を設定し、それとは別に時間とコストの上限を設けます。正確な回数は依存先によって異なりますが、ループは必ず終了する必要があり、永続的な失敗に対しては一切再試行すべきではありません。
- アクションを取り消すことも、冪等にすることもできない場合はどうすればよいですか?
- そのアクションをまたぐ自動再試行は行わないでください。不可逆なステップの前にチェックポイントを設定し、失敗した場合は推測で動くのではなく、人間または監視エージェントにエスカレーションします。不可逆性とは、再試行を強化するのではなく、処理を慎重に進めるべきというシグナルです。