Repository navigation
fix(live): keep the resumption handle through non-resumable updates - #7939
Closed
AtulJoshi1206 wants to merge 1 commit into
Closed
AtulJoshi1206 wants to merge 1 commit into
AtulJoshi1206 wants to merge 1 commit into
Conversation
The Live API also sends a session resumption update while the session cannot be resumed, for example while the model is generating or a tool call is in flight. That update carries no handle, and the live flow stored it anyway, so for much of every turn the run held no handle at all. A GoAway or a dropped connection in that window then lost the session even though resumption was configured: a 1006 or 1011 close, or a ConnectionClosed, failed the run; a 1000 close ended it as if the model had finished; and a GoAway reconnected without a handle, which opened a new session seeded only with the history from before the run. Replace the stored handle only when an update carries one. Resuming from the last handle the server offered loses only the turn in flight, which is what the Live API documents for resuming from an earlier handle.
copybara-service Bot
pushed a commit
that referenced
this pull request
Nov 4, 2026
Merge #7939 The Live API sends session_resumption_update messages with no handle while the session cannot be resumed (the model is generating or a tool call is running). The live flow stored new_handle from every update, so those wiped the last good handle and a GoAway or dropped connection in that window reconnected without resumption or ended the run. The stored handle is now replaced only when an update carries one; the update events are still yielded as before. PiperOrigin-RevId: 1014061479
Collaborator
|
Thank you @AtulJoshi1206 for your contribution! 🎉 Your changes have been successfully imported and merged via Copybara in commit 02db0ff. Closing this PR as the changes are now in the main branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
No existing issue; described below following the bug-report structure.
Describe the Bug:
With session resumption on, the Live API sends
session_resumption_updatemessages throughout the session. Some of them say the session can't be resumed at that moment. That happens while the model is generating or a tool call is running, and those updates carry no handle. The genai type documents it: "In that case we send update empty new_handle and resumable=false."receive_from_modelinlive/_live_llm_flow.pystoresnew_handlefrom every update, so the first handle-less one replaces the good handle withNone. Every reconnect path inrun_live_flowdepends on that stored handle, so for much of each turn the run behaves as if resumption were never configured. For comparison, the Live API session management guide only keeps the handleif update.resumable and update.new_handle.Impact:
This affects every live app that turns on session resumption, which is the documented way to get past the ~10-minute connection limit and to survive network drops:
RunConfig(session_resumption=...);/run_livewithenable_session_resumption;A GoAway or a drop that lands while the agent is talking or running a tool loses the session. In a voice conversation the model is speaking or running tools a big share of the time, so long sessions hit this regularly.
Observed Behavior:
I scripted a live model behind
Runner.run_live. It sends a resumable update withhandle-1, then a non-resumable one (as happens once the model starts answering), and then the connection goes. Onmain:ConnectionClosedWithout the non-resumable update in between, all four resume with
handle-1, so the lost handle is the only difference.Expected Behavior:
The run reconnects with
handle-1, the last handle the server offered, and doesn't replay history into a session that already has it.Solution:
The stored handle is now only replaced when the update actually carries one.
I check
new_handlealone rather thanresumable and new_handlelike the docs sample, becauseresumable=falseis the proto default and gets left off the wire, so the handle itself is the reliable signal.Testing Plan
Unit Tests:
I added two tests to
tests/unittests/live/test_live_llm_flow.py:test_run_live_resumes_a_connection_lost_while_not_resumablegoes throughRunner.run_livewith a scripted live model. It's parametrized over GoAway, 1006, 1011 andConnectionClosed, and checks that the reconnect uses the last handle and skips the history replay.test_receive_from_model_keeps_the_last_handle_the_server_offeredcovers the bookkeeping directly, for both shapes a handle-less update takes:resumable=False, and an update with onlylast_consumed_client_message_index.All 6 cases fail on
mainand pass with the fix.Checklist
Additional context
Two related things I noticed and left out to keep this focused:
Happy to send either as a follow-up.
🤖 Generated with Claude Code