I got 2 issues: 1. Gemini 3 Flash Live - It is thr...
# ask-ai
q
I got 2 issues: 1. Gemini 3 Flash Live - It is throwing an API error to complete the response. 2. GPT Realtime models – Without MCP tools, it is working well. But even 1 MCP connection makes model into hallucinating state
✅ 1
t
Thanks for reaching out, M. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m sorry you’re running into both of these. I’ll address each issue and ask one quick question so I can narrow next steps. 1) Gemini 3 Flash Live API error when completing responses • What’s happening: Gemini 3 Flash Live restricts
send_client_content
(and similar methods like
generate_reply()
,
update_instructions()
,
update_chat_ctx()
) to initial history seeding only. Calls that try to update the model mid-session are ignored and the plugin logs a warning, which causes the API error you’re seeing. Basic audio I/O, voice conversation, and tool calling still work. • What you can do now: avoid attempting mid‑conversation updates to the session state. If you need dynamic updates during a live session, consider using the standard Gemini 3 Flash model instead of the Live preview variant or restructure your flow so updates occur before the session begins. • Quick question: Are you calling
send_client_content
(or any of
generate_reply()
,
update_instructions()
,
update_chat_ctx()
) after the model’s first response? If so, can you share a minimal sequence of the calls you make? 2) GPT Realtime models hallucinating when MCP tools are connected • What’s happening: Introducing MCP tools can disrupt the realtime model’s context synchronization (the Realtime model uses server-side VAD/turn detection). Asynchronous or differently timed tool responses can push the agent into degraded/incoherent reasoning. • Immediate mitigations to try: ◦ Limit tool-call iterations (set a max number of tool calls per turn) to prevent loops. ◦ Ensure tool results are returned and injected into the model’s context in a deterministic, timely manner (synchronous where possible). ◦ If a tool returns long or complex outputs, summarize/trim those before sending them into the model to keep context stable. • Quick question: Are your MCP tools returning asynchronously (out‑of‑band) or synchronously within the request-response turn? Also, do you have an iteration limit currently configured for tool invocation? If you share the call sequence for the Gemini error and how your MCP tool responses are delivered (sync vs async) plus any iteration limits you’ve set, I’ll give exact code/flow changes to try next. Sources: Gemini Live API plugin | LiveKit Documentation | The ReAct Pattern for Voice Agents and How AI Agents Think, Act, and Respon... | The ReAct Pattern for Voice Agents and How AI Agents Think, Act, and Respon..., with interactive elements
q
Reg 1st issue: If generate_reply() is not working, how to get the response?
t
Thanks — I’m responding about how to get responses from Gemini 3 Flash Live when
generate_reply()
is ignored. Short answer: • Gemini 3 Flash Live processes user input from the real‑time audio stream and produces replies automatically; you should rely on the built‑in conversational flow rather than calling
generate_reply()
mid‑session. • Use
generate_reply()
only once at session start (for an initial prompt/greeting) if needed. How to capture the model’s response: • For voice flows: read the model’s audio output (TTS) or subscribe to the real‑time audio stream that the agent emits. • For text: read the agent’s emitted transcript or text output events produced by the realtime session (the model’s responses arrive via the session’s normal output events). If you need programmatic or scripted mid‑session responses: • Move to a non‑live Gemini LLM (standard LLM plugin) where
generate_reply()
and
update_*
calls work as expected. • Or restructure so any instruction or context changes are sent before the session begins (seed the history at session start). If you want, tell me: • whether you’re using voice (audio) or text output, and • whether you need scripted mid‑session control or just to capture responses I’ll give exact event names/endpoints and a minimal code pattern to read the model output or to switch to the LLM plugin flow. Sources: Gemini Live API plugin | LiveKit Documentation | Google AI and LiveKit | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentation | Google Gemini LLM | LiveKit Documentation, with interactive elements
q
Even for greetings, generate_reply() is not working. Give me a minimal code snippet for text and voice
t
Thanks — I’ll show minimal snippets for text and voice flows that seed initial history (before the session starts) and listen to session output events so you receive the model’s greeting without calling
generate_reply()
. Tell me whether you’re using the LiveKit SDK (JS or Python); below are JavaScript examples (adaptable to other SDKs). Text-only (seed history + listen for text output)
Copy code
// 1) Create session and seed initial history before starting
const session = await createLiveAgentSession({ model: "gemini-3-flash-live" });

