Skip to content

Surface Gemini server-side tool-call and tool-response parts - #1107

Open
PratikDhanave (PratikDhanave) wants to merge 1 commit into
microsoft:mainfrom
PratikDhanaveFork:fix/gemini-server-side-tool-parts
Open

PratikDhanave (PratikDhanave) wants to merge 1 commit into
microsoft:mainfrom
PratikDhanaveFork:fix/gemini-server-side-tool-parts

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

Gemini can echo back server-side tool invocations as toolCall / toolResponse response parts (e.g. when a function tool is combined with a native tool). buildResponsePart only handled Thought, Text, FunctionCall, InlineData, FileData, ExecutableCode, and CodeExecutionResult — it never read part.ToolCall or part.ToolResponse, so those parts were silently dropped and the caller never observed the model's server-side tool interactions.

The Python client (_parse_parts) maps both: tool_call → a function call with informational_only=True, tool_response → a function result.

Change

  • Map part.ToolCallFunctionCallContent{InformationalOnly: true} — surfaced so callers can observe it, but marked informational so the tool-call loop does not try to execute a call the server already ran (toolautocall skips InformationalOnly calls).
  • Map part.ToolResponseFunctionResultContent.
  • Tool name comes from ToolType (fallback "tool_call"); missing call ids are synthesized like the existing FunctionCall path.

Test

  • TestServerSideToolCallAndResponsePartsSurfaced: a candidate carrying a toolCall and a toolResponse now surfaces an informational-only FunctionCallContent and a FunctionResultContent. Fails before the change (both dropped), passes after.

buildResponsePart never inspected part.ToolCall or part.ToolResponse, so a
server-side tool invocation echoed back by the model (its call and result)
was silently dropped and the caller never saw it.

Map part.ToolCall to an informational-only FunctionCallContent (so the tool
loop observes but does not re-execute the server-side call) and
part.ToolResponse to a FunctionResultContent, mirroring the Python client.
Tool names come from ToolType; missing call ids are synthesized like the
existing FunctionCall path.
Copilot AI lite review requested due to automatic review settings September 19, 2026 11:01
@github-actions github-actions Bot added area:provider Changes files in the provider area area:provider/gemini Changes files in the provider / gemini area size:medium At most 100 changed lines across at most 5 files labels Sep 19, 2026

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Address call-ID correlation and ThoughtSignature preservation; strengthen the response-payload assertion.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Surfaces Gemini server-side tool calls and responses as framework function content.

Changes:

  • Maps ToolCall to informational-only function calls.
  • Maps ToolResponse to function results.
  • Adds regression coverage for both mappings.
File Summary
provider/​geminiprovider/​agent.go Converts server-side tool parts into framework content.
provider/​geminiprovider/​agent_test.go Tests surfaced tool calls and responses.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +615 to +618
callID := part.ToolResponse.ID
if callID == "" {
callID = "tool-call-" + uuid.NewString()
}
@github-actions github-actions Bot added kind:code Changes production behavior or code kind:tests Changes tests, fixtures, or test infrastructure labels Sep 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Scope: internal-only (bug fix to unexported parsing logic; no exported API surface added or changed)

Changed Go contract: None. provider/geminiprovider/agent.go's unexported buildResponsePart now also reads part.ToolCall / part.ToolResponse and emits already-existing exported types message.FunctionCallContent{InformationalOnly: true} and message.FunctionResultContent. No new exported functions, types, fields, or options were introduced; InformationalOnly on FunctionCallContent already existed and is already respected by agent/harness/toolautocall (e.g. autocall.go:301,446,726).

Upstream evidence reviewed: python/packages/gemini/agent_framework_gemini/_chat_client.py, method _parse_parts (lines ~1194-1246):

  • part.tool_call is not None → builds a FunctionCallContent-equivalent with informational_only=True, tool_name from tool_call.tool_type (falls back to "tool_call"), and a generated call_id via _generate_tool_call_id() when missing.
  • part.tool_response is not None → builds a function-result-equivalent with call_id=tool_response.id or self._generate_tool_call_id() and result=tool_response.response.

The Go change (provider/geminiprovider/agent.go) mirrors this mapping symbol-for-symbol: part.ToolCallFunctionCallContent{Name: string(ToolType) or "tool_call", InformationalOnly: true, CallID: ID or generated}, and part.ToolResponseFunctionResultContent{CallID: ID or generated, Result: Response}.

Result: Aligned. This closes a genuine parity gap (Go was previously silently dropping these parts while Python already surfaced them) and does not introduce any exported Go API or new user-configurable behavior — the new content is instances of existing public types and is correctly treated as non-executable via the existing InformationalOnly short-circuit in toolautocall. No inline findings; no public-api-change label needed.

Generated by Go API Consistency Review Agent · copilot · auto · 20.4 AIC · ⌖ 6.14 AIC · ⊞ 9.2K ·

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

Labels

area:provider/gemini Changes files in the provider / gemini area area:provider Changes files in the provider area kind:code Changes production behavior or code kind:tests Changes tests, fixtures, or test infrastructure size:medium At most 100 changed lines across at most 5 files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants