Skip to content

fix(google): gate mixed Gemini tools - #2035

Merged
toubatbrian merged 3 commits into
mainfrom
musical-palmetto-abrades
Jul 15, 2026
Merged

fix(google): gate mixed Gemini tools#2035
toubatbrian merged 3 commits into
mainfrom
musical-palmetto-abrades

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Port livekit/agents#6426 to the JS Google plugin.

  • Gate mixed Gemini built-in/provider tools plus function tools to the Gemini 3 Developer API only.
  • Build Google tools and toolConfig in LLM.chat() instead of LLMStream.run().
  • Suppress tools/toolConfig when cachedContent is active, including raw extraKwargs values.
  • Add request-construction parity tests for mixed tools, Vertex AI, and cached content.

Source diff coverage

Coverage classification
Source file Classification Target file Notes
livekit-plugins/livekit-plugins-google/livekit/plugins/google/llm.py Ported/adapted plugins/google/src/llm.ts Ported request-shaping changes into chat(), added tool-choice mapping helper, gated mixed function/provider tools to Gemini 3 Developer API (gemini-3 and not Vertex AI), and moved cache-related tool suppression out of stream execution. Adapted naming and target-specific geminiTools support.
livekit-plugins/livekit-plugins-google/livekit/plugins/google/utils.py Ported/adapted plugins/google/src/utils.ts Ported the (tools, mixed) return shape and warning/drop behavior when mixed tools are not allowed. Adapted to treat both geminiTools and GeminiTool provider tools as built-in/provider tools in the JS API.
livekit-plugins/livekit-plugins-google/livekit/plugins/google/realtime/realtime_api.py Ported/adapted plugins/google/src/realtime/realtime_api.ts Updated the realtime callsite to consume the new toToolsConfig() tuple. No realtime behavior change beyond matching the new helper contract.
tests/test_plugin_google_llm.py Ported/adapted plugins/google/src/llm.test.ts Ported the added request-construction assertions to Vitest using a mocked GoogleGenAI client and the target toolCtx API. No extra tests beyond source parity.

Verification

  • pnpm test plugins/google passes: 3 files, 15 passed, 2 skipped.
  • pnpm --filter @livekit/agents-plugin-google build passes.
  • pnpm --filter @livekit/agents-plugin-google lint exits 0 with existing warnings in plugins/google/src/realtime/realtime_api.ts.
  • pnpm build passes.
  • pnpm lint exits 0 with existing warnings across the repo.

Infrastructure gaps

None. The target already had Google provider tools, cached content, and request-config testing infrastructure; the required helper contract changes were ported as part of this PR.


Ported from livekit/agents#6426

Original PR description

Follow-up to #6416 (mixed built-in + function tool support). Two things: a correctness fix (Vertex) and a structural cleanup (move request shaping into chat()).

Why

  • Vertex gap. Mixing built-in (provider) tools with function tools is only supported on the Gemini 3 Developer API — Vertex AI drops search tools when function declarations are present (docs). The merged code set include_server_side_tool_invocations on Vertex too, producing a request Vertex rejects.
  • Split construction. Tool/tool_config construction lived in LLMStream._run() even though all its inputs (tools, tool_choice, model, vertexai, cached_content) are known at chat() time. That forced a build-then-mutate pattern, a duplicated mixed-tools predicate, and a build-then-pop() cache dance.

What changed

  • Vertex gate: is_gemini_3_api = _is_gemini_3_model(model) and not client.vertexai. On Vertex, mixing falls back to single-type tool use with a warning instead of an unsupported request.
  • Moved all tool/tool_config construction from _run() into chat(). Builds the ToolConfig once; _run() now owns only what depends on the formatted context (system_instruction dropping) and no longer mutates shared request state on retry.
  • Cache handling is now a plain if/else in chat() (skip building tools when cached) instead of build-then-pop(). Honors cached_content from either the constructor or extra_kwargs.
  • create_tools_config returns (tools, mixed) and is the single source of truth for whether built-in + function tools are actually combined, so the server-side-invocation flag can't drift from what's sent.

Note on tool_choice="auto"

AUTO is passed through as-is alongside the circulation flag (no AUTO→VALIDATED upgrade). Verified live against the Gemini 3 Developer API: AUTO + built-in tools is accepted.

Tests

New request-capture tests in test_plugin_google_llm.py covering: Dev-API mixed path, Vertex fallback, non-Gemini-3 fallback, provider-tools-only, tool_choice="auto" passthrough, and cache-via-extra_kwargs suppression. All 21 google LLM tests pass; ruff clean.

🤖 Generated with Claude Code

Cue voice E2E

  • Voice-mode request-shaping session: sid_9f619be36f11 at head b79ec082.
  • A deterministic local Google-compatible HTTP boundary captured the real plugin request and persisted developerApiMixedTools=true, function tool get_weather, and toolChoiceMode=AUTO; the spoken turn completed as Request shape verified.
  • QCLI persisted framework events plus full-session and per-command WAV recordings under ~/.cue-cli/sessions/sid_9f619be36f11/.
  • Provider limitation: request construction was verified against a local protocol-compatible boundary rather than the production Gemini endpoint. The later 22e91679 custom-function-config fix is covered by a red-green request-boundary regression test; the final focused suite passes 12/12.

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner July 14, 2026 22:06
@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 22e9167

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 36 packages
Name Type
@livekit/agents-plugin-google Patch
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch
@livekit/agents-plugins-test Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@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

Keep mocked provider-boundary coverage from replacing credentialed integration clients, and cover tool-choice mapping plus retry-stable configs.

Co-authored-by: Cursor <cursoragent@cursor.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Avoid replacing caller-supplied function-calling settings when mixed tools only require the server-side invocation flag.

Co-authored-by: Cursor <cursoragent@cursor.com>
@toubatbrian
toubatbrian merged commit 227b92b into main Jul 15, 2026
8 checks passed
@toubatbrian
toubatbrian deleted the musical-palmetto-abrades branch July 15, 2026 00:10
@github-actions github-actions Bot mentioned this pull request Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant