agentscope-ai/agentscope-java
[Bug]:AnthropicChatModel 将 ThinkingBlock 作为普通 text 传回 API,导致 400 错误
Open
#2,400 opened on Jul 27, 2026
bughelp wanted
Repository metrics
- Stars
- (3,253 stars)
- PR merge metrics
- (Avg merge 2d 8h) (58 merged PRs in 30d)
Description
先撤销刚才的源码修改:
已撤销。以下是你可以提 issue 的完整描述:
Issue:
环境信息
- AgentScope v2.0.0
- 模型:deepseek-v4-pro(通过 Anthropic 协议接入的第三方模型)
- 场景:多轮对话,ReActAgent
问题现象
多轮对话时,Anthropic API 报 400 错误:
The `content[].thinking` in the thinking mode must be passed back to the API.
根因
AnthropicMessageConverter.java 第131-137行,将 ThinkingBlock 转换为普通 TextBlockParam 传回 API:
} else if (block instanceof ThinkingBlock thinkingBlock) {
contentBlocks.add(
ContentBlockParam.ofText(
TextBlockParam.builder()
.text(thinkingBlock.getThinking())
.build()));
}
问题在于:
- 模型上一轮回复产生了 thinking 块,AgentScope 存入对话历史
- 下一轮请求时,thinking 块被转成普通
text类型传回 API - 但 Anthropic API 要求 thinking 内容必须用**
thinkingcontent type** 原样传回(包含thinking、signature等字段),不能用text类型 - 如果对话经过 CompactionMiddleware 压缩,thinking 块可能被截断或丢失,传回不完整内容,API 直接报 400
触发条件
- 使用 Anthropic 协议的模型(Claude / 第三方如 deepseek-v4-pro)
- 开启了 thinking 模式(
enableThinking: true或thinkingBudget设了值) - 多轮对话(第二轮起),或对话历史经过 compaction 压缩后
建议修复
方案A(推荐):ThinkingBlock 应该用 Anthropic 的 thinking content type 传回,包含 thinking 和 signature 字段,而不是转成 text:
} else if (block instanceof ThinkingBlock thinkingBlock) {
// 用 Anthropic 原生的 thinking content type 传回
contentBlocks.add(ContentBlockParam.ofThinking(
ThinkingBlockParam.builder()
.type("thinking")
.thinking(thinkingBlock.getThinking())
.signature(thinkingBlock.getSignature()) // 需要在 ThinkingBlock 中保存 signature
.build()));
}
方案B(兜底):如果无法保证 thinking 块的完整性(如 compaction 后),应该跳过 ThinkingBlock,不传回 API:
} else if (block instanceof ThinkingBlock) {
// Skip: thinking 块不完整时传回会导致 400
continue;
}
补充说明
- CompactionMiddleware 压缩后也会丢失 thinking 块的
signature,即使转成正确的 thinking type 也会失败 - 对于第三方模型(非 Claude 原生),thinking 的 signature 机制可能不适用
- 建议增加一个配置项:
stripThinkingBlocks=true,在发送前移除所有 thinking 块