From 01cb38e8ecfe4b7fe338fc9e7c17d022963b74bd Mon Sep 17 00:00:00 2001 From: Atakan Date: Sun, 26 Jul 2026 19:08:41 +0300 Subject: [PATCH] fix(gemini): preserve bridged tool response name --- agent/gemini_native_adapter.py | 8 +++-- tests/agent/test_gemini_native_adapter.py | 42 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/agent/gemini_native_adapter.py b/agent/gemini_native_adapter.py index bb53e32b2ce..d19ea378e84 100644 --- a/agent/gemini_native_adapter.py +++ b/agent/gemini_native_adapter.py @@ -321,9 +321,13 @@ def _translate_tool_result_to_gemini( ) -> Dict[str, Any]: tool_name_by_call_id = tool_name_by_call_id or {} tool_call_id = str(message.get("tool_call_id") or "") + # A tool result can carry the unwrapped internal tool name (for example, + # an MCP tool invoked through the `tool_call` bridge). Gemini requires + # functionResponse.name to echo the matching functionCall.name, so the + # call-id mapping must take precedence over the internal result name. name = str( - message.get("name") - or tool_name_by_call_id.get(tool_call_id) + tool_name_by_call_id.get(tool_call_id) + or message.get("name") or tool_call_id or "tool" ) diff --git a/tests/agent/test_gemini_native_adapter.py b/tests/agent/test_gemini_native_adapter.py index e7493fe4918..6a49c416448 100644 --- a/tests/agent/test_gemini_native_adapter.py +++ b/tests/agent/test_gemini_native_adapter.py @@ -122,6 +122,48 @@ def test_build_native_request_uses_original_function_name_for_tool_result(): assert tool_response["name"] == "get_weather" + +def test_build_native_request_prefers_call_name_over_unwrapped_result_name(): + """Gemini must receive the bridge call name, not the internal MCP name.""" + from agent.gemini_native_adapter import build_gemini_request + + request = build_gemini_request( + messages=[ + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "call_1", + "type": "function", + "function": { + "name": "tool_call", + "arguments": ( + '{"name": "mcp__github__create_issue", ' + '"arguments": {"title": "Regression"}}' + ), + }, + } + ], + }, + { + "role": "tool", + "name": "mcp__github__create_issue", + "tool_name": "mcp__github__create_issue", + "tool_call_id": "call_1", + "content": '{"number": 123}', + }, + ], + tools=[], + tool_choice=None, + ) + + function_call = request["contents"][0]["parts"][0]["functionCall"] + function_response = request["contents"][1]["parts"][0]["functionResponse"] + assert function_call["name"] == "tool_call" + assert function_response["name"] == function_call["name"] + + def test_parallel_tool_results_merge_into_one_user_content(): """Gemini requires strict user/model alternation; two consecutive `user` contents are rejected with HTTP 400. Parallel tool calls produce two tool