F-1: 同期 vs 非同期¶
この相反は何か¶
エージェントへのリクエストを同期的に(レスポンスが返るまで呼び出し元がブロックして待つ)処理するか、非同期的に(ジョブIDを即座に返し、完了を別経路で通知する)処理するかという二者択一です。これはアーキテクチャの最も基礎的な分岐点であり、後続のほぼすべての設計判断に影響を及ぼします。
この選択が二者択一である理由は、呼び出し元との通信プロトコルとインフラが根本的に異なるためです。同期ではHTTPリクエスト-レスポンスサイクル内で完結し、状態はインコンテキストで足ります。非同期ではジョブキュー・チェックポイントストア・結果通知メカニズムが必要になり、運用・デバッグ・テストの複雑性が一段上がります。「中間」は存在しますが、それ自体が独立したパターン(A3 同期ファサード)であり、内部的には非同期パイプラインの上に同期的な外観を被せる構成です。
AIエージェント固有の事情として、LLM呼び出しはレイテンシのばらつきが大きく(F12)、1リクエストが長い(F1)という特性があります。従来のWeb APIでは「概ね100ms以内に返る」と仮定できましたが、エージェントでは数秒から数十分までレイテンシが分布します。この特性により、同期/非同期の選択がシステム設計の最初の分岐点として不可避になります。
選択肢A:同期¶
同期処理では、クライアントがHTTPリクエストを送信し、処理が完了するまで接続を維持し、レスポンスとして結果を受け取ります。状態管理はインコンテキスト(リクエストスコープ内の変数)で完結し、ジョブキューもチェックポイントストアも不要です。
同期の最大の利点は単純さです。デバッグはスタックトレースを追えば足りますし、テストは関数呼び出しの入出力を検証するだけです。デプロイもステートレスなHTTPサーバとして扱えます。運用上の可動部が最も少ないため、障害の原因特定も容易です。
しかし同期には厳しい制約があります。クライアントの待機耐性(ユーザー対面で概ね5〜10秒、API連携で概ね30秒)を超える処理は許されません。LLMのp99レイテンシがこの閾値を超えるなら、同期は適用外です。また、処理中にプロセスがクラッシュすると途中結果はすべて失われ、最初からやり直しになります。人間による承認待ちが必要な場面では、待機中にコネクションを占有し続けるため現実的ではありません。
同期が適する典型例は、テキスト分類、情報抽出、単純なQ&A、要約、構造化出力生成など、LLM呼び出し1回+軽量ツール0〜2回で完結する処理です。A1 同期エッジがこの選択肢を体現するパターンです。
選択肢B:非同期¶
非同期処理では、クライアントのリクエストに対してジョブIDを即座に返し(HTTP 202 Accepted)、処理はバックグラウンドのワーカーが担います。結果はポーリング、Webhook、SSE、WebSocketなどで別途通知します。実行状態はチェックポイントとして外部ストアに永続化されます。
非同期の最大の利点は耐久性と拡張性です。処理時間に上限がなく、ワーカーが落ちても別のワーカーが最後のチェックポイントから再開できます。人間による承認待ち(分〜時間〜日)が挟まってもワーカーを占有しません。並列性も高く、ジョブキューのワーカー数を増やすだけで水平スケールできます。
代償は複雑性です。ジョブキュー(SQS、Redis Streams、Temporalなど)、チェックポイントストア、結果ストア、通知メカニズムが必要になります。デバッグではリクエスト→キュー→ワーカー→結果ストアをまたいだ分散トレースが必要です。テストも非同期のタイミング依存を考慮しなければなりません。さらに、即座に結果がほしい短いタスクにも、クライアントにポーリングやWebSocket接続を強制してしまいます。
非同期が適する典型例は、多段ツール連鎖、複数SaaSをまたぐ処理、人間承認を含むフロー、実行に30秒以上かかる処理です。A2 耐久非同期がこの選択肢を体現するパターンです。
選定基準¶
選定は主に [latency_budget] と [reversibility] の2つの駆動変数で決まります。
[latency_budget](レイテンシ予算)が判定の第一軸です。 処理時間がクライアントの待機耐性を超えるかどうかを、LLMのp99レイテンシで判定します。
| 条件 | 判定 |
|---|---|
| p99が対面5〜10秒 / API連携30秒に収まる | 同期 |
| p99が上記を超える、または所要時間が読めない | 非同期 |
| 分布が二峰的(短い方は収まるが長い方は超える) | ハイブリッド(A3) |
[reversibility](可逆性)が第二の判断軸です。 処理が失敗したときのやり直しコストが高い場合、チェックポイント・再開機構のある非同期が有利です。
| 条件 | 判定 |
|---|---|
| 失敗しても最初からやり直して許容できる | 同期で十分 |
| 途中再開が必要、やり直しのコストが高い | 非同期 |
加えて、人間承認が処理の途中に入るかどうかも判断材料です。承認待ちが発生するなら、コネクションを保持し続ける同期は現実的ではなく、非同期一択になります。
デフォルトとハイブリッド¶
デフォルト:数秒の読取・分類のような単純処理は同期、多段処理や所要時間が不定の処理は非同期です。判断に迷ったらまず同期で始め、レイテンシが枠を超えた時点で非同期に移行するのが安全な出発点です。同期からの移行は比較的容易ですが、非同期から同期への巻き戻しは不要なインフラを抱え続けることになります。
ハイブリッド:A3 同期ファサードが定石です。内部は常に非同期パイプラインで処理し、閾値時間内に完了すれば同期レスポンスを返し、超過すればジョブIDを返して非同期に昇格します。レイテンシ分布が二峰的な場合に特に有効です。
判断を誤ったときの症状¶
同期を選ぶべきだったのに非同期を選んだ場合:
- 数百ミリ秒で返せる処理にもかかわらず、クライアントがポーリングやWebSocket接続を強制され、UXが不必要に複雑になります。
- ジョブキュー・チェックポイントストアの運用コストが発生しますが、チェックポイントから再開する機会はほぼありません。
- デバッグ時に分散トレースを追う必要があり、開発速度が低下します。
非同期を選ぶべきだったのに同期を選んだ場合:
- クライアント側でタイムアウトが頻発します。特にp99が閾値を超える処理で顕著です。
- プロセスのクラッシュやプロバイダの一時障害で途中結果が失われ、全処理をやり直す「全損」が繰り返されます。
- ロングポーリングやコネクション保持によりHTTPワーカースレッドが枯渇し、全体のスループットが低下します。
- 人間承認が必要になった段階で、アーキテクチャの大幅な書き直しが必要になります。
判定のシグナル: p99レイテンシを計測し、クライアントのタイムアウト率を監視してください。タイムアウト率が概ね1%を超えたら同期の限界です。逆に、非同期ジョブの90%以上が1秒以内に完了しているなら、非同期のオーバーヘッドが見合っていない可能性があります。
関連パターン¶
- A1 同期エッジ — 同期側の代表パターンです。単発LLM呼び出し+軽量ツールを同期HTTPで完結させます。
- A2 耐久非同期 — 非同期側の代表パターンです。ジョブ化・チェックポイント・再開を実現します。
- A3 同期ファサード — ハイブリッドの定石です。内部非同期・外向き自動切替を実現します。
- A6 適応タイムアウト — 同期・非同期いずれでも、タイムアウト値の設定に使います。
- F-13 プッシュ vs プル — 非同期を選んだ場合の結果通知方式を決めるフォークです。
- F-14 インコンテキスト状態 vs 外部ステートストア — 同期ならインコンテキスト、非同期なら外部化が基本です。