diff --git a/agentscope-core/src/main/java/io/agentscope/core/message/ToolResultBlock.java b/agentscope-core/src/main/java/io/agentscope/core/message/ToolResultBlock.java index 3f64596f2..80eb5751f 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/message/ToolResultBlock.java +++ b/agentscope-core/src/main/java/io/agentscope/core/message/ToolResultBlock.java @@ -199,15 +199,19 @@ public static ToolResultBlock text(String text) { /** * Create an error result (for tool method return values). * + *
The result carries {@link ToolResultState#ERROR} so that failures are + * recognized by state, independent of the output text prefix. + * * @param errorMessage Error message - * @return ToolResultBlock with error output + * @return ToolResultBlock with error output and {@code state = ERROR} */ public static ToolResultBlock error(String errorMessage) { return new ToolResultBlock( null, null, List.of(TextBlock.builder().text("Error: " + errorMessage).build()), - null); + null, + ToolResultState.ERROR); } /** diff --git a/agentscope-core/src/test/java/io/agentscope/core/tool/ToolExecutorTest.java b/agentscope-core/src/test/java/io/agentscope/core/tool/ToolExecutorTest.java index b123c3ac9..9ef4cc9a3 100644 --- a/agentscope-core/src/test/java/io/agentscope/core/tool/ToolExecutorTest.java +++ b/agentscope-core/src/test/java/io/agentscope/core/tool/ToolExecutorTest.java @@ -22,6 +22,7 @@ import io.agentscope.core.message.ContentBlock; import io.agentscope.core.message.TextBlock; import io.agentscope.core.message.ToolResultBlock; +import io.agentscope.core.message.ToolResultState; import io.agentscope.core.message.ToolUseBlock; import io.agentscope.core.tool.test.SampleTools; import io.agentscope.core.tool.test.ToolTestUtils; @@ -124,6 +125,20 @@ void shouldReturnErrorWhenToolThrows() { "Error: Tool execution failed: Tool error: test failure", content, "Error message should be wrapped by executor"); + assertEquals( + ToolResultState.ERROR, + responses.get(0).getState(), + "A failed tool call must be reported with state=ERROR, not SUCCESS"); + } + + @Test + @DisplayName("ToolResultBlock.error() carries state=ERROR (issue #2157)") + void errorResultCarriesErrorState() { + // Regression guard: previously error() left state=null (defaulting to + // RUNNING) and relied on an "[ERROR]" text prefix it never produced, so + // determineToolResultState() misclassified failures as SUCCESS. + ToolResultBlock result = ToolResultBlock.error("boom"); + assertEquals(ToolResultState.ERROR, result.getState()); } @Test