Bug Description
MessageUtils.extractRecentToolCalls() calls .equals() directly on msg.getName() without a null check. Since Msg.name is an optional field that can be null, this throws a NullPointerException whenever an ASSISTANT message with no name is present in the message list.
Affected File
agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java, line 54
Current Code
for (int i = messages.size() - 1; i >= 0; i--) {
Msg msg = messages.get(i);
if (msg.getRole() == MsgRole.ASSISTANT && msg.getName().equals(agentName)) { // ← NPE here
List<ToolUseBlock> toolCalls = msg.getContentBlocks(ToolUseBlock.class);
if (!toolCalls.isEmpty()) {
return toolCalls;
}
break;
}
}
msg.getName() returns null when the message was constructed without a name (the field is not required by Msg.builder()). Calling .equals() on null throws NullPointerException.
Expected Behavior
The method should handle null names gracefully and simply skip messages where the name does not match.
Impact
- Any
ASSISTANT message in memory that was created without a name field will crash extractRecentToolCalls()
- This method is called during the ReAct agent's acting phase to look up pending tool calls
- The crash propagates up and terminates the agent's reasoning loop
- Third-party integrations that construct
Msg objects without names (a valid use of the API) are silently broken
Steps to Reproduce
// Create an assistant message without a name
Msg assistantMsg = Msg.builder()
.role(MsgRole.ASSISTANT)
// name intentionally omitted
.content(TextBlock.builder().text("Hello").build())
.build();
List<Msg> messages = List.of(assistantMsg);
// This throws NullPointerException
MessageUtils.extractRecentToolCalls(messages, "MyAgent");
Suggested Fix
Use Objects.equals() which handles null safely:
// Before
if (msg.getRole() == MsgRole.ASSISTANT && msg.getName().equals(agentName)) {
// After
if (msg.getRole() == MsgRole.ASSISTANT && Objects.equals(msg.getName(), agentName)) {
Bug Description
MessageUtils.extractRecentToolCalls()calls.equals()directly onmsg.getName()without a null check. SinceMsg.nameis an optional field that can benull, this throws aNullPointerExceptionwhenever anASSISTANTmessage with no name is present in the message list.Affected File
agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java, line 54Current Code
msg.getName()returnsnullwhen the message was constructed without a name (the field is not required byMsg.builder()). Calling.equals()onnullthrowsNullPointerException.Expected Behavior
The method should handle
nullnames gracefully and simply skip messages where the name does not match.Impact
ASSISTANTmessage in memory that was created without anamefield will crashextractRecentToolCalls()Msgobjects without names (a valid use of the API) are silently brokenSteps to Reproduce
Suggested Fix
Use
Objects.equals()which handlesnullsafely: