Circuit Breakerと前述のリトライ戦略記事で触れた「単一タスクの総コスト上限」は、どちらも損失を制限しているように聞こえますが、両者は具体的にどう分業していますか?
両者の分業の核心は「作用範囲が異なる」ことにあります。単一タスクの総コスト上限はタスクレベルの境界であり、Circuit BreakerはAgentまたはサービスレベルの境界です。両者は重ねて使用され、互いに代替するものではありません。
単一タスクの総コスト上限の作用範囲:「今回のタスク」のみを制限します——例えばあるタスクのリトライ回数と累積コストの合計が$5を超えられないなど、あるタスクがこの上限に達すると、そのタスクは中止され失敗としてマークされますが、次の新しいタスクは新しいカウントであり、今回のタスクが上限をトリガーしたことの影響を受けず、システム全体(このAgent・このサービス)は依然として正常動作とみなされます。
Circuit Breakerの作用範囲:単一タスクではなく「このAgentの過去一定期間の全体的なタスク失敗パターン」を対象とします——複数のタスクが連続して同じ理由でコスト上限やリトライ上限をトリガーした場合、これは「今回のタスクの運が悪かった」のではなく、このAgent自体、またはそれが依存する何らかの基盤サービス(MCP Server・外部APIなど)に構造的な異常が発生していることを示します。Circuit Breakerはこの種のタスクをまたぐパターンを監視し、検知すると現在の1つのタスクだけを中止するのではなく、人的介入が問題の解決を確認するまでこのAgentの以降のすべての実行能力を一時停止します。
具体的な分業ロジック:単一タスクのコスト上限は「今回のタスク自体の異常消費」を遮断する責任を負い、単一タスクが不合理なコストを燃やすのを防ぎます。Circuit Breakerは「複数タスクの失敗パターンが反映する構造的な問題」を検知する責任を負い、すでに壊れているAgentが、それぞれコスト上限に遮断されながらも合計すると大量の損失と無駄な試行を引き起こす一連の失敗タスクを継続的に生成し続けることを防ぎます。単一タスクのコスト上限を第一層の防御(単一タスクの異常を防ぐ)、Circuit Breakerを第二層の防御(「単一タスクの防御が繰り返し失敗し続ける」というより大きな構造的問題を防ぐ)と考えることができます——両者を重ねることで初めて「単発の事故」と「構造的な故障」という異なるスケールのリスクを同時に処理できます。
Circuit BreakerがOpen状態に入りAgentの実行を一時停止した後、「人的介入で問題が解決したことを確認する」という段階では具体的に何をすべきですか?しばらく待てば自動的に復旧するだけではダメですか?
単純に「しばらく待てば自動的に復旧する」(人的介入不要)というのは、実はCircuit BreakerのHalf-Open状態設計に対応しますが、Half-Openの自動復旧が適用されるのは「問題が一時的なもので自動試験する価値がある」というシナリオであり、Open状態をトリガーするすべてのシナリオが自動復旧に完全に依存するのに適しているわけではありません。理由は次の通りです。
Half-Open自動復旧が適用されるシナリオ:Open状態のトリガー原因が「ある外部APIが短時間不安定になりエラー率が急上昇した」のような、本質的に一時的で外部要因によるものであれば、Half-Open状態を使った自動化された小規模な試験(クールダウン時間を待ち、少量のテストリクエストを送信し、成功すれば自動的にClosedに戻る)は合理的です。この種の問題は待機後に自然に解決する確率が確かに高く、毎回人的確認を待つ必要はありません。
人的介入が必須で自動復旧だけに頼れないシナリオ:Open状態のトリガー原因がプログラムロジック自体のバグである可能性、または資金安全に関わる異常(前述の記事で議論した、あるSub-agentに異常な資金移動パターンが現れるなど)を含む場合、この種の問題は「しばらく待つ」だけでは自動的に消えません。Half-Openの自動試験メカニズムだけに頼ると、実際に問題のあるシステムがOpenとHalf-Openの間を繰り返し行き来し、継続的に復旧を試みながらも根本的な問題を真に解決できないままになりかねません。この状況では真の修復には人的介入が必須です。
具体的な人的介入で何をすべきか:Circuit Breakerをトリガーした具体的なログとデータを確認する(前述のリトライ戦略記事で議論した、状態オブジェクトが十分なデバッグフィールドを保持すべきというのは、まさにここで重要な診断根拠になる)。トリガー原因が一時的(直接手動で復旧するかHalf-Open自動試験を有効にできる)か構造的(コードを修正するか戦略を調整してから安全に復旧できる)か判断する。構造的な問題と判断される場合、待機時間が予想より長くなっても、実際に修正がデプロイされるまでAgentの実行能力を復旧すべきではありません。
実務上一般的な階層的設計:多くの成熟したシステムの方法は、トリガー原因を分類することです——「既知の、過去に通常一時的であると証明されているエラータイプ」(ネットワークタイムアウトなど)はHalf-Open自動試験を許可します。「未知の、または過去に通常人的診断が必要と証明されているエラータイプ」(資金移動の異常・大量の形式エラー出力など)は、Open状態からの復旧に人的介入を強制的に要求し、Half-Open自動試行を許可しません。この分類自体も、Circuit Breakerのトリガー履歴に基づいて経験を継続的に蓄積し動的に調整するプロセスです。
私のAgentシステムが複数の異なるユーザーに同時にサービスを提供する場合(SaaS化されたAgentプロダクトなど)、Circuit Breakerはグローバルに1つを共有すべきか、それともユーザーごとに独立させるべきですか?
ユーザーごと(あるいはより正確には独立した実行環境ごと)に独立したCircuit Breakerを持つべきで、グローバル共有すべきではありません。理由はグローバル共有が深刻な「連座」問題を生み、1人のユーザーの異常が他のすべてのユーザーを巻き込むためです。
グローバル共有Circuit Breakerの問題:Circuit Breakerが「システム全体のエラー率」を監視し、「各ユーザーそれぞれのエラー率」を別々に監視しない場合、よくある障害シナリオは——あるユーザーの使用シナリオがたまたま境界事例のバグをトリガーし(このユーザーが問題のあるカスタムMCP Serverに接続したなど)、このユーザーのタスクが継続的に失敗する。Circuit Breakerがグローバル共有されている場合、この単一ユーザーの異常なエラー率がシステム全体の平均エラー率を押し上げ、グローバルな遮断をトリガーし、結果として他のすべての本来正常に動作していたユーザーも一緒にサービス停止を強いられます——これは典型的な「一人が病気になると全員一緒に隔離される」という過剰な処罰シナリオであり、他の無関係なユーザーに不必要なサービス中断を引き起こします。
ユーザーごとの独立したCircuit Breaker設計:各ユーザー(より正確には各独立した実行環境または独立したリソース接続)がそれぞれ独立したエラー率・コスト消費統計を維持し、このユーザー自身の統計が閾値を超えた場合のみ、このユーザーのみに影響する遮断がトリガーされ、他のユーザーに波及しません。この設計は前述の最小権限項目で議論した「被害範囲に明確な上限が必要」という原則と呼応します——ただしここで制限されているのは単発操作の資金被害範囲ではなく「異常な1人のユーザーの影響範囲」であり、同様に分離設計で被害を最小範囲に制限しています。
追加で重ねるシステムレベルのCircuit Breaker:各ユーザー独立のブレーカーに加え、通常システムレベルのブレーカーの層も重ねられ、「システム全体の基盤インフラ」(データベース接続・コアLLM API呼び出し)に異常が発生していないか監視します。基盤インフラ自体に問題がある場合(単一ユーザーの個別シナリオによるものではない)、これは実際にすべてのユーザーに影響し、システムレベルのブレーカーがトリガーされシステム全体を一時停止させることは合理的な対応です——この層とユーザーレベルのブレーカーは監視対象とトリガー範囲が全く異なり、両者を重ねることで初めて「個々のユーザーの局所的な異常」と「システム全体のグローバルな異常」という異なるスケールの問題を同時に処理できます。
具体的な実装上の注意:ユーザーレベルのCircuit Breakerの状態(Closed/Open/Half-Open)は、ユーザーIDまたは実行環境IDごとに個別に保存・追跡する必要があり、単一のグローバル変数で全体の状態を記録してはいけません。これは実装上見落とされやすいですが、「連座問題が発生するかどうか」を直接決定する重要な詳細です。
マルチAgentシステムで、Orchestratorが呼び出す複数のSub-agentがそれぞれ独立したCircuit Breakerを持ち、そのうちの1つのSub-agentのブレーカーがOpen状態にトリガーされた場合、Orchestratorはこの状況をどう処理すべきですか?
この状況は前述のHandoff項目とマルチAgentエラー処理で議論した原則を拡張したものです。あるSub-agentが遮断されたときのOrchestratorの処理ロジックは「タスク全体を直接失敗させる」べきではなく、このSub-agentが全体のタスクで果たす役割に基づいて段階的な判断をすべきです。
ステップ1:このSub-agentに代替可能な経路があるか判断する。遮断されたSub-agentが担当する機能に他の利用可能なソースがあれば(前述のMCP Server項目で触れたシナリオ、市場データ照会機能がもともと主要とバックアップの2つの異なるMCP Serverに接続していたなど)、Orchestratorはタスク全体を失敗と判定する前にまずバックアップ経路への切り替えを試みられます——これには、事が起きてからバックアップがないと気づくのではなく、アーキテクチャ設計の段階で重要機能に代替経路をあらかじめ用意しておく必要があります。
ステップ2:代替経路がない場合、このSub-agentの役割がタスクの必須段階かどうか判断する。遮断されたSub-agentがタスク内の「あれば嬉しい」補助機能(「追加のセンチメント分析参考」でコアな決定根拠ではない)を担当している場合、Orchestratorはこの段階をスキップし「この部分の情報は一時的に取得できない」とマークして、タスクの他のコア部分を続行できます。遮断されたSub-agentがタスク内のコア段階(前述のHandoff項目の事例における「リスク評価」や「取引実行」といったSub-agentなど)を担当している場合、Orchestratorはスキップすべきではなく、タスク全体を中止し「重要な段階が利用不可のためタスク一時停止、人的介入が必要」とマークすべきです。
ステップ3:Orchestrator自身の状態記録は「どのSub-agentが遮断をトリガーしこの結果を引き起こしたか」を明確に反映すべき。前述の記事で議論したデバッグフィールド設計原則と呼応し、OrchestratorはSub-agentの遮断通知を受け取った後、この情報を完全に記録すべきです(どのSub-agentか、いつトリガーされたか、トリガー原因)。「タスク失敗」という漠然とした記録だけを残すのではなく——こうすることで人的介入の際、どのSub-agentに問題があったか直接特定でき、ゼロから調査し直す必要がありません。
この設計が呼応する核心原則:マルチAgentシステムでは、単一のSub-agentの遮断が自動的にシステム全体の遮断に等しいべきではなく、Orchestratorの役割はまさに「この局所的な異常が全体のタスクにどれだけの影響を与えるか」という判断と決定を下すことです——これは前述の記事で「Orchestratorは実行型権限を持つべきでない」が「調整決定権限は持つべき」と繰り返し強調してきた理由でもあり、Sub-agentの遮断のような異常シナリオに直面することこそ、Orchestratorという調整役割が価値を発揮すべき場面です。
あるマルチチェーン裁定Agentシステムの階層的Circuit Breaker設計事例
複数のチェーンにまたがって裁定機会を探すマルチAgentシステムは、Circuit Breakerを次のように設計しました。Sub-agentレベルのブレーカー——各チェーンの実行Sub-agentがそれぞれ独立したブレーカーを維持し、トリガー条件は「連続5回の取引失敗」または「1時間以内の累積Gasコストが$20を超える」で、いずれかの条件が満たされればOpen状態に入り、そのチェーンの実行能力を一時停止し、他のチェーンのSub-agentは影響を受けません。ユーザーレベルのブレーカー(これは複数ユーザーにサービスを提供するプラットフォームのため)——各ユーザーがそれぞれ独立したブレーカー統計を維持し、1人のユーザーの異常(問題のあるカスタムMCP Serverへの接続など)が他のユーザーのサービスを巻き込まないようにします。システムレベルのブレーカー——コアLLM APIの全体的な呼び出し成功率を監視し、短時間で成功率が大幅に低下した場合(個別のAgentやユーザーの問題ではなくLLMプロバイダー自体に問題がある可能性を示す)、システムレベルの遮断をトリガーし、プラットフォーム全体の自動実行能力を一時停止します。これはすべてのユーザーに影響する唯一のブレーカー層です。基盤の依存関係に問題がある場合、確かにすべてのユーザーが影響を受けるためです。Half-Openの差別化された設計——Sub-agentレベルのブレーカーでは、トリガー原因が「ネットワークやGas価格の変動といった既知の一時的要因」に分類されればHalf-Open自動試験を許可します(10分のクールダウン後、少額のテスト取引を試み、成功すれば復旧)。トリガー原因が「繰り返し発生する形式異常の取引レスポンス」(あるプロトコルのインターフェースに変更があり、コード調整が必要な可能性を示す)であれば、人的介入を必須とし、Half-Open自動試行は許可しません。実際の運用で発見された問題:エンジニアリングチームはローンチ初期、単一のグローバル共有ブレーカー設計を使用していました。あるとき、あるユーザーが応答速度が異常に遅いカスタムRPCノードに接続し、このユーザーのリクエストが継続的にタイムアウト失敗し、プラットフォーム全体のグローバルエラー率を押し上げ、すべてのユーザーに影響する遮断をトリガーし、多くの無関係なユーザーのサービス中断を引き起こしました。この事故により、チームは前述の3層独立ブレーカーアーキテクチャに再設計することになり、この事例はQ3で議論した「グローバル共有ブレーカーは連座問題を生む」という原則を具体的に裏付けています。
Circuit Breaker設計の核心的なトレードオフは「感度 vs 誤トリガーコスト」です。閾値を敏感に(低く)設定するほど、被害が拡大する前に本当の問題を早期に遮断できますが、正常な偶発的変動にも過剰反応しやすく、不必要なサービス中断をトリガーしユーザー体験に影響します。閾値を緩く設定するほど誤トリガーの確率は低くなりますが、本当の問題はより長く蓄積し、より多くの損失を引き起こしてから遮断される可能性があります。もう一つのトレードオフは「Half-Open自動復旧の利便性 vs 構造的問題が隠蔽されるリスク」です。より多くのシナリオでHalf-Open自動試験復旧を許可すると、人的介入の負担が減りシステム可用性が高く見えますが、自動復旧すべきでない構造的問題もHalf-Open自動試験の範囲に含めてしまうと、問題が繰り返しトリガーされながらも真に修正されず、OpenとHalf-Openの間を循環し続けるだけになりかねません。推奨:閾値設定は履歴データに基づいて動的に校正すべきです(正常な変動の統計分布を観察し、正常範囲から明らかに逸脱する位置に閾値を設定する)、感覚で数字を決めるのではなく。Half-Open自動復旧は「この種の問題は通常一時的」という歴史的証拠に裏付けられたエラータイプにのみ適用し、資金安全や未知のエラータイプに関わるものは一律人的介入を要求すべきで、人的負担を減らしたいがために安全境界を犠牲にすべきではありません。