Gemini Live: updates inside a tool miss its reply
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 55/100
Research direction
The reproduction uses Agent.update_instructions(), Agent.update_tools(), and the Gemini realtime model; start by tracing how tool execution sends session.update and then submits the tool result. Compare the inside-tool and before-turn cases with the repro in the issue. Done means updates made inside a tool affect the reply to its result, or the realtime limitation is documented.
Written by the indexing model from the issue text.
Description
Bug Description
On Gemini Live through LiveKit Inference, update_instructions() and update_tools() called inside a function tool don't apply to the reply to that tool's result. LiveKit sends the session.update before the tool result, but Gemini answers with the old instructions and tools.
Agents that change phase from a tool hit this. For example, a confirm_ready tool that swaps the welcome instructions for the interview instructions gets a first question written without the interview instructions. A tool that adds a finish tool and asks the model to call it gets no call.
In the repro below, the unlock tool swaps in instructions containing a secret word, adds a finish tool, and returns "Tell the user the secret word from your instructions, then call finish.":
| Updates made | Knew the secret word | Called finish |
|---|---|---|
| Inside the tool | 0 of 4 | 0 of 4 |
| Before the turn | 4 of 4 | 4 of 4 |
When the updates are made inside the tool, the model replies "The session is now unlocked." and nothing more.
Expected Behavior
Instructions and tools updated inside a tool apply to the reply to that tool's result, as they do for chained LLMs. If Gemini Live can't apply them mid-turn, the SDK could hold the tool reply until the session.update has been applied.
Reproduction Steps
- Set
LIVEKIT_API_KEY/LIVEKIT_API_SECRET. - Run
python repro.py inside(updates inside the tool), thenpython repro.py before(the same updates before the turn).
import asyncio
import sys
from livekit.agents import Agent, AgentSession, RunContext, function_tool, inference
INSIDE_TOOL = sys.argv[1] == "inside"
SECRET = "You are helping with the Alfred's study. The secret word is MARIGOLD."
class Assistant(Agent):
def __init__(self):
super().__init__(
instructions="When the user asks to unlock, call the unlock tool."
)
@function_tool()
async def unlock(self, context: RunContext) -> str:
"""Unlock the session when the user asks."""
if INSIDE_TOOL:
await self.update_instructions(SECRET)
await self.update_tools([*self.tools, finish])
return "Unlocked. Tell the user the secret word from your instructions, then call finish."
@function_tool()
async def finish() -> None:
"""Finish the session."""
print("FINISH CALLED")
async def main():
session = AgentSession(
llm=inference.RealtimeModel(
"google/gemini-3.8-live", modalities=["text"], turn_detection=None
)
)
said = []
session.on(
"conversation_item_added",
lambda ev: said.append(ev.item.text_content)
if getattr(ev.item, "role", None) == "assistant"
else None,
)
agent = Assistant()
await session.start(agent=agent)
if not INSIDE_TOOL:
await agent.update_instructions(SECRET)
await agent.update_tools([*agent.tools, finish])
await session.generate_reply(user_input="Please unlock.")
await asyncio.sleep(8)
print("AGENT SAID:", said)
await session.aclose()
asyncio.run(main())
Output:
## inside: AGENT SAID: ['The session is now unlocked.']
## before: FINISH CALLED AGENT SAID: ['The secret word is MARIGOLD.', 'The session is now finished.']
Operating System
macOS 15.2
Models Used
LiveKit Inference google/gemini-3.8-live, text output
Package Versions
livekit-agents==1.8.8
Session/Room/Call IDs
No response
Proposed Solution
Wait for the realtime session to acknowledge a `session.update` sent during tool execution before requesting the tool reply, or document that instruction and tool updates inside a tool only apply from the next turn on realtime models.
Additional Context
Related: #7915, #7916.
Screenshots and Recordings
No response
- Dominant language
- Python
- Stars
- 14.6k
- Forks
- 3.9k
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 169
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from livekit/agents
-
`_ParticipantAudioInputStream` 补静音帧时`data` 长度未乘声道数,多声道配置下抛`ValueError`Possibly taken @Hugo-DDT claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
Google TTS: default ssml_gender NEUTRAL is rejected for Neural2 voicesPossibly taken @sarankumar1325 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Gemini Live: agent stays "speaking" without audio outputPossibly taken @Luke-salinero claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Assistant markup is stripped from chat history when expressive mode is offPossibly taken @ShivamSharma43 claimed this 12 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
docs: openai.LLM vs openai.responses.LLM for HTTP OpenAI-compat hostsMay be free again @AbarnaaSree claimed this 51 days ago, and no pull request is open. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
livekit/agents#7022 · 1 comment ·
Maintainers usually reply within 1 day
Similar issues
-
wr.dynamodb.read_items returns [{}] for a single partition value that does not existPossibly taken @auraseb claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
aws/aws-sdk-pandas#3520 ·
Maintainers usually reply within 2 days
-
requires triage typing
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
sqlalchemy/sqlalchemy#13704 ·
Maintainers usually reply within 1 day
-
Edit tool converts CRLF files to LFPossibly taken @RaphaelFakhri claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
huggingface/tau#774 ·
Maintainers usually reply within 1 day
-
show ignores the row limit when a column or table name contains "limit"Possibly taken @RaphaelFakhri claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
linebender/resvg#1179 · 1 comment ·
Maintainers usually reply within 2 days