Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: resolve three bugs in core agent and tool management (#1164 #1165 #1166)#1167

Merged
LearningGp merged 8 commits into
agentscope-ai:mainfrom
Fruank4:fix/bug-1164-1165-1166
Apr 28, 2026
Merged

fix: resolve three bugs in core agent and tool management (#1164 #1165 #1166)#1167
LearningGp merged 8 commits into
agentscope-ai:mainfrom
Fruank4:fix/bug-1164-1165-1166

Conversation

@Fruank4
Copy link
Copy Markdown
Contributor

@Fruank4 Fruank4 commented Apr 8, 2026

Summary

This PR fixes three bugs identified in the core library:

Changes

Fix #1164 — `StaticLongTermMemoryHook.java`

Change memory message role from `SYSTEM` to `USER` and append it at the end of the message list so the sequence remains valid and the memory context is closest to the model's generation point:

```java
// Before
Msg memoryMsg = Msg.builder().role(MsgRole.SYSTEM)...build();
List enhancedMessages = new ArrayList<>();
enhancedMessages.addAll(inputMessages);
enhancedMessages.add(memoryMsg); // appended at end but wrong role

// After
Msg memoryMsg = Msg.builder().role(MsgRole.USER)...build();
List enhancedMessages = new ArrayList<>(inputMessages);
enhancedMessages.add(memoryMsg); // USER role, appended at end
```

Fix #1165 — `ToolGroupManager.java`

Replace the non-thread-safe `ArrayList` with `CopyOnWriteArrayList` (declared `volatile`) and update `setActiveGroups()` / `copyTo()` to replace the reference atomically, avoiding the transient empty-list window that `clear()` + `addAll()` would create:

```java
// Before
private List activeGroups = new ArrayList<>();
// ...
this.activeGroups = new ArrayList<>(activeGroups);
target.activeGroups = new ArrayList<>(this.activeGroups);

// After
private volatile List activeGroups = new CopyOnWriteArrayList<>();
// ...
this.activeGroups = new CopyOnWriteArrayList<>(activeGroups);
target.activeGroups = new CopyOnWriteArrayList<>(this.activeGroups);
```

Fix #1166 — `MessageUtils.java`

Replace `msg.getName().equals(agentName)` with `Objects.equals()` to safely handle `null` names:

```java
// Before
if (msg.getRole() == MsgRole.ASSISTANT && msg.getName().equals(agentName)) {

// After
if (msg.getRole() == MsgRole.ASSISTANT && Objects.equals(msg.getName(), agentName)) {
```

Test plan

  • Existing unit tests pass (`mvn test -pl agentscope-core`)
  • `StaticLongTermMemoryHookTest` updated to assert `USER` role and end-of-list position
  • Verify no `ConcurrentModificationException` when multiple agents modify tool groups concurrently
  • Verify no `NullPointerException` when assistant messages without names are present in memory

@Fruank4 Fruank4 requested a review from a team April 8, 2026 13:28
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 8, 2026

CLA assistant check
All committers have signed the CLA.

Fruank4 added 2 commits April 8, 2026 21:34
- 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 agentscope-ai#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 agentscope-ai#1165)

- MessageUtils.extractRecentToolCalls: replace msg.getName().equals()
  with Objects.equals() to avoid NullPointerException when an assistant
  message has no name set (fixes agentscope-ai#1166)
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 agentscope-ai#1164.
@Fruank4 Fruank4 force-pushed the fix/bug-1164-1165-1166 branch from 4fcddee to 5317598 Compare April 8, 2026 13:34
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 8, 2026

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ain/java/io/agentscope/core/util/MessageUtils.java 0.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@Fruank4
Copy link
Copy Markdown
Contributor Author

Fruank4 commented Apr 9, 2026

三个问题:空指针,并发安全,记忆反序

@Fruank4
Copy link
Copy Markdown
Contributor Author

Fruank4 commented Apr 10, 2026

给孩子过了吧 呜呜呜

@LearningGp
Copy link
Copy Markdown
Collaborator

lichuang34 这个账号没有签署 CLA,要不用Fruank4这个账号提交下后两个commit

@Fruank4
Copy link
Copy Markdown
Contributor Author

Fruank4 commented Apr 14, 2026

CLA验证了

Comment thread agentscope-core/src/main/java/io/agentscope/core/tool/ToolGroupManager.java Outdated
…ring

- ToolGroupManager: replace clear()+addAll() with direct reference swap
  via volatile field to avoid transient empty list visible to readers
- StaticLongTermMemoryHook: change long-term memory msg role from SYSTEM
  to USER and inject at end of message list instead of beginning
@Fruank4 Fruank4 force-pushed the fix/bug-1164-1165-1166 branch from 6ba4830 to 9d0d8fe Compare April 27, 2026 06:47
Fruank4 and others added 2 commits April 27, 2026 14:59
…n behavior

Memory message is now USER role and appended at end of message list.
Copy link
Copy Markdown
Collaborator

@LearningGp LearningGp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@LearningGp LearningGp merged commit 29a9bea into agentscope-ai:main Apr 28, 2026
5 checks passed
liangxingguang pushed a commit to liangxingguang/agentscope-java that referenced this pull request May 21, 2026
…-ai#1164 agentscope-ai#1165 agentscope-ai#1166) (agentscope-ai#1167)

## Summary

This PR fixes three bugs identified in the core library:

- **agentscope-ai#1164** \`StaticLongTermMemoryHook\` injects retrieved memory at the
beginning of the message list with a \`SYSTEM\` role, which breaks
message sequence constraints and degrades RAG quality
- **agentscope-ai#1165** \`ToolGroupManager.activeGroups\` uses a non-thread-safe
\`ArrayList\`, causing race conditions in concurrent agent scenarios
- **agentscope-ai#1166** \`MessageUtils.extractRecentToolCalls\` calls \`.equals()\`
on \`msg.getName()\` without a null check, throwing
\`NullPointerException\` when an assistant message has no name

## Changes

### Fix agentscope-ai#1164 — \`StaticLongTermMemoryHook.java\`

Change memory message role from \`SYSTEM\` to \`USER\` and append it at
the end of the message list so the sequence remains valid and the memory
context is closest to the model's generation point:

\`\`\`java
// Before
Msg memoryMsg = Msg.builder().role(MsgRole.SYSTEM)...build();
List<Msg> enhancedMessages = new ArrayList<>();
enhancedMessages.addAll(inputMessages);
enhancedMessages.add(memoryMsg);   // appended at end but wrong role

// After
Msg memoryMsg = Msg.builder().role(MsgRole.USER)...build();
List<Msg> enhancedMessages = new ArrayList<>(inputMessages);
enhancedMessages.add(memoryMsg);   // USER role, appended at end
\`\`\`

### Fix agentscope-ai#1165 — \`ToolGroupManager.java\`

Replace the non-thread-safe \`ArrayList\` with \`CopyOnWriteArrayList\`
(declared \`volatile\`) and update \`setActiveGroups()\` / \`copyTo()\`
to replace the reference atomically, avoiding the transient empty-list
window that \`clear()\` + \`addAll()\` would create:

\`\`\`java
// Before
private List<String> activeGroups = new ArrayList<>();
// ...
this.activeGroups = new ArrayList<>(activeGroups);
target.activeGroups = new ArrayList<>(this.activeGroups);

// After
private volatile List<String> activeGroups = new
CopyOnWriteArrayList<>();
// ...
this.activeGroups = new CopyOnWriteArrayList<>(activeGroups);
target.activeGroups = new CopyOnWriteArrayList<>(this.activeGroups);
\`\`\`

### Fix agentscope-ai#1166 — \`MessageUtils.java\`

Replace \`msg.getName().equals(agentName)\` with \`Objects.equals()\` to
safely handle \`null\` names:

\`\`\`java
// Before
if (msg.getRole() == MsgRole.ASSISTANT &&
msg.getName().equals(agentName)) {

// After
if (msg.getRole() == MsgRole.ASSISTANT && Objects.equals(msg.getName(),
agentName)) {
\`\`\`

## Test plan

- [x] Existing unit tests pass (\`mvn test -pl agentscope-core\`)
- [x] \`StaticLongTermMemoryHookTest\` updated to assert \`USER\` role
and end-of-list position
- [ ] Verify no \`ConcurrentModificationException\` when multiple agents
modify tool groups concurrently
- [ ] Verify no \`NullPointerException\` when assistant messages without
names are present in memory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants