Skip to Content
Docs03. 実装ストリーミングと Agent の UX 実装パターン

この記事の音声は準備中です。

音声の一覧・再生リストへ

ストリーミングと Agent の UX 実装パターン

この記事の目的

「Agent は本質的に遅い」という前提に立ち、体感品質を決める 4 つの実装パターン — トークンストリーミング・進捗の可視化・中断と軌道修正・非同期化 — を使い分けられるようになります。

対象読者

  • ユーザーに直接応答する Agent(チャット・アシスタント)のフロントエンド/バックエンドを実装するエンジニア
  • 「Agent が黙り込む」「止められない」という UX 課題に取り組むチーム

前提知識

本文

概要: レイテンシは消せない。不安だけ消せる

Agent の応答時間は、単発の LLM 呼び出しと桁が違います(数十秒〜数分)。この遅さの多く — 複数回の推論、ツールの実行、外部 API の待ち — は本質的で、最適化しても消えません。UX 実装の目標は、待ち時間を消すことではなく、「動いているか分からない不安」を消すことです。無応答の 30 秒は、ユーザーにとって故障と区別がつきません。

詳細: パターン 1 — トークンストリーミング

最終応答のテキストを、生成と同時に逐次表示します。主要な LLM API はサーバー送信イベント(SSE: Server-Sent Events)形式のストリーミングをサポートしており、最初のトークンが出るまでの時間(TTFT最初のトークンが出るまでの時間。ストリーミング表示の体感と全体レイテンシを左右する主要指標の一つ。)が体感を支配します。

  • 長い応答では必ずストリーミングにします。全文完成を待つ実装は、体感を数倍悪化させるうえ、HTTP タイムアウトの原因にもなります
  • ストリーミング中の部分テキストは未確定として扱います(途中でツール呼び出しに切り替わる・エラーで中断されることがあります)

詳細: パターン 2 — 進捗の可視化

ループの中間ステップ(いま何をしているか)をユーザーの語彙で表示します。

  • やること: ステップの要約表示(「経費データを検索しています…」「3 件見つかりました。規定と照合しています…」)
  • やらないこと: 生のツール入出力のダンプ。情報過多で読めないだけでなく、内部 API のレスポンスに含まれる秘密情報・個人情報を画面に流出させる事故につながります
  • 実装上は、ツール呼び出しイベントを「ユーザー向けの一文」に変換する層を 1 枚挟みます(ツール名からの固定文言でも、モデルに生成させる方式でも可)

詳細: パターン 3 — 中断と軌道修正

長く走る Agent には、ユーザーがいつでも止められる・向きを変えられる手段が必要です。

詳細: パターン 4 — 同期チャット型か、非同期ジョブ型か

形態向くタスク実装の要点
同期チャット型数秒〜1 分程度。対話的に方向修正したいタスクストリーミング + 進捗表示 + キャンセル
非同期ジョブ型数分〜時間単位。調査・一括処理・長い生成依頼を受け付けて即応答 → バックグラウンド実行 → 完了通知。進捗の照会画面

数分を超えるタスクを同期チャットで待たせるのは設計ミスです。「受け付けました。終わったら通知します」に切り替え、承認待ち(Human-in-the-Loop 設計)も通知で運びます。

実装例: 非同期ツールと実行中の軌道修正

2026-09-10 確認の OpenAI Responses API では、Astra の function / custom tool に async: true を付けると、アプリがツールを実行している間もモデルが独立した作業を続けられます。結果は元の call_id と結び付けます。WebSocket の実行中の指示変更(mid-turn steering)では、完了済みの作業を引き継ぐ継続処理へ追加指示を渡せます。

画面の「停止」「条件変更」は次の状態管理につなぎます。

起きたことアプリ側の処理表示すること
ツールが実行中呼出し ID と実行状態を保存し、同じ操作を重複起動しない確認中の対象と進捗
条件が変わった対象・引数・承認の有効性を再評価する変更を受け付けた条件と残る作業
停止後に結果が届いた元の実行に記録し、新しい実行への採用可否を判定する停止済みでも完了した外部操作があればその事実

推論の停止は、送信済みメールや外部 API の更新を巻き戻しません。キャンセル不能な操作は状態を照会し、必要なら補償処理へ進みます。非同期ツール API の採用だけでジョブの永続化・再起動後の復旧が得られるわけではありません。

実務での注意点

アンチパターン

  • スピナーだけで数十秒待たせる → ユーザーは故障と判断して離脱・再送信し、再送信が二重実行を生む → 進捗の可視化(パターン 2)と、処理中の再送信ガードを入れる
  • 生のツールログをそのまま流す → 読めない上に、内部データ・秘密情報の画面流出になる → ユーザー語彙への変換層を挟み、表示内容を出力としてレビュー対象にする
  • キャンセルが効かない(見た目だけ止まる) → 裏でループが走り続け、コストと副作用が発生し続ける → キャンセルをループ停止条件・実行中ツールの中断まで貫通させ、テストで確認する

チェックリスト

  • 最終応答がストリーミング表示される
  • 実行中に「いま何をしているか」がユーザーの語彙で見える
  • 進捗表示に秘密情報・内部データが混入しない設計になっている
  • 停止ボタンがあり、裏のループまで実際に止まることをテストした
  • 数分を超えるタスクが非同期ジョブ型(通知ベース)になっている
  • 中断時に途中経過が保全され、再開または報告ができる

関連トピック

参考資料

TODO・未確認事項