Skip to content

Live mode: save_live_blob=True causes early return in _postprocess_live and swallows function calls #5239

@lgenzelis

Description

@lgenzelis

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    live[Component] This issue is related to live, voice and video chat

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions