Skip to content

fix(google): add fallback thought signature sentinel for foreign function calls#6420

Open
igui wants to merge 1 commit into
livekit:mainfrom
igui:fix/gemini-fallback-thought-signature-sentinel
Open

fix(google): add fallback thought signature sentinel for foreign function calls#6420
igui wants to merge 1 commit into
livekit:mainfrom
igui:fix/gemini-fallback-thought-signature-sentinel

Conversation

@igui

@igui igui commented Jul 14, 2026

Copy link
Copy Markdown

Fixes #6135

Reimplementation of #6138 — that PR is stuck because its author was unable to sign the CLA, so this rewrites the same fix from scratch (I filed the original issue and have signed the CLA). Credit to @nightcityblade for the original implementation and review iterations.

Summary

When google.LLM (Gemini 2.5+/3) sits behind another provider in a FallbackAdapter, the ChatContext can contain function calls produced by a non-Google model. Those calls have no stored thought signature, and Gemini rejects the request with HTTP 400 INVALID_ARGUMENT ("Function call is missing a thought_signature in functionCall parts").

  • Inject Google's documented skip_thought_signature_validator sentinel for any function_call part whose call_id has no stored thought signature.
  • Real stored signatures are passed through unchanged, and the field is still omitted entirely for models that don't require thought signatures (pre-2.5).
  • Tolerate a missing/None _thought_signatures cache on the LLM instance, both when formatting the request and when storing a returned signature.
  • Regression coverage at the formatter level (existing / missing / disabled signature) and at the request level (2.5+ with None cache sends the sentinel; pre-2.5 omits the field even with a cached signature).

Note: per Google's docs the sentinel is a last resort and can degrade model performance around function calls; it is only ever used for call_ids the Gemini API did not generate, where the alternative is a hard 400.

Tests

  • uv run ruff check / uv run ruff format --check on the touched files
  • uv run pytest tests/test_google_thought_signatures.py tests/test_plugin_google_llm.py -q — 55 passed
  • uv run pytest tests/test_chat_ctx.py tests/test_tokenizer_xml_markup.py tests/test_expr_markup.py -q — 106 passed, 1 skipped

…gn function calls

Gemini 2.5+ rejects multi-turn requests (HTTP 400 INVALID_ARGUMENT) when a
function_call part has no thought_signature, which happens whenever the
ChatContext contains tool calls produced by another provider — e.g. when
google.LLM is a fallback in FallbackAdapter behind a non-Google LLM.

Use Google's documented validator-skip sentinel for call_ids without a
stored signature, keep real signatures unchanged, and continue omitting
the field entirely for models that don't require thought signatures.
Also tolerate a missing/None signature cache on the LLM instance.

Fixes livekit#6135
@igui
igui requested a review from a team as a code owner July 14, 2026 12:31

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

google.LLM in FallbackAdapter fails with HTTP 400 when ChatContext contains function calls from a non-Google model

1 participant