Skip to content

fix: IncludeServerSideToolInvocations field in genai api - #5576

Merged
akshaydeo merged 2 commits into
devfrom
07-27-fix_includeserversidetoolinvocations_field_in_genai_api
Jul 27, 2026
Merged

fix: IncludeServerSideToolInvocations field in genai api#5576
akshaydeo merged 2 commits into
devfrom
07-27-fix_includeserversidetoolinvocations_field_in_genai_api

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds include_server_side_tool_invocations as a first-class parameter on both the Chat and Responses schemas. Gemini 3+ rejects requests that mix function declarations with built-in tools like Google Search unless this flag is explicitly set; without it, function declarations are silently dropped to preserve existing behaviour. This PR also fixes a bug where grounding annotations were only emitting one citation per segment (the first chunk index), losing all additional sources.

Changes

  • Added IncludeServerSideToolInvocations *bool to ChatParameters and ResponsesParameters schemas, registered in the HTTP handler's known-fields maps for both chat and responses paths.
  • Added applyServerSideToolInvocations helper in Gemini utils that sets toolConfig.includeServerSideToolInvocations = true and promotes AUTO (or unset) function-calling mode to VALIDATED, as Gemini rejects AUTO in combination mode.
  • Updated convertResponsesToolsToGemini to accept the flag and, when set, emit function declarations and Google Search as separate Tool entries (matching Google's documented tool-combination shape) rather than collapsing them into one or dropping declarations.
  • Wired the flag through both the chat (ToGeminiChatCompletionRequest) and responses (ToGeminiResponsesRequest) conversion paths.
  • Extended ToBifrostResponsesRequest (native genai round-trip) to read IncludeServerSideToolInvocations from ToolConfig, with a custom UnmarshalJSON on ToolConfig that accepts both camelCase and snake_case spellings.
  • Fixed grounding annotation emission in both the non-streaming (convertGeminiCandidatesToResponsesOutput) and streaming (emitAnnotationsFromGroundingSupports) paths to iterate over all GroundingChunkIndices per support rather than only the first, skipping chunks with no Web field or an empty URI, and using per-annotation index values instead of a shared pointer.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go test ./core/providers/gemini/... -run TestIncludeServerSideToolInvocations
go test ./core/providers/gemini/... -run TestIncludeServerSideToolInvocationsGenAIRoundTrip
go test ./core/providers/gemini/... -run TestGroundingMultiSourceCitationsResponses
go test ./core/providers/gemini/... -run TestGeminiResponsesStreamMultiSourceAnnotations
go test ./...

To exercise end-to-end, send a Gemini 3+ request with both a web_search tool and a function declaration, setting "include_server_side_tool_invocations": true. Without the flag the function declaration is dropped; with it both tools appear on the wire and Gemini accepts the request.

Breaking changes

  • No

Existing behaviour is preserved: when the flag is absent or false, function declarations are still dropped when Google Search is present, matching the previous default.

Related issues

Security considerations

None. The flag controls tool-combination semantics on the Gemini API and does not affect authentication, secrets, or PII handling.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


tejas ghatte seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Gemini request schemas and conversions now support optional server-side tool invocations, preserve configuration across JSON formats, separate function and Google Search tools, account for grounding search usage, and emit multi-source citations in streaming and non-streaming Responses conversions.

Changes

Gemini tooling and grounding

Layer / File(s) Summary
Request parameter contracts and decoding
core/schemas/..., transports/bifrost-http/handlers/inference.go, core/providers/gemini/types.go
Adds the server-side invocation parameter, recognizes it during HTTP parsing, and decodes Gemini tool configuration from camelCase and snake_case JSON.
Server-side tool request conversion
core/providers/gemini/chat.go, core/providers/gemini/responses.go, core/providers/gemini/utils.go
Propagates the opt-in flag, normalizes function-calling mode, and sends function declarations and Google Search as separate Gemini tool entries when enabled.
Grounding citations and search usage
core/providers/gemini/chat.go, core/providers/gemini/responses.go, core/providers/gemini/utils.go
Records grounding search-query usage and emits citations for valid support and grounding chunk pairs, including streaming and fallback output handling.
Conversion and end-to-end regression coverage
core/providers/gemini/*_test.go, tests/e2e/api/collections/provider-harness.json, tests/cmd/*/go.mod
Validates tool combinations, JSON round trips, grounding annotations, search-entry-point preservation, and updated core module versions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HTTPRequest
  participant RequestParameters
  participant GeminiConversion
  participant GeminiGenerationRequest
  HTTPRequest->>RequestParameters: parse include_server_side_tool_invocations
  RequestParameters->>GeminiConversion: pass opt-in flag
  GeminiConversion->>GeminiGenerationRequest: create separate function and Google Search tools
  GeminiConversion->>GeminiGenerationRequest: apply server-side tool invocation settings
Loading

Suggested reviewers: akshaydeo, danpiths, pratham-mishra04, sammaji

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 85.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title names the Gemini IncludeServerSideToolInvocations field change and matches the main scope of the PR.
Description check ✅ Passed The description follows the template with summary, changes, type, affected areas, tests, breaking changes, security, and checklist.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-27-fix_includeserversidetoolinvocations_field_in_genai_api

Comment @coderabbitai help to get the list of available commands.

TejasGhatte commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator Author

@TejasGhatte TejasGhatte mentioned this pull request Jul 27, 2026
18 tasks
@TejasGhatte
TejasGhatte marked this pull request as ready for review July 27, 2026 09:21
@TejasGhatte
TejasGhatte force-pushed the 07-27-fix_includeserversidetoolinvocations_field_in_genai_api branch from fe968cd to a391b54 Compare July 27, 2026 09:56
@coderabbitai
coderabbitai Bot requested a review from danpiths July 27, 2026 09:57

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
core/providers/gemini/responses.go (1)

3908-3966: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Citation-building logic duplicated with the non-stream path; prefer schemas.Ptr() over &field.

The (support, chunk) → url_citation annotation construction here (3928-3961) mirrors the non-stream logic at responses.go lines 2719-2743 almost line-for-line (bounds/URL checks, Title/URL/segment-offset population). Extracting a shared helper, e.g. buildURLCitationAnnotations(supports []*GroundingSupport, chunks []*GroundingChunk) []schemas.ResponsesOutputMessageContentTextAnnotation, would keep both call sites in sync going forward — they were both touched by this very PR and are already showing minor drift (see the &field vs schemas.Ptr() note below).

Separately, lines 3940/3943/3948 take the address of struct fields directly (&chunk.Web.URI, &support.Segment.Text, &chunk.Web.Title) instead of using schemas.Ptr(...) as the non-stream path and the rest of the codebase does.

Based on learnings, "prefer using bifrost.Ptr() to create pointers instead of the address operator (&) even when & would be valid syntactically... Apply this consistently across all code paths."

♻️ Proposed Ptr() fix
 			annotation := schemas.ResponsesOutputMessageContentTextAnnotation{
 				Type: "url_citation",
-				URL:  &chunk.Web.URI,
+				URL:  schemas.Ptr(chunk.Web.URI),
 			}
 			if support.Segment.Text != "" {
-				annotation.Text = &support.Segment.Text
+				annotation.Text = schemas.Ptr(support.Segment.Text)
 			}
 			annotation.StartIndex = schemas.Ptr(int(support.Segment.StartIndex))
 			annotation.EndIndex = schemas.Ptr(int(support.Segment.EndIndex))
 			if chunk.Web.Title != "" {
-				annotation.Title = &chunk.Web.Title
+				annotation.Title = schemas.Ptr(chunk.Web.Title)
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/gemini/responses.go` around lines 3908 - 3966, Extract the
shared grounding-support citation construction used by
emitAnnotationsFromGroundingSupports and the non-stream path into a helper such
as buildURLCitationAnnotations, preserving the existing bounds, URL,
segment-offset, and multi-source behavior. Update both call sites to use the
helper, and construct URL, text, and title pointers with schemas.Ptr(...)
instead of taking field addresses.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/gemini/responses.go`:
- Around line 2719-2766: Update grounding citation attachment to use each
GroundingSupport.Segment.PartIndex when selecting the candidate text block,
rather than always targeting textMessageIdx; apply the same mapping in the
streaming helper. Preserve the standalone fallback only when the referenced text
block is absent, and initialize its text block’s LogProbs as an empty array
instead of null.

---

Nitpick comments:
In `@core/providers/gemini/responses.go`:
- Around line 3908-3966: Extract the shared grounding-support citation
construction used by emitAnnotationsFromGroundingSupports and the non-stream
path into a helper such as buildURLCitationAnnotations, preserving the existing
bounds, URL, segment-offset, and multi-source behavior. Update both call sites
to use the helper, and construct URL, text, and title pointers with
schemas.Ptr(...) instead of taking field addresses.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c9f7792a-9ea8-41fd-b2f7-0d1166381e23

📥 Commits

Reviewing files that changed from the base of the PR and between fe968cd and a391b54.

📒 Files selected for processing (9)
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/types.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/websearchstreamstate_test.go
  • core/schemas/chatcompletions.go
  • core/schemas/responses.go
  • transports/bifrost-http/handlers/inference.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • core/schemas/chatcompletions.go
  • core/providers/gemini/chat.go
  • core/schemas/responses.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/types.go
  • transports/bifrost-http/handlers/inference.go
  • core/providers/gemini/websearchstreamstate_test.go

Comment thread core/providers/gemini/responses.go
@TejasGhatte
TejasGhatte force-pushed the 07-27-fix_includeserversidetoolinvocations_field_in_genai_api branch from a391b54 to f5d98ef Compare July 27, 2026 10:22
@TejasGhatte
TejasGhatte force-pushed the 07-27-fix_includeserversidetoolinvocations_field_in_genai_api branch from f5d98ef to fd57bd8 Compare July 27, 2026 11:02

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/gemini/chat.go`:
- Around line 69-71: Update the Gemini chat conversion flow around
convertBifrostToolsToGemini and the IncludeServerSideToolInvocations check so
function declarations are omitted unless server-side tool invocations are
explicitly enabled. Ensure requests with unset or false opt-in, including those
using WebSearchOptions, do not send function declarations, and add chat coverage
for both disabled states.

In `@core/providers/gemini/utils.go`:
- Around line 1850-1869: Update applyServerSideToolInvocations to handle
requests without FunctionDeclarations: either skip enabling server-side tool
invocations at the caller in ToGeminiChatCompletionRequest, or clear
FunctionCallingConfig before applying the mode when declarations are absent.
Ensure search-only requests do not send an invalid tool config, while preserving
the existing AUTO-to-VALIDATED behavior when function declarations exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b0d9f220-cbcd-4e5c-b314-6af156b8eefd

📥 Commits

Reviewing files that changed from the base of the PR and between f5d98ef and fd57bd8.

📒 Files selected for processing (13)
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/types.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/websearchstreamstate_test.go
  • core/schemas/chatcompletions.go
  • core/schemas/responses.go
  • tests/cmd/e2eseed/go.mod
  • tests/cmd/seed/go.mod
  • tests/cmd/seedvks/go.mod
  • tests/e2e/api/collections/provider-harness.json
  • transports/bifrost-http/handlers/inference.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • core/schemas/responses.go
  • tests/cmd/seed/go.mod
  • tests/cmd/e2eseed/go.mod
  • core/schemas/chatcompletions.go
  • transports/bifrost-http/handlers/inference.go
  • core/providers/gemini/types.go
  • tests/cmd/seedvks/go.mod
  • tests/e2e/api/collections/provider-harness.json
  • core/providers/gemini/websearchstreamstate_test.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go

Comment thread core/providers/gemini/chat.go
Comment thread core/providers/gemini/utils.go
@TejasGhatte
TejasGhatte force-pushed the 07-27-fix_includeserversidetoolinvocations_field_in_genai_api branch from fd57bd8 to f3ebadb Compare July 27, 2026 11:28

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
core/providers/gemini/chat.go (1)

41-83: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Chat conversion path may still send function declarations + Google Search together without the opt-in flag, and no test would catch it.

ToGeminiChatCompletionRequestWithImageURLSchemes unconditionally builds function declarations (line 43) and unconditionally appends the GoogleSearch tool for WebSearchOptions (line 77); applyServerSideToolInvocations (lines 80-82) only sets flags/mode when IncludeServerSideToolInvocations is true — it never strips declarations when the flag is false/absent. This mirrors a previously flagged issue on this same PR (chat.go:69-71, marked "Addressed") and the currently visible code shows no drop logic, so it's unclear the fix covers the chat path. Meanwhile, the Responses path is proven (via tests) to drop declarations in the equivalent scenario.

  • core/providers/gemini/chat.go#L41-L83: add the same declarations-drop logic used on the Responses path (or verify it already exists in convertBifrostToolsToGemini/responses.go) when WebSearchOptions is set and IncludeServerSideToolInvocations is false/absent.
  • core/providers/gemini/gemini_test.go#L4823-L4844: add a chat-path subtest for IncludeServerSideToolInvocations false/nil + WebSearchOptions + function tools, asserting only the GoogleSearch tool remains — mirroring the existing Responses-path negative test at lines 4783-4789.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/gemini/chat.go` around lines 41 - 83, The chat conversion path
in ToGeminiChatCompletionRequestWithImageURLSchemes must remove function
declarations when WebSearchOptions is set and IncludeServerSideToolInvocations
is false or absent, leaving only the GoogleSearch tool; reuse the equivalent
Responses-path logic rather than changing convertBifrostToolsToGemini broadly.
Add a chat-path subtest in core/providers/gemini/gemini_test.go covering
nil/false opt-in with WebSearchOptions and function tools, asserting that only
GoogleSearch remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/gemini/gemini_test.go`:
- Around line 4823-4844: Add chat-path negative subtests alongside “chat path
sets the flag on toolConfig” for IncludeServerSideToolInvocations nil and false
with WebSearchOptions configured; assert the request succeeds and only the
GoogleSearch tool remains, with function declarations omitted. Mirror the
existing Responses flag-false coverage while keeping the current true-case test
unchanged.

---

Duplicate comments:
In `@core/providers/gemini/chat.go`:
- Around line 41-83: The chat conversion path in
ToGeminiChatCompletionRequestWithImageURLSchemes must remove function
declarations when WebSearchOptions is set and IncludeServerSideToolInvocations
is false or absent, leaving only the GoogleSearch tool; reuse the equivalent
Responses-path logic rather than changing convertBifrostToolsToGemini broadly.
Add a chat-path subtest in core/providers/gemini/gemini_test.go covering
nil/false opt-in with WebSearchOptions and function tools, asserting that only
GoogleSearch remains.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c6b4aad0-04cc-491a-9d52-12a27e2d3365

📥 Commits

Reviewing files that changed from the base of the PR and between fd57bd8 and f3ebadb.

📒 Files selected for processing (13)
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini_test.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/types.go
  • core/providers/gemini/utils.go
  • core/providers/gemini/websearchstreamstate_test.go
  • core/schemas/chatcompletions.go
  • core/schemas/responses.go
  • tests/cmd/e2eseed/go.mod
  • tests/cmd/seed/go.mod
  • tests/cmd/seedvks/go.mod
  • tests/e2e/api/collections/provider-harness.json
  • transports/bifrost-http/handlers/inference.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • tests/cmd/seed/go.mod
  • core/schemas/responses.go
  • core/schemas/chatcompletions.go
  • core/providers/gemini/types.go
  • transports/bifrost-http/handlers/inference.go
  • tests/cmd/e2eseed/go.mod
  • core/providers/gemini/websearchstreamstate_test.go
  • tests/e2e/api/collections/provider-harness.json
  • tests/cmd/seedvks/go.mod
  • core/providers/gemini/utils.go
  • core/providers/gemini/responses.go

Comment thread core/providers/gemini/gemini_test.go
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 27, 2026
akshaydeo
akshaydeo previously approved these changes Jul 27, 2026

akshaydeo commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jul 27, 12:23 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 27, 12:24 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 07-27-docs_responses_retrieve_stream to graphite-base/5576 July 27, 2026 12:24
@akshaydeo
akshaydeo changed the base branch from graphite-base/5576 to dev July 27, 2026 12:24
@akshaydeo
akshaydeo dismissed stale reviews from coderabbitai[bot] and themself July 27, 2026 12:24

The base branch was changed.

@akshaydeo
akshaydeo merged commit 75b5b2e into dev Jul 27, 2026
8 of 9 checks passed
@akshaydeo
akshaydeo deleted the 07-27-fix_includeserversidetoolinvocations_field_in_genai_api branch July 27, 2026 12:24
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.

3 participants