長時間実行される AI エージェントには永続的なチャネルが必要です
OpenAI のバックグラウンドモードのドキュメントは、いまやエージェントで普通に起きる問題を扱っています。推論タスクには数分かかることがあり、開発者は ID でレスポンスをポーリングし、レスポンスをキャンセルし、記録されたシーケンス番号からストリームを再開できます。1
重要なポイント
- 長時間実行されるエージェントの実行には、宛先が必要です。 クライアントは同じ作業に再接続し、既知のカーソルからストリームを読み、進路を変えるコマンドを送り、実行をキャンセルし、証拠を確認できなければなりません。
- ポーリングだけでは契約が薄すぎます。 ポーリングで状態は報告できますが、本格的なエージェント作業には、コマンド、イベント履歴、再開可能なストリーム、成果物、認可、チェックポイントも必要です。
- 永続的な実行が解決するのは、システムの一部だけです。 Temporal 型のワークフローは実行状態とイベント履歴を保持します。それでも、実行中の作業を取り囲む永続的な通信面はユーザー側に必要です。23
- WebSockets は役に立ちますが、ソケットそのものが宛先ではありません。 接続が切れても、ユーザーがエージェントの実行へ戻る経路まで消えてはいけません。
- プロダクトとしての見せ方が重要です。 ユーザーが見るべきなのは、散らばったログや楽観的な状態文ではありません。証拠、判断、次のアクションがまとまった、1つの一貫した実行です。
長時間実行される AI エージェントは、従来のリクエスト・レスポンスの形に収まりません。通常のリクエストには、エンドポイント、レスポンス、タイムアウトがあります。一方で本格的なエージェント実行には、継続時間、イベント履歴、中間成果物、ユーザーからの割り込み、モデルやツールの状態、キャンセル規則、そして離脱して戻ってくる可能性のある人間がいます。
足りないのは、もう1つのチャットメッセージではありません。足りないのは永続的なチャネルです。実行中の作業に対する安定した宛先が必要なのです。
以前、マネージドエージェントが実行基盤を吸収していること、そしてエージェントの実行トレースが実行時の契約になりつつあることを書きました。永続的なチャネルは、その2つの考えの間にあります。トレースは何が起きたかを証明します。マネージド実行基盤は作業を生かし続けます。永続的なチャネルは、その作業が続いている間、プロダクトとユーザーが作業とやり取りできるようにします。
古いリクエストモデルでは何が壊れるのか
従来の Web モデルでは、計算はリクエスト内で終わるか、バックグラウンドジョブへ移される前提です。永続的な状態はデータベースに保存されます。アプリケーションサーバーはステートレスに保たれます。クライアントはページを更新し、別のサーバーに当たり、同じデータベース行を読めます。
エージェント作業は、このモデルに3つの方向から負荷をかけます。数分から数時間かかることがあります。1つのデータベースレコードへきれいに還元できないプロセス状態を持ちます。そして、監視、割り込み、承認、方向転換、キャンセル、再開という双方向の制御を必要とします。
Zak Knill も同じ圧力をルーティングの問題として捉えています。2026年5月の投稿では、長時間続き、状態を持ち、対話的に進むエージェント作業には、出力を保存するデータベースだけでなく、作業をしているプロセスそのものを指定できる、ルーティング可能な基本要素が必要だと論じています。4 この見方で有用なのは、クライアントが「実行 X にコマンド Y を届けてほしい」と言いたい点です。元のソケット、ワーカー、タブ、プロセスが消えていてもです。
単純なタスクなら、バックグラウンドジョブで十分な場合もあります。画像リサイズ、請求書のエクスポート、夜間同期であれば、queued、running、succeeded、failed だけで済むかもしれません。作業が終わる前にユーザーが進路を変える必要が出てきた瞬間、エージェント作業は一線を越えます。
なぜポーリングだけでは足りないのか
ポーリングは、クライアントが「もう終わりましたか」と尋ねる方法を与えます。しかし、完全な対話契約にはなりません。
OpenAI のバックグラウンドモードにポーリングが含まれているのは、ポーリングがタイムアウト問題を解くからです。ドキュメントでは、状態が queued または in_progress の間はバックグラウンドレスポンスを取得し、終端状態に達したら止めるよう説明されています。1 同じページには、キャンセルと sequence_number カーソルによるストリーム再開も用意されています。これは、基本的なポーリングを超えた、より豊かな実行契約を示しています。1
ポーリングだけで止まるプロダクトでは、たいていエージェントの状態が多すぎる場所に分散します。
| 必要なこと | 薄いポーリングの答え | 永続的なチャネルの答え |
|---|---|---|
| 進捗を見る | status = in_progress |
タイムスタンプと型を持つ追記専用イベント |
| タブが落ちたあと再接続する | 最新行をポーリングする | カーソル N のあとからストリームを再開する |
| 作業の方向を変える | どこかにメモを書く | 実行 X に型付きシグナルを送る |
| 安全にキャンセルする | boolean を反転する | 終端イベント付きの冪等なキャンセルコマンド |
| 証拠を確認する | 最終テキストを読む | イベント履歴、成果物、チェックポイントを調べる |
| 制御を認可する | ページのセッションを信頼する | 実行ごと、コマンドごとに権限を確認する |
ポーリングはアクセス経路の1つとして残せます。間違いは、ポーリングをプロダクトの契約そのものとして扱うことです。
永続的なチャネルには何を含めるべきか
永続的なチャネルとは、実行を取り囲む名前付きの通信契約です。実装には、ワークフローエンジン、キュー、イベントテーブル、WebSocket、SSE ストリーム、pub/sub トピック、マネージドエージェントの作業単位、あるいはそれらの組み合わせを使えます。重要なのは転送方式よりも、プロダクト上の契約です。
最小限の契約には、9つの要素があります。
| フィールドまたはエンドポイント | 目的 |
|---|---|
run_id または workflow_id |
作業の安定した宛先。 |
GET /runs/{id} |
現在の状態、所有者、タイムスタンプ、終端状態、要約。 |
GET /runs/{id}/events?after=N |
再接続と監査のための順序付きイベント履歴。 |
GET /runs/{id}/stream?after=N |
既知のカーソルから再開できるライブ更新。 |
POST /runs/{id}/signals |
approve、revise、pause、add context などの型付き制御コマンド。 |
POST /runs/{id}/cancel |
記録された終端イベントを伴う冪等なキャンセル。 |
GET /runs/{id}/artifacts |
diff、ファイル、レポート、スクリーンショット、トレース、その他の証拠。 |
checkpoint イベント |
引き継ぎと再開のために人間が読める状態。 |
| 認可チェック | 実行ごとの読み取り、ストリーム、シグナル、成果物、キャンセル権限。 |
すべてのイベントには、型、シーケンス番号、タイムスタンプ、実行主体、ペイロード参照、秘匿方針が必要です。その構造がなければ、イベントログはただの別のチャット記録になります。
チャネルには判断の品位も必要です。ユーザーが判断を必要としているときに、すべてのトークンを流してはいけません。ツール失敗を親しげなスピナーの裏に隠してはいけません。実行中のエージェントを通知の嵐にしてはいけません。良いチャネルは、ユーザーが作業を信頼し、方向づけ、止めるために役立つ少数のイベントを見せます。
既存システムはこのパターンをどう示しているのか
Temporal は、実行側に成熟した語彙を与えます。ワークフロー実行には、イベント履歴、リプレイ、決定論的なワークフローコード、そして API 呼び出し、データベースクエリ、LLM 呼び出し、ファイル I/O など外部世界の作業を扱うアクティビティがあります。2 Temporal の TypeScript メッセージパッシングのドキュメントでは、ワークフローを、クエリ、シグナル、更新を受け取るステートフルサービスとして説明しています。クライアントはワークフロー ID でワークフローハンドルを取得し、状態をクエリし、シグナルを送り、更新を実行できます。3
このモデルは、エージェント作業にきれいに対応します。クエリは「この実行はどんな状態だと報告しているか」に答えます。シグナルは「進路を変えてください」に答えます。更新は「追跡される変更を実行し、結果を返してください」に答えます。イベント履歴は「何が起きたか」に答えます。Temporal を使わなくても、この形から学べます。ただし、この形は「バックグラウンドジョブにチャットを足す」よりも、エージェントプロダクトに適した語彙を与えてくれます。
Cloudflare Durable Objects は、別の要素を示しています。宛先を持つ調整です。Cloudflare は各 Durable Object を、ストレージを備えたグローバルに一意なインスタンスとして説明しており、複数クライアント間のステートフルな調整に使えるとしています。5 WebSocket ドキュメントでは、長く続く双方向接続と、オブジェクトが休止中でもクライアント接続を維持し、メッセージ到着時にオブジェクトを起こす WebSocket Hibernation が説明されています。6 これで Durable Objects が万能のエージェント実行基盤になるわけではありません。それでも、ライブなエージェント画面にとって、宛先を持つ調整オブジェクトが自然に感じられる理由はよくわかります。
Anthropic の長時間実行エージェントに関する記事は、人間の作業面を補っています。その投稿では、エージェントはいまだに多くのコンテキストウィンドウをまたぐ作業を苦手としており、後続の作業単位が少しずつ進捗を重ね、次の作業単位のために明確な成果物を残すパターンを説明しています。7 永続的なチャネルは、それらの成果物をプロダクト画面へ運ぶべきです。プライベートなログに埋めてはいけません。
最初に何を作るべきか
最初に作るなら、大がかりなオーケストレーション基盤ではなく、小さな実行サービスから始めます。
所有者、状態、タイムスタンプ、現在の要約を持つ runs テーブルを作ります。単調増加するシーケンス番号を持つ run_events テーブルまたはストリームを作ります。大きなペイロードや成果物は別に保存し、イベントから参照します。再開可能なストリームエンドポイントを1つ、型付きシグナルエンドポイントを1つ追加します。キャンセルは冪等にします。すべての状態遷移をイベントログに入れます。
次に、イベントの語彙を絞ります。
| イベント型 | 意味 |
|---|---|
run.started |
システムが作業を受け付け、安定した ID を割り当てた。 |
agent.plan.updated |
エージェントが現在の計画またはチェックポイントを変更した。 |
tool.started |
ツールまたはコマンドが、秘匿済みの引数で開始した。 |
tool.finished |
ツールまたはコマンドが、状態、所要時間、証拠参照とともに終了した。 |
artifact.created |
diff、ファイル、スクリーンショット、レポート、トレースが利用可能になった。 |
human.signal.received |
ユーザーが型付きの制御コマンドを送った。 |
run.blocked |
実行に権限、入力、外部状態が必要になった。 |
run.cancelled |
システムがキャンセルを受け付け、作業を停止した。 |
run.completed |
作業が証拠付きで成功の終端状態に達した。 |
run.failed |
作業が証拠付きで失敗の終端状態に達した。 |
これで UI は、1つの一貫した実行を表示できます。ユーザーは同じ宛先から離脱し、戻り、イベントを確認し、成果物を調べ、方向づけられます。エージェントは文章で成功を主張するのをやめ、状態遷移に証拠を添付し始められます。
チームが避けるべきこと
避けるべき近道が3つあります。
1つ目は、純粋なチャット記録です。チャットは作業の開始や確認事項の収集には使えます。しかし、長時間実行されるタスクの唯一の実行時オブジェクトにするべきではありません。
2つ目は、生のトークンストリーミングを主な進捗表示にすることです。トークンストリームは開発者がレイテンシをデバッグする助けになりますが、ほとんどのユーザーが必要としているのは、マイルストーン、ブロッカー、成果物、判断です。永続的なチャネルでも、専門家向けの確認手段として生のイベントを公開することはできます。
3つ目は、プライベートなプロセスの漏えいです。公開プロダクトの画面が見せるべきなのは証拠であって、プライベートなプロンプト、フックの本文、ローカルファイルパス、内部スコアリングの仕組みではありません。ユーザーには作業を信頼するのに十分な情報が必要です。作業を可能にした内部の工夫をすべて見る必要はありません。
このプライバシーの線引きは、エージェントシステムについて公開記事を書くときにも当てはまります。契約は共有します。プライベートな仕組みはプライベートなままにします。
永続的なチャネルは評価をどう変えるのか
永続的なチャネルがあると、評価は見せかけではなくなります。
最終回答がもっともらしく聞こえるかどうかではなく、評価者は実行そのものを確認できます。
- 実行は正しい所有者、権限、範囲で始まったか。
- エージェントは行動する前に計画を出したか。
- 主張された成果物はすべて、記録済みイベントに由来しているか。
- 失敗時に有用なチェックポイントが残されたか。
- ユーザーのシグナルは、期待どおりに実行を変えたか。
- キャンセルは1つの終端状態で終わったか。
- 最終レポートはイベントログの証拠を引用しているか。
このリストによって、証拠ゲートは実行基盤が直接支えられるものになります。また、クリーンアップ層にもつながります。多くのエージェントプロダクトは、混乱した実行を理解しやすく、再開しやすく、レビューしやすくすることで勝つはずです。
まとめ
長時間実行される AI エージェントに永続的なチャネルが必要なのは、ユーザーが作業へ戻るための安定した経路を必要としているからです。ポーリングは状態を報告できますが、それだけで契約全体を担うことはできません。良いエージェント実行には、ワークフロー ID、順序付きイベント、再開可能なストリーム、型付きシグナル、冪等なキャンセル、成果物参照、権限、人間が読めるチェックポイントが必要です。永続的な実行は作業を生かし続けます。永続的なチャネルは、ユーザーとプロダクトがその作業とやり取りできるようにします。
FAQ: 長時間実行される AI エージェントと永続的なチャネル
長時間実行される AI エージェントには Temporal が必要ですか
いいえ。Temporal はチームに強力なワークフロー語彙と成熟した実行モデルを与えますが、永続的なチャネルの契約はもっと単純な基盤でも動かせます。安定した run ID、順序付きイベント、再開可能なストリーム、型付きコマンド、成果物から始めましょう。リトライ、リプレイ、タイマー、運用規模が必要になったときに、ワークフローエンジンへ移れば十分です。
エージェントの進捗には WebSockets だけで十分ですか
いいえ。WebSockets はライブな双方向接続を提供します。それでもプロダクトには、永続的な宛先、イベント履歴、再接続カーソル、権限、終端状態が必要です。ソケットはチャネルを運べますが、チャネル全体を定義するべきではありません。
ポーリングは常に悪いのですか
いいえ。ポーリングは単純な状態確認に有効で、フォールバック経路として残せます。問題は、長時間実行されるエージェントの実行を観察し、方向づけ、復旧する唯一の手段がポーリングになるときに始まります。
小さなチームは最初に何を作るべきですか
runs リソースと追記専用の run_events ログを作ります。イベントログにシーケンス番号が入ったら、再開可能なストリームを追加します。型付きシグナルは、プロダクトが安全に実行できるコマンドだけに限定してください。approve、pause、revise、add context、cancel です。
エージェント実行イベントには何を入れるべきですか
状態遷移、計画、ツールの開始と終了、成果物の作成、人間からのシグナル、ブロッカー、キャンセル、失敗、完了を記録します。機密性の高いペイロードは、インラインのイベント本文に入れないでください。プライベートな詳細は、秘匿済み参照とアクセス制御の裏に保存します。
参考文献
-
OpenAI, “Background mode,” OpenAI API documentation, accessed 2026年5月18日。非同期バックグラウンド Responses、response ID によるポーリング、終端状態、キャンセル、
sequence_numberカーソル、starting_afterによるストリーム再開の出典。 ↩↩↩ -
Temporal, “Temporal Workflow,” Temporal documentation, accessed 2026年5月18日。Workflow Executions、イベント履歴、リプレイ、決定論的なワークフローコード、API 呼び出し、データベースクエリ、LLM 呼び出し、ファイル I/O のためのアクティビティの出典。 ↩↩
-
Temporal, “Workflow message passing - TypeScript SDK,” Temporal documentation, accessed 2026年5月18日。ステートフルサービスとして動くワークフロー、クエリ、シグナル、更新、ワークフローハンドル、ワークフロー ID の出典。 ↩↩
-
Zak Knill, “LLMs are breaking 20 year old system design,” /dev/knill, 2026年5月13日。ルーティング可能な基本要素という捉え方、ポーリング批判、接続としての WebSocket という区別、永続的なチャネルの議論の出典。 ↩
-
Cloudflare, “Durable Objects,” Cloudflare Developers documentation, accessed 2026年5月18日。Durable Objects を、ストレージを持つグローバルに一意なステートフル調整オブジェクトとして説明する出典。 ↩
-
Cloudflare, “Use WebSockets,” Cloudflare Developers documentation, accessed 2026年5月18日。WebSocket エンドポイントとしての Durable Objects、長時間続く双方向接続、WebSocket Hibernation の挙動の出典。 ↩
-
Anthropic, “Effective harnesses for long-running agents,” Anthropic Engineering, 2025年11月26日。多くのコンテキストウィンドウをまたぐ長時間実行エージェント、作業単位をまたいだ段階的な進捗、後続の作業単位に向けた明確な成果物の出典。 ↩