From ef8c2d85bf064647f5c5b0bab06ba9f20e97b486 Mon Sep 17 00:00:00 2001 From: zhengyateng Date: Wed, 22 Jul 2026 16:56:40 +0800 Subject: [PATCH 1/5] fix(gemini): group parallel tool responses --- .../formatter/GeminiMessageConverter.java | 20 ++++++------ .../formatter/GeminiMessageConverterTest.java | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java index 4ca629ed45..fbdf834214 100644 --- a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java +++ b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java @@ -59,7 +59,7 @@ * *

Important Conversion Behaviors: *

@@ -88,6 +88,7 @@ public List convertMessages(List msgs) { for (Msg msg : msgs) { List parts = new ArrayList<>(); + List toolResultParts = new ArrayList<>(); for (ContentBlock block : msg.getContent()) { if (block instanceof TextBlock tb) { @@ -137,7 +138,7 @@ public List convertMessages(List msgs) { parts.add(partBuilder.build()); } else if (block instanceof ToolResultBlock trb) { - // IMPORTANT: Tool result as independent Content with "user" role + // Tool results from the same message share one user Content. String textOutput = convertToolResultToString(trb.getOutput()); // Create response map with "output" key @@ -154,14 +155,7 @@ public List convertMessages(List msgs) { Part functionResponsePart = Part.builder().functionResponse(functionResponse).build(); - Content toolResultContent = - Content.builder() - .role("user") - .parts(List.of(functionResponsePart)) - .build(); - - result.add(toolResultContent); - // Skip adding to current message parts + toolResultParts.add(functionResponsePart); continue; } else if (block instanceof ImageBlock ib) { @@ -190,6 +184,12 @@ public List convertMessages(List msgs) { } } + if (!toolResultParts.isEmpty()) { + Content toolResultContent = + Content.builder().role("user").parts(toolResultParts).build(); + result.add(toolResultContent); + } + // Add message if there are parts if (!parts.isEmpty()) { String role = convertRole(msg.getRole()); diff --git a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java index 6cad792f02..2b33991964 100644 --- a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java +++ b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java @@ -223,6 +223,38 @@ void testConvertToolResultBlock() { assertEquals("Result text", part.functionResponse().get().response().get().get("output")); } + @Test + @DisplayName("Should group tool results from one message into one user Content") + void testConvertMultipleToolResultBlocks() { + ToolResultBlock firstResult = + ToolResultBlock.builder() + .id("call_123") + .name("search") + .output(List.of(TextBlock.builder().text("First result").build())) + .build(); + ToolResultBlock secondResult = + ToolResultBlock.builder() + .id("call_456") + .name("lookup") + .output(List.of(TextBlock.builder().text("Second result").build())) + .build(); + Msg msg = + Msg.builder() + .name("system") + .content(List.of(firstResult, secondResult)) + .role(MsgRole.TOOL) + .build(); + + List result = converter.convertMessages(List.of(msg)); + + assertEquals(1, result.size()); + Content content = result.get(0); + assertEquals("user", content.role().get()); + assertEquals(2, content.parts().get().size()); + assertEquals("call_123", content.parts().get().get(0).functionResponse().get().id().get()); + assertEquals("call_456", content.parts().get().get(1).functionResponse().get().id().get()); + } + @Test @DisplayName("Should format tool result with single output") void testToolResultSingleOutput() { From dec726dbc10465bc712a7ebc46516ca5c5518b88 Mon Sep 17 00:00:00 2001 From: zhengyateng Date: Wed, 22 Jul 2026 17:22:08 +0800 Subject: [PATCH 2/5] docs(gemini): clarify grouped tool response content --- .../model/gemini/formatter/GeminiMessageConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java index fbdf834214..a20e8fa662 100644 --- a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java +++ b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java @@ -53,7 +53,7 @@ *
    *
  • Text blocks
  • *
  • Tool use blocks (function_call)
  • - *
  • Tool result blocks (function_response as independent Content)
  • + *
  • Tool result blocks (function_response grouped into one user Content per message)
  • *
  • Multimodal content (image, audio, video)
  • *
* From 896f115c322d709982365130e1529293a347bdad Mon Sep 17 00:00:00 2001 From: zhengyateng Date: Mon, 24 Aug 2026 11:28:52 +0800 Subject: [PATCH 3/5] ci: rerun flaky Harness cleanup From a9b60c5452bb3ece45b161e85f298b9885573647 Mon Sep 17 00:00:00 2001 From: zhengyateng Date: Mon, 24 Aug 2026 12:37:32 +0800 Subject: [PATCH 4/5] ci: rerun harness cleanup check From a39e0c6740eee8b341b483d8b39ceb739b0a0b8e Mon Sep 17 00:00:00 2001 From: zhengyateng Date: Mon, 24 Aug 2026 13:44:45 +0800 Subject: [PATCH 5/5] ci: retry harness suite once more