agentscope-ai / agentscope-ai/agentscope-java

[Bug]: 1.0.11 流式模式下 ToolUseBlock name 为 null

Đang mở
#1,237 0 bình luận 0 reaction 1 người được giao Được @chickenlj nhận Xem trên GitHub
area/core/model bug
Ngôn ngữ chính
Java
Star
5.6k
Fork
1.3k
Merge trung bình
4 ngày 12 giờ
Pull request đã merge (30 ngày)
77

Mô tả

## 问题描述
Java 使用 AgentScope 1.0.11 + 非 OpenAI 模型(如 Qwen3-14b)开启流式响应(`stream=true`)时,ReAct Agent 执行 MCP 工具调用后,日志中持续输出以下警告且agent无法调用mcp且无法正常返回响应给客户端, 设置 `agent.stream=false`后问题消失。

```plain
WARN i.a.c.f.o.OpenAIMessageConverter - ToolUseBlock has null id or name, skipping
```

## 影响范围
+ **功能影响**:agent无法调用mcp且无法正常返回响应给客户端
+ **日志噪音**:每轮 ReAct 迭代重复打印 WARN
+ **潜在风险**:被丢弃的 ToolUseBlock 不会出现在发给模型的对话历史中,可能影响模型对上下文的理解

## 根因定位
**缺陷位置**:`io.agentscope.core.agent.accumulator.ToolCallsAccumulator.ToolCallBuilder#build()`

### 调用链路
1. LLM(Qwen3, stream)返回流式 chunk,部分 chunk 不携带 `function.name`
2. `OpenAIResponseParser.parseChunkResponse()` 将 name 为 null 的 chunk 设为空串 `""`,创建 fragment ToolUseBlock(`name="__fragment__"`)
3. `ToolCallsAccumulator.ToolCallBuilder.merge()` 判断 `"__fragment__"` 为 placeholder,跳过赋值
4. `ToolCallBuilder.name` 始终为初始值 `null`
5. `ToolCallBuilder.build()` 生成 `ToolUseBlock(id=generated, name=null)`
6. `ReasoningContext.buildFinalMessage()` 将该 ToolUseBlock 存入 Memory 的 assistant Msg
7. 下一轮迭代 `OpenAIMessageConverter.convertAssistantMessage()` 检测到 `name==null`,打印 WARN 并跳过

### 代码缺陷
`ToolCallBuilder.build()` 对 `toolId` 做了 null 兜底(生成合成 ID),但对 `name` 没有做任何兜底处理,直接透传了可能为 null 的字段:

```plain
// ToolCallBuilder.build() 反编译还原
ToolUseBlock.builder()
.id(toolId != null ? toolId : generateId()) // ✅ 有兜底
.name(name) // ❌ 无兜底,可为 null
.input(mergedArgs)
.build();
```

## 临时规避
```plain
agent:
stream: false
```

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.