Skip to content

fix: deduplicate tool results and merge consecutive tool_result blocks for Anthropic API#1793

Merged
alexhoshina merged 1 commit intosipeed:mainfrom
liuliqiang:fix/anthropic-duplicate-tool-result
Mar 23, 2026
Merged

fix: deduplicate tool results and merge consecutive tool_result blocks for Anthropic API#1793
alexhoshina merged 1 commit intosipeed:mainfrom
liuliqiang:fix/anthropic-duplicate-tool-result

Conversation

@liuliqiang
Copy link
Copy Markdown
Contributor

@liuliqiang liuliqiang commented Mar 19, 2026

Fixes #1792

📝 Description

修复使用 Anthropic 提供商时,LLM 调用返回 400 错误:each tool_use must have a single result. Found multiple tool_result blocks with id 的问题。

根因有两个:

  1. 历史消息清理函数 sanitizeHistoryForProvider 未对重复的 ToolCallID 进行去重,导致相同 ID 的 tool result 被多次发送。
  2. Anthropic Messages 适配器在 buildRequestBody 中将每个 tool result 作为独立的 user 消息发送,而 Anthropic API 要求连续的 tool result 必须合并到同一个 user 消息的 content 数组中。

本 PR 的修改:

  • sanitizeHistoryForProviderpkg/agent/context.go)的第二遍扫描中增加 seenToolCallID map,遇到相同 ToolCallID 的 tool 消息时仅保留第一个,跳过后续重复项。
  • 在 Anthropic 的 buildRequestBodypkg/providers/anthropic_messages/provider.go)中,将连续的 tool result(无论是 role: "user" + ToolCallID 还是 role: "tool" 格式)合并到前一个 user 消息的 content 数组中,而非创建新的独立消息。
  • 新增对应的单元测试覆盖去重和合并逻辑。

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL: https://docs.anthropic.com/en/api/messages
  • Reasoning: Anthropic Messages API 要求每个 tool_use 对应唯一一个 tool_result,且同一轮对话中的多个 tool result 必须放在同一个 user 消息的 content 数组内。违反这两个约束时 API 会返回 400 错误。

🧪 Test Environment

  • Hardware: Mac (Apple Silicon)
  • OS: macOS
  • Model/Provider: Anthropic Claude
  • Channels: N/A(单元测试验证)

📸 Evidence (Optional)

Click to view Logs/Screenshots

修复前错误日志:

400 Bad Request: each tool_use must have a single result. Found multiple tool_result blocks with id

修复后单元测试通过:

go test ./pkg/agent/ -run TestSanitizeHistoryForProvider_DuplicateToolResults -v
go test ./pkg/providers/anthropic_messages/ -run TestBuildRequestBody_ConsecutiveToolResultsMerged -v
go test ./pkg/providers/anthropic_messages/ -run TestBuildRequestBody_UserToolResultsMerged -v

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

…sult blocks for Anthropic API

Anthropic API returns 400 when multiple tool_result blocks share the same
tool_use_id, or when consecutive tool results are sent as separate user
messages. This fix:

1. Adds ToolCallID deduplication in sanitizeHistoryForProvider (context.go)
   to drop duplicate tool results before sending to any provider.
2. Merges consecutive tool result messages into a single user message with
   multiple tool_result content blocks in Anthropic's buildRequestBody,
   for both "user" (with ToolCallID) and "tool" role messages.
3. Adds tests for both behaviors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@liuliqiang liuliqiang changed the title fix(#1792): deduplicate tool results and merge consecutive tool_result blocks for Anthropic API fix #1792 : deduplicate tool results and merge consecutive tool_result blocks for Anthropic API Mar 19, 2026
@liuliqiang liuliqiang changed the title fix #1792 : deduplicate tool results and merge consecutive tool_result blocks for Anthropic API fixes #1792 : deduplicate tool results and merge consecutive tool_result blocks for Anthropic API Mar 19, 2026
@liuliqiang liuliqiang changed the title fixes #1792 : deduplicate tool results and merge consecutive tool_result blocks for Anthropic API fix: deduplicate tool results and merge consecutive tool_result blocks for Anthropic API Mar 19, 2026
@sipeed-bot sipeed-bot Bot added type: bug Something isn't working domain: provider domain: agent go Pull requests that update go code labels Mar 19, 2026
Copy link
Copy Markdown
Collaborator

@afjcjsbx afjcjsbx left a comment

Choose a reason for hiding this comment

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

LGTM!

@alexhoshina alexhoshina merged commit f81b44b into sipeed:main Mar 23, 2026
4 checks passed
andressg79 pushed a commit to andressg79/picoclaw that referenced this pull request Mar 30, 2026
…sult blocks for Anthropic API (sipeed#1793)

Anthropic API returns 400 when multiple tool_result blocks share the same
tool_use_id, or when consecutive tool results are sent as separate user
messages. This fix:

1. Adds ToolCallID deduplication in sanitizeHistoryForProvider (context.go)
   to drop duplicate tool results before sending to any provider.
2. Merges consecutive tool result messages into a single user message with
   multiple tool_result content blocks in Anthropic's buildRequestBody,
   for both "user" (with ToolCallID) and "tool" role messages.
3. Adds tests for both behaviors.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ra1phdd pushed a commit to ra1phdd/picoclaw-pkg that referenced this pull request Apr 12, 2026
…sult blocks for Anthropic API (sipeed#1793)

Anthropic API returns 400 when multiple tool_result blocks share the same
tool_use_id, or when consecutive tool results are sent as separate user
messages. This fix:

1. Adds ToolCallID deduplication in sanitizeHistoryForProvider (context.go)
   to drop duplicate tool results before sending to any provider.
2. Merges consecutive tool result messages into a single user message with
   multiple tool_result content blocks in Anthropic's buildRequestBody,
   for both "user" (with ToolCallID) and "tool" role messages.
3. Adds tests for both behaviors.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
armmer016 pushed a commit to cryptoquantumwave/khunquant that referenced this pull request Apr 14, 2026
…sult blocks for Anthropic API (sipeed#1793)

Anthropic API returns 400 when multiple tool_result blocks share the same
tool_use_id, or when consecutive tool results are sent as separate user
messages. This fix:

1. Adds ToolCallID deduplication in sanitizeHistoryForProvider (context.go)
   to drop duplicate tool results before sending to any provider.
2. Merges consecutive tool result messages into a single user message with
   multiple tool_result content blocks in Anthropic's buildRequestBody,
   for both "user" (with ToolCallID) and "tool" role messages.
3. Adds tests for both behaviors.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: agent domain: provider go Pull requests that update go code type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Anthropic API 返回 400:重复 tool_result 及连续 tool result 未合并

3 participants