Skip to content

fix(google): gate mixed tool use to the Gemini 3 Developer API + build tool config in chat()#6426

Merged
tinalenguyen merged 2 commits into
mainfrom
tina/strengthen-tool-construction
Jul 14, 2026
Merged

fix(google): gate mixed tool use to the Gemini 3 Developer API + build tool config in chat()#6426
tinalenguyen merged 2 commits into
mainfrom
tina/strengthen-tool-construction

Conversation

@tinalenguyen

Copy link
Copy Markdown
Member

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

…d tool config in chat()

Combining 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. Gate `include_server_side_tool_invocations` (and the
provider-tool merge) on `not vertexai`, so Vertex falls back to single-type
tool use with a warning instead of sending an unsupported request.

Also moves all tool/tool_config construction out of `LLMStream._run()` and into
`LLM.chat()`, where all of its inputs (tools, tool_choice, model, vertexai,
cached_content) already live. This builds the `ToolConfig` once instead of
mutating one built earlier, drops the build-then-pop cache dance (caching now
simply skips building tools), and leaves `_run()` owning only what depends on
the formatted context (system_instruction). `_run()` no longer mutates shared
request state on retry.

`create_tools_config` now returns `(tools, mixed)` and is the single source of
truth for whether built-in and function tools are combined, so the flag can't
drift from what's actually sent. The cache gate honors cached_content passed via
either the constructor or extra_kwargs.

Adds request-capture tests covering the Dev-API mixed path, the Vertex and
non-Gemini-3 fallbacks, provider-tools-only, tool_choice=auto passthrough, and
cache-via-extra_kwargs suppression.
@tinalenguyen
tinalenguyen requested a review from a team as a code owner July 14, 2026 20:54
devin-ai-integration[bot]

This comment was marked as resolved.

The cache branch skipped building tools but didn't remove tools/tool_config a
caller passed directly via extra_kwargs, so those were sent alongside
cached_content and rejected by Gemini. Restore the old behavior of dropping
them (from either source) when a cache is active.
@tinalenguyen
tinalenguyen merged commit d36f2b7 into main Jul 14, 2026
24 checks passed
@tinalenguyen
tinalenguyen deleted the tina/strengthen-tool-construction branch July 14, 2026 21:59
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.

2 participants