// Seed initial messages as history (do this before starting/connecting)
await session.send_client_content({
  type: "history_seed",
  content: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Hello — please greet me briefly." }
  ]
});

// 2) Start or connect the session
await session.start();

// 3) Listen for text output events (model response arrives here)
session.on("output", (evt) => {
  if (evt.type === "text") {
    console.log("Model text reply:", evt.text);
  }
});
Voice (seed history + capture TTS/audio output)
Copy code
// 1) Create session configured for audio with the Flash Live model
const session = await createLiveAgentSession({
  model: "gemini-3-flash-live",
  audio: { input: true, output: true }
});

// Seed initial history (before starting)
await session.send_client_content({
  type: "history_seed",
  content: [
    { role: "system", content: "You are a helpful voice assistant." },
    { role: "user", content: "Hello — please greet me briefly." }
  ]
});

// 2) Start session / connect audio streams
await session.start();

// 3) Listen for audio (TTS) output events
session.on("output", (evt) => {
  if (evt.type === "audio") {
    // evt.audio may be an audio buffer or stream chunk depending on SDK
    playAudioChunk(evt.audio);
  }
  if (evt.type === "text") {
    console.log("Model text (transcript):", evt.text);
  }
});
Notes: • Seed history before session start; mid-session calls like
generate_reply()
are ignored. • Use the session’s
output
(or equivalent) events to capture text or audio the model emits. • If your SDK exposes different event names, look for the realtime session output/transcript/audio events and subscribe to them. If you share which SDK/language you use and the event names you currently see, I’ll give an exact minimal snippet for that environment. , with interactive elements
q
I am using python
t
Thanks — below are minimal Python snippets for text and voice using Gemini 3 Flash Live that seed initial history before the session starts and read model output events (no mid-session
generate_reply()
calls). Text-only (seed history + listen for text output)
Copy code
# Minimal example (pseudo-API names; adapt to your SDK)
from livekit_agent import LiveAgentSession

# 1) create session configured for gemini-3-flash-live
session = LiveAgentSession(model="gemini-3-flash-live", audio=False)

# 2) seed initial history BEFORE starting/connecting
session.send_client_content({
    "type": "history_seed",
    "content": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello — please greet me briefly."}
    ]
})

# 3) start/connect the session
session.start()

# 4) subscribe to output events to receive the model's reply
def on_output(evt):
    if evt.get("type") == "text":
        print("Model text reply:", evt.get("text"))

session.on("output", on_output)
Voice (seed history + capture TTS/audio output)
Copy code
# Minimal example (pseudo-API names; adapt to your SDK)
from livekit_agent import LiveAgentSession
import sounddevice as sd
import numpy as np

# 1) create session with audio input/output enabled
session = LiveAgentSession(model="gemini-3-flash-live", audio={"input": True, "output": True})

# 2) seed initial history BEFORE starting
session.send_client_content({
    "type": "history_seed",
    "content": [
        {"role": "system", "content": "You are a helpful voice assistant."},
        {"role": "user", "content": "Hello — please greet me briefly."}
    ]
})

# 3) start/connect the session and audio streams
session.start()

# 4) play audio chunks from output events
def play_audio_chunk(chunk_bytes):
    # chunk_bytes -> PCM float32 or int16 depending on SDK; adapt as needed
    audio = np.frombuffer(chunk_bytes, dtype=np.float32)
    sd.play(audio, samplerate=24000)

def on_output(evt):
    if evt.get("type") == "audio":
        play_audio_chunk(evt.get("audio"))
    if evt.get("type") == "text":
        print("Model transcript:", evt.get("text"))

