Description
When using a live audio model (gemini-live-2.5-flash-native-audio) with save_live_blob=True in the RunConfig, function/tool calls declared on the agent are never executed. The model's audio output gets cut off mid-sentence at the point where it decides to invoke the tool, and the tool is never actually called.
Setting save_live_blob=False fixes the issue: tools are invoked correctly and audio is not truncated.
Root Cause
This is according to AI, but seems accurate to me:
In base_llm_flow.py, _postprocess_live, the audio cache flush has an early return that fires before the function call handler:
# Line 1043-1057
if invocation_context.run_config.save_live_blob:
flushed_events = await self._handle_control_event_flush(
invocation_context, llm_response
)
for event in flushed_events:
yield event
if flushed_events:
# NOTE below return is O.K. for now, because currently we only flush
# events on interrupted or turn_complete. turn_complete is a pure
# control event ...
return # ← Returns BEFORE function call handling at line 1066
# Line 1065-1068 (never reached when flushed_events is non-empty)
if model_response_event.get_function_calls():
function_response_event = await functions.handle_function_calls_live(...)
The inline comment assumes turn_complete is a "pure control event," but when the Gemini Live API model decides to call a tool, its response includes turn_complete=True alongside (or immediately preceding) the function call. _handle_control_event_flush sees turn_complete, flushes audio caches, returns a non-empty list, and the early return skips function call processing entirely.
This results in:
- Audio output truncated mid-sentence (model stops audio to make the function call)
- Tool function never executed (before/after callbacks never fire)
- No function call events visible downstream (
event.get_function_calls() never yields results)
- The model never receives a function response, so it never resumes audio generation
Reproduction
from google.adk.agents import Agent
from google.adk.runners import Runner, RunConfig
from google.adk.tools import ToolContext
def my_tool(tool_context: ToolContext) -> str:
"""A simple tool that should be called by the agent."""
tool_context.state["tool_was_called"] = True
return "Done."
agent = Agent(
name="my_agent",
model="gemini-live-2.5-flash-native-audio",
tools=[my_tool], # ← Adding any tool triggers the bug
instruction="You are a helpful assistant. Call my_tool when the conversation is over.",
)
run_config = RunConfig(
speech_config=...,
save_live_blob=True, # ← Required to trigger the bug
)
# Use runner.run_live() with the above config.
# The agent will never actually call my_tool, and audio will be truncated
# at the point where the model decides to invoke it.
With save_live_blob=False: Tools work correctly, audio is not truncated.
Version Info
google-adk: 1.29.0
google-genai: 1.72.0
- Model:
gemini-live-2.5-flash-native-audio
- The same early return pattern exists in all versions from v1.15.0 through v2.0.0a3.
Suggested Fix
The early return after _handle_control_event_flush should check whether the response also contains function calls before returning. Something like:
if flushed_events:
# Still need to check for function calls even on control events
model_response_event = self._finalize_model_response_event(
llm_request, llm_response, model_response_event
)
if model_response_event.get_function_calls():
function_response_event = await functions.handle_function_calls_live(
invocation_context, model_response_event, llm_request.tools_dict
)
yield function_response_event
return
Description
When using a live audio model (
gemini-live-2.5-flash-native-audio) withsave_live_blob=Truein theRunConfig, function/tool calls declared on the agent are never executed. The model's audio output gets cut off mid-sentence at the point where it decides to invoke the tool, and the tool is never actually called.Setting
save_live_blob=Falsefixes the issue: tools are invoked correctly and audio is not truncated.Root Cause
This is according to AI, but seems accurate to me:
In
base_llm_flow.py,_postprocess_live, the audio cache flush has an earlyreturnthat fires before the function call handler:The inline comment assumes
turn_completeis a "pure control event," but when the Gemini Live API model decides to call a tool, its response includesturn_complete=Truealongside (or immediately preceding) the function call._handle_control_event_flushseesturn_complete, flushes audio caches, returns a non-empty list, and the earlyreturnskips function call processing entirely.This results in:
event.get_function_calls()never yields results)Reproduction
With
save_live_blob=False: Tools work correctly, audio is not truncated.Version Info
google-adk: 1.29.0google-genai: 1.72.0gemini-live-2.5-flash-native-audioSuggested Fix
The early return after
_handle_control_event_flushshould check whether the response also contains function calls before returning. Something like: