From 83247dfad4c6c8504b5a4485464a2728e8f08bcb Mon Sep 17 00:00:00 2001 From: lichuang34 Date: Wed, 8 Apr 2026 21:27:39 +0800 Subject: [PATCH 1/2] fix: resolve three bugs in core agent and tool management - StaticLongTermMemoryHook: inject retrieved memory at the beginning of the message list instead of appending it at the end, so the LLM receives context before the user query (fixes #1164) - ToolGroupManager: replace non-thread-safe ArrayList with CopyOnWriteArrayList for activeGroups, and update setActiveGroups() and copyTo() to mutate the list in-place rather than reassigning the field, preventing race conditions in concurrent agent scenarios (fixes #1165) - MessageUtils.extractRecentToolCalls: replace msg.getName().equals() with Objects.equals() to avoid NullPointerException when an assistant message has no name set (fixes #1166) --- .../agentscope/core/memory/StaticLongTermMemoryHook.java | 2 +- .../java/io/agentscope/core/tool/ToolGroupManager.java | 9 ++++++--- .../main/java/io/agentscope/core/util/MessageUtils.java | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/agentscope-core/src/main/java/io/agentscope/core/memory/StaticLongTermMemoryHook.java b/agentscope-core/src/main/java/io/agentscope/core/memory/StaticLongTermMemoryHook.java index b57bb5433..0a01a00c1 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/memory/StaticLongTermMemoryHook.java +++ b/agentscope-core/src/main/java/io/agentscope/core/memory/StaticLongTermMemoryHook.java @@ -156,8 +156,8 @@ private Mono handlePreCall(PreCallEvent event) { // Inject memory message at the beginning List enhancedMessages = new ArrayList<>(); - enhancedMessages.addAll(inputMessages); enhancedMessages.add(memoryMsg); + enhancedMessages.addAll(inputMessages); event.setInputMessages(enhancedMessages); return Mono.just(event); diff --git a/agentscope-core/src/main/java/io/agentscope/core/tool/ToolGroupManager.java b/agentscope-core/src/main/java/io/agentscope/core/tool/ToolGroupManager.java index c6d4c0fcf..9b4fa72b3 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/tool/ToolGroupManager.java +++ b/agentscope-core/src/main/java/io/agentscope/core/tool/ToolGroupManager.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +34,7 @@ class ToolGroupManager { private final Map toolGroups = new ConcurrentHashMap<>(); // group -> tools private final Map> tools = new ConcurrentHashMap<>(); // tool -> groups - private List activeGroups = new ArrayList<>(); + private final List activeGroups = new CopyOnWriteArrayList<>(); /** * Create tool groups and record them in the manager. @@ -324,7 +325,8 @@ public List getActiveGroups() { * @param activeGroups List of group names to mark as active */ public void setActiveGroups(List activeGroups) { - this.activeGroups = new ArrayList<>(activeGroups); + this.activeGroups.clear(); + this.activeGroups.addAll(activeGroups); // Mark corresponding groups as active for (String groupName : activeGroups) { @@ -374,7 +376,8 @@ void copyTo(ToolGroupManager target) { } // Copy activeGroups list - target.activeGroups = new ArrayList<>(this.activeGroups); + target.activeGroups.clear(); + target.activeGroups.addAll(this.activeGroups); } private boolean removeGroupFromToolIndex(String toolName, String groupName) { diff --git a/agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java b/agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java index c7839f2d6..f28c3a627 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java +++ b/agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java @@ -19,6 +19,7 @@ import io.agentscope.core.message.MsgRole; import io.agentscope.core.message.ToolUseBlock; import java.util.List; +import java.util.Objects; /** * Utility methods for message processing and extraction. @@ -51,7 +52,7 @@ public static List extractRecentToolCalls(List messages, Stri for (int i = messages.size() - 1; i >= 0; i--) { Msg msg = messages.get(i); - if (msg.getRole() == MsgRole.ASSISTANT && msg.getName().equals(agentName)) { + if (msg.getRole() == MsgRole.ASSISTANT && Objects.equals(msg.getName(), agentName)) { List toolCalls = msg.getContentBlocks(ToolUseBlock.class); if (!toolCalls.isEmpty()) { return toolCalls; From 5317598d6480a9c89cf5f35170be2a4c32790138 Mon Sep 17 00:00:00 2001 From: lichuang34 Date: Wed, 8 Apr 2026 21:32:27 +0800 Subject: [PATCH 2/2] fix: update StaticLongTermMemoryHookTest to expect memory at index 0 The test was asserting memory message at index 1 (end), which matched the old buggy behavior. Update to assert index 0 (beginning) to align with the fix in #1164. --- .../core/memory/StaticLongTermMemoryHookTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agentscope-core/src/test/java/io/agentscope/core/memory/StaticLongTermMemoryHookTest.java b/agentscope-core/src/test/java/io/agentscope/core/memory/StaticLongTermMemoryHookTest.java index 37417ee26..14a2c8e46 100644 --- a/agentscope-core/src/test/java/io/agentscope/core/memory/StaticLongTermMemoryHookTest.java +++ b/agentscope-core/src/test/java/io/agentscope/core/memory/StaticLongTermMemoryHookTest.java @@ -138,13 +138,13 @@ void testOnEventWithPreReasoningEventAndRetrievedMemories() { resultEvent -> { List messages = resultEvent.getInputMessages(); assertEquals(2, messages.size()); - assertEquals(MsgRole.SYSTEM, messages.get(1).getRole()); + assertEquals(MsgRole.SYSTEM, messages.get(0).getRole()); assertTrue( - messages.get(1) + messages.get(0) .getTextContent() .contains("")); assertTrue( - messages.get(1) + messages.get(0) .getTextContent() .contains("User prefers dark mode")); })