Name: google-genai
Version: 1.70.0
Summary: GenAI Python SDK
Home-page: https://github.com/googleapis/python-genai
Author:
Author-email: Google LLC googleapis-packages@google.com
License-Expression: Apache-2.0
Summary
AsyncLiveSession.receive() internally calls break after yielding the first turn_complete message. In multi-turn voice applications that call async for msg in session.receive() once for the entire session lifetime, this silently exits the receive loop after the first turn — causing the bot to go permanently silent after its first response.
SDK version
google-genai ==
Check with: pip show google-genai
Affected code
live.py lines ~456–459:
async def receive(self) -> AsyncIterator[types.LiveServerMessage]:
while result := await self._receive():
if result.server_content and result.server_content.turn_complete:
yield result
break # <-- exits after first turn_complete
yield result
Steps to reproduce
async with client.aio.live.connect(model=model, config=config) as session:
# Send turn 1
await session.send_realtime_input(activity_start=types.ActivityStart())
await session.send_realtime_input(audio=types.Blob(data=pcm, mime_type="audio/pcm;rate=16000"))
await session.send_realtime_input(activity_end=types.ActivityEnd())
# Iterate receive() for the entire session lifetime
async for msg in session.receive():
sc = msg.server_content
if sc and sc.turn_complete:
print("Turn 1 complete")
# Now send turn 2...
await session.send_realtime_input(activity_start=types.ActivityStart())
await session.send_realtime_input(audio=types.Blob(data=pcm2, mime_type="audio/pcm;rate=16000"))
await session.send_realtime_input(activity_end=types.ActivityEnd())
# ← No more messages ever arrive — receive() loop has already exited
Expected behaviour
receive() should continue yielding messages across multiple turns for the lifetime of the session, since a Live session is a persistent bidirectional connection designed for multi-turn conversations.
Actual behaviour
After the first turn_complete is yielded, the async for loop exits silently. Any audio or messages sent for subsequent turns are never received, making multi-turn conversations impossible using receive().
Workaround
Call _receive() directly in a while True loop:
while True:
message = await session._receive()
if message is None:
break
# process message...
This is not ideal as _receive() is a private method. The fix should be in receive() itself.
Suggested fix
Either:
Remove the break so receive() continues across turns, or
Add a multi_turn=True parameter (default False for backwards compatibility) that skips the break, or
Document clearly that receive() only covers a single turn and a separate receive_all() / receive_stream() method should be used for multi-turn sessions.
Model tested
gemini-3.1-flash-live-preview
gemini-2.0-flash-live-001
Name: google-genai
Version: 1.70.0
Summary: GenAI Python SDK
Home-page: https://github.com/googleapis/python-genai
Author:
Author-email: Google LLC googleapis-packages@google.com
License-Expression: Apache-2.0
Summary
AsyncLiveSession.receive() internally calls break after yielding the first turn_complete message. In multi-turn voice applications that call async for msg in session.receive() once for the entire session lifetime, this silently exits the receive loop after the first turn — causing the bot to go permanently silent after its first response.
SDK version
google-genai ==
Check with: pip show google-genai
Affected code
live.py lines ~456–459:
async def receive(self) -> AsyncIterator[types.LiveServerMessage]:
while result := await self._receive():
if result.server_content and result.server_content.turn_complete:
yield result
break # <-- exits after first turn_complete
yield result
Steps to reproduce
async with client.aio.live.connect(model=model, config=config) as session:
# Send turn 1
await session.send_realtime_input(activity_start=types.ActivityStart())
await session.send_realtime_input(audio=types.Blob(data=pcm, mime_type="audio/pcm;rate=16000"))
await session.send_realtime_input(activity_end=types.ActivityEnd())
Expected behaviour
receive() should continue yielding messages across multiple turns for the lifetime of the session, since a Live session is a persistent bidirectional connection designed for multi-turn conversations.
Actual behaviour
After the first turn_complete is yielded, the async for loop exits silently. Any audio or messages sent for subsequent turns are never received, making multi-turn conversations impossible using receive().
Workaround
Call _receive() directly in a while True loop:
while True:
message = await session._receive()
if message is None:
break
# process message...
This is not ideal as _receive() is a private method. The fix should be in receive() itself.
Suggested fix
Either:
Remove the break so receive() continues across turns, or
Add a multi_turn=True parameter (default False for backwards compatibility) that skips the break, or
Document clearly that receive() only covers a single turn and a separate receive_all() / receive_stream() method should be used for multi-turn sessions.
Model tested
gemini-3.1-flash-live-preview
gemini-2.0-flash-live-001