Repository navigation
fix(agents): send Gemini thought signatures back through the chat-completions bridge - #409
Merged
Merged
Conversation
…pletions bridge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale
approved these changes
Oct 30, 2026
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.
The Gemini agent's chat-completions bridge, used for provider-prefixed models (
vertex_ai/...), reads each tool call's thought signature off the LiteLLM response and hands it to the CLI asthoughtSignature, but drops it when it turns the CLI's history back into OpenAI messages. Gemini 3 and newer require the signature on the next request, so Vertex answersFunction call is missing a thought_signature in functionCall partsand the turn fails after its first tool call. LiteLLM hides this only for model names its_is_gemini_3_or_newerrecognizes, where it fills in a placeholder signature; for any other Gemini 3+ name the call goes out unsigned and fails every time.This change carries each part's
thoughtSignatureback as the tool call'sprovider_specific_fields.thought_signature, the field LiteLLM reads first on input. Because every signature now goes back to Vertex, the response side also stops copying a message-level signature onto every call of a parallel batch: Gemini signs only the first call, and LiteLLM's Vertex transformation notes that Gemini 3+ bills each replayed copy as the previous turn's reasoning tokens (litellm/llms/vertex_ai/gemini/transformation.py).Rollout
/geminipassthrough (bare model names) is untouched.agentenv-geminiimage (src-<hex>changes with this folder). Anyone running a registered copy of the agent needs to register the new image to pick it up. Until then, a bare model name avoids the bridge.Validation
Head
c6bfb22(same tree as the reviewed5cb0252)./litellm-geminiproxy, two tool turns end to endtest_each_tool_calls_thought_signature_survives_the_round_tripfails onmain(no signatures sent), passes on headtest_a_message_level_signature_goes_only_to_the_first_parallel_callfails onmain, passes on headmainpasses there too: shows acceptance, not the fixpytest tst/unit/agents/gemini: 146 passed, 6 skipped. Mutants that drop the signature, attach it unconditionally, or keep only the first turn's fail the suite.make unit-test: 11896 passed, 66 skipped, 2 failed, neither in code this PR touches:tst/unit/agents/hermes/test_hermes_bridge.py::test_the_event_pipe_is_not_left_open_in_the_serverfails the same way on a cleanorigin/mainlocally (macOS), andtst/unit/cli/submit_runs_test.py::test_a_first_ctrl_c_lets_the_runner_finish_stoppingpasses 3 of 3 alone and passed in an earlier full run (timing under the parallel run).ruff check .: clean. Not run: integration tiers (nothing outside the Gemini agent folder changed).Not in this PR
🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no actionable issues were found.Summary
The Gemini bridge now sends tool-call thought signatures back to LiteLLM.
No actionable issues were found. Tests were inspected, not run during this review.
Acknowledged scope:
cikowskistates that signatures on text parts remain dropped because they are optional and outside this fix.Diagram
sequenceDiagram participant CLI as Gemini CLI participant Bridge as Gemini bridge participant LiteLLM LiteLLM-->>Bridge: Tool calls with thought signatures Bridge-->>CLI: Function-call parts with thoughtSignature CLI->>Bridge: History containing those parts Bridge->>LiteLLM: Tool calls with provider_specific_fields.thought_signatureReviews (1) · Last reviewed commit: "fix(agents): send Gemini thought signatu..." · Reviewed by Greptile