agentscope-ai / agentscope-ai/agentscope-java
[Bug]: 1.0.11 流式模式下 ToolUseBlock name 为 null
- Vorherrschende Sprache
- Java
- Sterne
- 5.6k
- Forks
- 1.3k
- Ø Merge
- 4 T. 12 Std.
- Gemergte PRs (30 T.)
- 77
Beschreibung
## 问题描述
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
```
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.