Durable Async Agent|耐久非同期セッション¶
このページは模範(status: stable)
新しいパターンを書くときの粒度・構成の参考にしてください。様式は テンプレート、品質基準は CLAUDE.md §3.3 を参照してください。
一言で(TL;DR)¶
長時間・多ステップのエージェント実行を、HTTP同期の中で完結させずジョブとして外部化します。実行状態を節目ごとに永続化(チェックポイント)し、プロセスやプロバイダが落ちても別ワーカーが最後のチェックポイントから再開できるようにします。
解決する問題¶
エージェント実行は1リクエストが長く(F1)、プロバイダ可用性が不安定(F7)で、同入力でも結果が変わります(F15)。素朴に同期リクエスト内で回すと、(1) タイムアウトやワーカー再起動で全部やり直し、(2) 人間承認(F17)の待ちでスレッド/コネクションを占有、(3) 途中状態が揮発して監査もデバッグも不能、という問題が発生します。状態を実行プロセスの外に出し再開可能にすることで、これらの問題を解消します。
選定条件(When to use / When NOT)¶
- 使う条件
- 処理が30秒を超えうる、または所要時間が読めません。
- 途中失敗から再開したい場合です(
[reversibility]が低くやり直しが高コスト)。 - 実行中に人間承認が挟まります(承認待ちが分〜時間)。
- ツール呼び出しが多段、または複数SaaSを跨ぎます。
- 後から実行を参照・監査する必要があります(
[accountability]が高い)。
- 使わない条件(=代替に倒す)
- 数秒で終わり再開も不要な場合 → A1 同期エッジ で十分です(インコンテキスト状態で足ります。F-14)。
- 「短ければ同期で返したい」UX要件がある場合 → 入口は A3 同期ファサード にし、その非同期コアとして本パターンを使います。
駆動変数とチューニング(程度)¶
| 目盛り | 効かなすぎ ⇔ 効きすぎ | 決め方 [駆動変数] |
目安(出発点) |
|---|---|---|---|
| チェックポイント頻度 | クラッシュで作業消失 ⇔ I/O過多・コスト | 副作用の直前は必須+意味あるステップ後 [reversibility] |
各ツール実行後・各LLM応答後・承認ノード前 |
| 状態の保存粒度 | 再開に必要な情報不足 ⇔ 全トークン保存で肥大 | 「再開に要る最小集合」+本文は参照(uri)で外出し [accountability] |
下の状態スキーマ参照 |
| ジョブ保持期間 | 監査・再開不能 ⇔ ストレージ肥大 | ホット短期・コールド規制要件まで(G1と整合)[accountability] |
実行メタ30日/生データ90日〜 |
| 再開リトライ上限 | 一過性障害で諦める ⇔ 暴走・無限再開 | 予算(A7)で律速 [latency_budget] |
再開2–3回、超過で人間へ |
値はいずれも定数でなく駆動変数の関数です。[reversibility] が高ければチェックポイントは粗くて構いません。
相反における立ち位置(相反)¶
- F-1 同期 vs 非同期 → 非同期。所要時間が待機耐性を超える、あるいは再開・承認が要るためです。即応UXも要るなら A3 を被せてください。
- F-14 インコンテキスト状態 vs 外部ステートストア → 外部化。プロセス障害から独立に再開するための必須条件です。
構造¶
flowchart LR
C[Client] -->|run_id 受領| API
API --> Q[Job Queue]
Q --> W[Agent Worker]
W <-->|checkpoint| CS[(Checkpoint Store)]
W -->|本文| OS[(Object Storage)]
W --> R[(Result Store)]
R -->|通知/ポーリング| C
CS --> W2[別 Worker が再開]
実装メモ¶
チェックポイントの最小状態を以下に示します(本文は uri で外出し、ホット層はメタのみ — G1と同じ思想です):
{
"run_id": "...",
"tenant_id": "...",
"agent_version": "...",
"model": "...",
"current_step": "tool_execution",
"status": "running",
"messages_uri": "s3://.../messages.json",
"tool_results_uri": "s3://.../tools.json",
"plan": [],
"pending_approval": null,
"cost_so_far": 1.23,
"token_so_far": 25000,
"seed": 42,
"updated_at": "2026-05-29T12:00:00Z"
}
落とし穴:
- LLM呼び出し中にDBトランザクションを開かないでください(F1)。チェックポイント書込は短い独立トランザクションで行います。
- 再開時は副作用ツールを冪等キーで保護します(C4)。そうしないと再開が二重実行を生みます。
- 承認待ち(E1)の間はワーカーを占有せず、状態だけ残して解放してください。
- 実行をイベント列で残すと再開・監査・評価が容易になります(F2)。
LangGraph のチェックポイント(HITL・メモリ・タイムトラベル・障害復旧)が実装基盤として相性が良いです。
効かせる力学(forces)¶
- F1(長時間):実行をジョブ化し、同期境界の外で進めます。
- F7(不安定):障害から状態を起点に別ワーカーで再開します。
- F15(再現性低):seed・version・メッセージを保存しリプレイ可能にします。
- F17(人間協働):承認待ちの長時間滞留に状態保持で耐えます。
関連・代替¶
コーディングエージェント向け指示(machine-actionable)¶
このパターンを人間に提案するなら、同時に以下を提案/確認してください:
- [ ] 状態の外部化先(Checkpoint / Object / Result Store)を具体化したか
- [ ] チェックポイント頻度を
[reversibility]から決め理由を添えて提示したか - [ ] 副作用ツールに C4 冪等キー を併置したか
- [ ] 即応UXが要るなら A3 同期ファサード の選択肢を示したか
- [ ] G1 二層観測・G2 トレース を併置したか
- [ ] 承認が入るなら E1 と承認待ち中のワーカー解放方針を示したか