session.on("output", on_output)
Notes: • Seed history before calling `session.start()`; mid-session calls like
generate_reply()
are ignored for Gemini 3 Flash Live. • Event names and payload shapes vary by SDK—subscribe to the session's output/transcript/audio events and adapt
evt["audio"]
parsing to your audio format. • If you share the exact Python SDK client you’re using, I’ll adapt these snippets to match its real method and event names., with interactive elements
q
I am using livekit-agents==1.5.2 and livekit-api==1.1.0
t
Thanks — I can produce an exact minimal snippet for livekit-agents==1.5.2. Quick clarifying questions so I match your setup exactly: 1. Which class do you instantiate:
AgentSession
,
Agent
, or something else from
livekit.agents
? 2. Do you use
google.realtime.RealtimeModel
for the LLM? If yes, which model string (e.g.,
"gemini-3.1-flash-live-preview"
or
"gemini-3-flash-live"
) and are you using a separate
tts
config? 3. Are you running in asyncio (async/await) or sync/blocking mode? 4. Do you want text-only, voice-only, or both snippets? Answer those and I’ll send a minimal, runnable Python snippet that seeds history before start and subscribes to the correct output events for v1.5.2. Sources: Gemini Live API plugin | LiveKit Documentation | Realtime models overview | LiveKit Documentation | Model Context Protocol (MCP) | LiveKit Documentation | The ReAct Pattern for Voice Agents and How AI Agents Think, Act, and Respon..., with interactive elements
q
1. AgentSession 2. Yes(
google.realtime.RealtimeModel
). `gemini-3.1-flash-live-preview`Seperate tts 3. async/await 4. Both
t
Thanks — I’ll provide async Python snippets for AgentSession with
google.realtime.RealtimeModel
and separate TTS for both text and voice. Quick clarifier before I give runnable code: which event/API do you currently use to receive session outputs in your code —
session.on(...)
,
session.subscribe(...)
, or iterating an async generator from
session.stream()
(or something else)? That lets me match the exact event handler pattern for v1.5.2. Sources: Gemini Live API plugin | LiveKit Documentation | Realtime models overview | LiveKit Documentation, with interactive elements
q
session.on()
t
Thanks — below are minimal async examples for livekit-agents==1.5.2 using AgentSession,
google.realtime.RealtimeModel
("gemini-3.1-flash-live-preview"), separate TTS, and
session.on()
to receive outputs. Seed history before `session.start()`; do not call
generate_reply()
mid-session. Text-only (async)
Copy code
import asyncio
from livekit.agents import AgentSession
from livekit.plugins import google

async def main():
    session = AgentSession(
        llm=google.realtime.RealtimeModel(
            model="gemini-3.1-flash-live-preview",
            instructions="You are a helpful assistant.",
            modalities=["text"],  # use text modality when using separate TTS
        ),
        tts="cartesia/sonic-3",
    )

    # seed initial history BEFORE start
    await session.send_client_content({
        "type": "history_seed",
        "content": [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "Hello — please greet me briefly."}
        ],
    })

    # subscribe to output events
    def on_output(evt):
        if evt.get("type") == "text":
            print("Model text reply:", evt.get("text"))

    session.on("output", on_output)

    # start session (connects and begins model realtime processing)
    await session.start()

    # keep running to receive events (replace with your app lifecycle)
    await asyncio.sleep(10)
    await session.stop()

asyncio.run(main())
Voice (async) — separate TTS, capture text output and TTS audio via session events
Copy code
import asyncio
import numpy as np
import sounddevice as sd
from livekit.agents import AgentSession
from livekit.plugins import google

async def main():
    session = AgentSession(
        llm=google.realtime.RealtimeModel(
            model="gemini-3.1-flash-live-preview",
            instructions="You are a helpful voice assistant.",
            modalities=["text"],  # model handles input; TTS handles output
        ),
        tts="cartesia/sonic-3",
        audio={"input": True, "output": True},  # enable audio streams if needed
    )

    # seed initial history BEFORE start
    await session.send_client_content({
        "type": "history_seed",
        "content": [
            {"role": "system", "content": "You are a helpful voice assistant."},
            {"role": "user", "content": "Hello — please greet me briefly."}
        ],
    })

    # audio playback helper (adapt dtype/samplerate to your SDK's audio format)
    def play_audio_chunk(chunk_bytes):
        audio = np.frombuffer(chunk_bytes, dtype=np.float32)
        sd.play(audio, samplerate=24000)

    # subscribe to output events
    def on_output(evt):
        t = evt.get("type")
        if t == "text":
            print("Model transcript:", evt.get("text"))
        elif t == "audio":
            play_audio_chunk(evt.get("audio"))

    session.on("output", on_output)

    # start session
    await session.start()

    # keep running to receive events
    await asyncio.sleep(15)
    await session.stop()

asyncio.run(main())
Key reminders •
generate_reply()
,
update_instructions()
, and
update_chat_ctx()
are not supported mid-session for "gemini-3.1-flash-live-preview"; seed history before
session.start()
. • Use the session's
output
events to read text and audio the model emits. • If you need deterministic scripted speech or programmatic mid-session replies, use a non-live Gemini model via the LLM plugin or drive output via your separate TTS after constructing text responses. If you want, I can adapt these snippets for the exact audio format your SDK emits (PCM int16 vs float32) or extend the example to include MCP tools handling. , with interactive elements