目次
音声AIがレポートを検索したまま黙ると、利用者には処理中なのか接続が切れたのか分かりません。GoogleのAgent Development Kit(ADK)では、遅いツールを会話の外側で動かし、必要な結果だけを発話の切れ目に届ける構成を選べます。対象はでGemini Live を使い、検索や集計を組み込むWebエンジニアです。まず実行方式と通知のタイミングを別々に決めましょう。
本記事は2026年11月8日に公式資料を確認した実践解説です。新機能の速報ではありません。双方向のrun_live()を使う構成を対象とし、通常のテキストチャットへ設定を移すだけで同じ動作になるとは扱いません。コードは動作の違いを調べるための仮想例で、本サイトでは音声セッションの実測を行っていません。
スポンサーリンク
async関数にしても会話が待つ理由
Pythonのasyncは、処理の途中でイベントループへ制御を返す仕組みです。しかし、アプリの他の仕事が動けることと、モデルが次の会話ターンを生成できることは別です。通常のreturnで結果を一度だけ返すツールを登録すると、Live側がその応答を待つ構成があります。「待っていると伝えて」と指示を足しても、応答待ちそのものを変えることはできません。
設計上は、検索時間、モデルへ結果が届く時間、音声が再生される時間を切り分けます。検索を非ブロッキングにしてもは速くなりません。代わりに、待っている間の質問へ答える余地を作ります。利用者が求めるのが処理時間の短縮なら、クエリや検索範囲の改善も別に必要です。
ADK公式のLive and voice agentsは、トークンを順次返すSSEと、双方が話せる双方向ストリーミングを区別しています。既存の文字チャットがストリーミング対応だからといって、会話中にツールを並行実行できると判断しないでください。
モデルとSDKの対応を先に固定する
公式の対応表では、Gemini 3.8 LiveはAI StudioとAgent Platformの双方で一般提供され、非ブロッキングツールとresponse_schedulingに対応します。一方、Gemini 3.1 Flash Liveは非ブロッキングツールに対応しません。名前が新しいモデルほど同じ設定を受け付ける、という選び方はできません。
さらにGemini 3.8 Live Extended ThinkingはAI Studio側のモデルで、すべてのツールをNON_BLOCKINGにし、response_schedulingを設定しない別の条件があります。以下の通知タイミングの例は通常のGemini 3.8 Liveを想定します。モデル名だけ置換してExtended Thinkingへ適用しないことが大切です。提供先、モデルID、利用できる地域やクォータは採用する環境で確認します。
ADK公式資料ではresponse_schedulingはADK Python 2.4以降、behaviorの明示指定はADK Python 2.10以降です。ここでは比較条件をそろえるため2.10以降を前提とし、google-adkとgoogle-genaiの実際の版を依存ロックへ記録します。ADKのモデル対応表と利用先の設定を合わせて確認し、更新とモデル変更を同時に行わず、一方ずつ比較します。
スポンサーリンク
待ち時間の中身でツールを選ぶ
一瞬で終わる取得なら、通常のツールを維持する方が構成は単純です。遅い処理でも、途中経過に利用者の判断材料がなければ、完了時だけ返すバックグラウンド実行が向きます。反対に、検索範囲の確定、集計、レポート生成のように意味の違う段階があるなら、async generatorからyieldするストリーミングツールを検討します。
本サイトの提案は、進捗を送る頻度を処理ループの回数で決めず、利用者に説明する価値で決めることです。レコードを一件読むたびに通知すると、発話が追いつかず、処理が終わってから古い進捗を説明しかねません。「まだ集計中」を繰り返すより、開始と完了だけの方が分かりやすい業務もあります。
最小例で実行方式だけを比較する
まず既存のLive接続を使い、外部APIの代わりに固定の待ち時間を置きます。次のコードはエージェントの定義部分です。接続設定、認証、マイク入力、run_live()の起動と音声再生は既存の実装へ接続してください。売上値などの架空データを返さず、ツールの完了だけを観測する例にしています。
import asyncio
from typing import AsyncGenerator
from google.adk.agents import Agent
async def prepare_report(region: str) -> AsyncGenerator[str, None]:
"""指定地域のレポートを準備する。一度だけ呼ぶ。"""
yield "レポートの準備を開始しました"
await asyncio.sleep(8) # 検証用の待ち時間
yield f"{region}の検証用レポートが完了しました"
agent = Agent(
name="report_assistant",
model="gemini-3.8-live",
tools=[prepare_report],
instruction=(
"準備ツールは同じ依頼に一度だけ呼ぶ。"
"進捗は簡潔に伝え、途中の質問にも答える。"
"完了通知と実際の売上データを混同しない。"
),
)
この例のawait asyncio.sleep()は、が遅い状況を再現するためのものです。本番の同期クライアントや重いCPU処理を、そのままasync関数へ入れる代わりにはなりません。イベントループを止めていないかは別に点検します。比較時は同じ待ち時間で通常のreturn版も用意し、ツール開始から最初の音声までを記録します。
ADKはasync generatorを非ブロッキングとして扱い、中間結果をモデルへ送ります。ただし、yieldした時刻と人が進捗を聞く時刻は一致しません。モデルの生成、ネットワーク、再生キューが間にあるためです。細かな説明を何度も流す前に、音声の録音やイベント時刻で遅れを確認します。
スポンサーリンク
結果をいつ話すかを独立して指定する
実行中に会話できても、レポート完成のたびに利用者の発話を遮れば使いにくくなります。ADKのresponse_schedulingには、自然な間を待つWHEN_IDLE、すぐ届けるINTERRUPT、会話の文脈へ加えるSILENTがあります。通常の照会結果はWHEN_IDLEを出発点とし、即時通知が必要な業務だけ別に検討します。SILENTを、利用者への完了通知と同じ意味で使わないようにします。
from google.adk.tools import FunctionTool
from google.genai import types
report_tool = FunctionTool(prepare_report)
report_tool.response_scheduling = (
types.FunctionResponseScheduling.WHEN_IDLE
)
# Agentのtoolsにはprepare_reportではなくreport_toolを登録する
この設定をストリーミングツールへ付けると、中間更新にも通知方式が適用されます。黙って処理したい場合は、最後に一度だけyieldする形も選べます。returnを維持した通常のコルーチンへ同じ設定を付ける方式では、最初の結果が届くまでモデルへペイロードが来ず、開始の相づちが出ない場合があります。即時の受付応答が必須なら、その条件を試験項目に含めます。
behaviorを明示した場合はresponse_schedulingより優先されます。複数の属性を念のため重ねるより、目的に必要な設定だけを残してください。詳しい組み合わせはADK公式のTools for live agentsで確認できます。
発話の割り込みと処理の中止を分ける
利用者が話しかけて音声が止まったとしても、実行中のツールまで止まったとは限りません。中止を扱うなら、利用者の意思を受け取り、ツール側の終了処理へつなぐ経路が必要です。Googleの解説では、予約名stop_streamingのツールによるキャンセルと、asyncio.CancelledErrorを受けた資源の解放を説明しています。
本サイトでは、読取専用の検証から始め、会話中に「もう不要」と伝えた後に何が残るか確かめることを提案します。停止対象のタスク、検索接続、生成済みファイル、後から届いた結果を区別します。音声が止まった画面表示だけで中止完了にせず、サーバー側の実行状態を確認できる設計にします。
同じ依頼が再度ツールを呼ぶケースも試します。へ一度だけと書くことに加え、業務側で依頼IDと実行状態を保持する方法が考えられます。特にレポート生成が高負荷なら、会話の言い直しが毎回新しい集計を起動しないようにします。これはアプリ側の提案であり、ADKの設定一つで重複処理が消えるという意味ではありません。
無音を四つの時刻で切り分ける
検証では、依頼の受付、ツールの開始、最初の音声、最終結果の再生完了を別々に記録します。初動は改善しても完了が遅いなら、バックエンドや結果の長さが主な課題です。ツールが完了したのに音声が出ないなら、スケジューリング、モデルの応答イベント、クライアントの再生を順に調べます。
ADKのイベント資料では、と応答、音声データ、書き起こし、interruptedなどを区別できます。イベントの先頭要素だけを読むと別の種類のパーツを落とすため、content.parts全体を走査します。サーバーで音声を受信したことと、ブラウザーで利用者が聞けたことも別に測ります。
本サイトの受入試験案は、遅い照会中の追加質問、利用者が話している間の完了、処理中止、同じ依頼の言い直し、バックエンドの失敗を含めることです。各ケースで結果の欠落、二重の読み上げ、古い音声の残存を確認します。合格時間は自社の用途に合わせて決め、公式デモの時間をそのまま保証値にしないでください。
導入判断では、最初の相づちの速さだけでなく、正しい結果が一度届くこと、不要な発話で会話を妨げないこと、処理の状態を追えることを重視します。非ブロッキング化は会話を続けるための手段です。検索そのものの高速化や、長い集計を別ジョブへ分ける設計と組み合わせ、短い実験から採否を判断しましょう。
関連記事
構造化出力とツール呼び出しをWeb機能へ組み込む設計では、出力形式と外部処理の役割を整理しています。本記事はその先の音声セッションにおける待ち時間と通知を扱います。
スポンサーリンク
参考資料
Google Developers Blog:Build a Voice Agent That Never Goes Silent using ADK








![[入門]LLMアプリ開発 --基本・LLMのしくみ・MCP・AIセキュリティ](https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4707/9784297154707_1_29.jpg?_ex=240x240)
