Skip to content
ISSUE 001·LIVE·01:53 IL
← Journal/2026-10-20·7 min·google adk

Voice Agents Go Silent While Tools Run. Google's ADK Fix: Streaming Tools and response_scheduling

Google's Oct 19 guide shows how ADK streaming tools, background execution and response_scheduling keep a Gemini Live voice agent talking during slow tool calls. What it claims, the patterns, and the production cautions it lists.

By Harel Asaf·AI Builder·Tel Aviv

In text chat, a slow tool call shows a spinner. In a voice call, it is silence, and users assume the call dropped.

Google's October 19 guide, Build a Voice Agent That Never Goes Silent using ADK, covers how to avoid that in the Agent Development Kit (ADK) with gemini-3.8-live. This article summarizes the guide. All numbers and behaviors are Google's, from its own demo workflow. I have not run the code.

The problem

A standard ADK tool is an async def that returns once. Google says that during a Gemini Live session (run_live), the loop waits for that return before the model generates more turns. If the tool takes 13 seconds, the agent is silent for 13 seconds. Prompting the model to "tell the user you are working on it" does not fix it, the guide says, because the model's turn is blocked waiting for the function response.

Google's headline number: in its benchmark sales-report workflow on gemini-3.8-live, switching from a blocking tool to a streaming tool cut the time to the agent's first words from 14.4 seconds to 1.2 seconds. That is one workflow, built by the vendor to show the feature.

Google is also clear on the limit: non-blocking tools do not make the backend faster. A 13-second query still takes 13 seconds. What changes is what the user hears.

Pattern 1: streaming tools

When a job has real stages, make the tool an async generator and change return to yield. Per the guide, ADK then marks the tool declaration as NON_BLOCKING and immediately sends the model a status acknowledgement, so the agent can speak right away. Each yield is sent as a partial function response, and the model paraphrases it. Google notes narration can trail the tool by several seconds. If the user asks something unrelated mid-job, the agent can answer without cancelling the task.

Google lists three production cautions:

  • Single-flight calls. Models may try to call the tool again if prompted repeatedly. Put "Call this ONCE" in the docstring and consider an in-memory latch or idempotency key.
  • Cancellation. Include a function named stop_streaming(function_name: str) in the tools list. ADK intercepts it and cancels the generator's asyncio.Task, raising asyncio.CancelledError in your function so you can close connections cleanly.
  • Barge-in does not cancel tools. When the user talks over the agent, the Live API stops the model's output and ADK emits an event with interrupted=True so the client can stop audio. Running tools are not cancelled and their results are still delivered. To stop one, the model has to call stop_streaming.

Pattern 2: background execution

When the wait has no story, Google suggests running quietly. Two approaches:

  • Single-yield generator. An async generator that yields once, on completion. ADK issues an immediate pending response, so the agent acknowledges the request, stays quiet during the work, then presents results when ready or when the user finishes speaking.
  • FunctionTool with response_scheduling. Keep a plain coroutine, wrap it in FunctionTool, and set response_scheduling = types.FunctionResponseScheduling.WHEN_IDLE. The guide notes the trade-off: with a return-once coroutine the model gets nothing until the function finishes, so it typically does not say an initial acknowledgement unless the user keeps talking. A note says that in ADK 2.10 and later you can set behavior = types.Behavior.NON_BLOCKING instead.

Controlling when the result lands

response_scheduling sets when the model reacts to an incoming tool response. In Google's benchmark sessions on gemini-3.8-live:

  • WHEN_IDLE: never cuts into a turn in progress. A report waited while the model finished a separate 20-second answer, then was delivered.
  • INTERRUPT: the result cut off current speech mid-sentence, then the model finished its answer and added the figures.
  • SILENT: the result went into conversation history for later turns without an announcement.

Execution shape (streaming versus single return) and delivery timing are independent and can be combined. On a streaming tool, a response_scheduling setting stamps every partial update. Per the guide, in ADK 2.8 and newer a streaming tool can choose scheduling per update by yielding types.FunctionResponse with a scheduling value, for example SILENT for intermediate progress and WHEN_IDLE for the final result.

Google's rule of thumb: if the wait has a story, stream it. If it is just a wait, run it in the background and let the result land when idle.

Requirements as stated

  • google-adk >= 2.10.0
  • gemini-3.8-live on Gemini Enterprise
  • A bidirectional live session (run_live)

What I would check

These are my own untested suggestions.

1. Time your own tools first. If most finish in under a second or two, none of this matters.

2. Test the single-flight problem on purpose by asking for the same thing twice.

3. Decide what happens on barge-in. Google says the tool keeps running, so a user who says "never mind" needs a path to stop_streaming.

4. Choose scheduling per tool. A critical alert and a background report probably want different modes.

5. Listen to recordings. Google notes narration can lag, and no benchmark replaces hearing it.

What I would not conclude

  • That 14.4 seconds to 1.2 seconds applies to your workflow. It is one vendor demo.
  • That the model will narrate well. Google says the model paraphrases updates, and the exact words are its choice.
  • That it works outside the stated setup. Requirements are specific to ADK 2.10+, a live session and gemini-3.8-live.

Frequently asked questions

Why does a voice agent go silent during a tool call?

Per Google, the live loop waits for a standard tool's single return before generating more model turns.

What is a streaming tool in ADK?

An async generator tool that uses yield. ADK marks it NON_BLOCKING and sends partial updates the model can narrate.

Does this make my backend faster?

No. Google says a 13-second query still takes 13 seconds. Only the conversational experience changes.

What does WHEN_IDLE do?

It delivers the tool result at the next natural pause instead of cutting into a turn in progress.

Does interrupting the agent cancel a running tool?

Not according to the guide. Barge-in stops audio, but tools keep running and results are delivered. The model must call stop_streaming.

Can the model call a streaming tool twice?

Google says it may, and suggests a "Call this ONCE" docstring plus an idempotency key or latch.

What versions do I need?

The guide lists google-adk >= 2.10.0 and gemini-3.8-live on Gemini Enterprise, with run_live sessions.

Sources

Related reading

The build log

Follow the work.

New essays and prototypes, in your feed reader. Email subscriptions are paused while I connect a working delivery service. No email is collected here.

Follow via RSS