Skip to content

fix(llm): round-trip Anthropic tool_search_tool_result blocks - #48466

Open
lu-zero wants to merge 1 commit into
anomalyco:devfrom
lu-zero:luca/anthropic-tool-search-block-roundtrip
Open

fix(llm): round-trip Anthropic tool_search_tool_result blocks#48466
lu-zero wants to merge 1 commit into
anomalyco:devfrom
lu-zero:luca/anthropic-tool-search-block-roundtrip

Conversation

@lu-zero

@lu-zero lu-zero commented Sep 11, 2026

Copy link
Copy Markdown

Issue for this PR

Fixes #45527.

Scope note: this lands the protocol half — the wire round-trip for Anthropic tool-search blocks. It does not add the config seam (defer_loading passthrough, declaring a provider-defined tool) that #45527 also asks for; happy to keep that issue open if maintainers prefer.

Type of change

  • Bug fix

What does this PR do?

The native Anthropic protocol dropped tool_search_tool_result content blocks at stream-decode time and refused to lower them back onto the wire. Both gaps keyed off the same hardcoded three-entry server-tool list, which predates Anthropic's tool-search server tools.

A tool search puts signed thinking, server_tool_use, tool_search_tool_result and tool_use in one assistant turn. Dropping the result block means the replayed turn no longer matches the original response, and Anthropic rejects the signed thinking block:

`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified.

One unknown block type turns into a hard 400 for the rest of the conversation.

File Change
llm/src/protocols/anthropic-messages.ts Decode and re-emit tool_search_tool_result; record server_tool_use id → name in parser state, because tool_search_tool_bm25 and tool_search_tool_regex both report through one result block type that carries no name of its own.
llm/test/provider/anthropic-messages.test.ts Round-trip coverage for the tool-search block shapes.

How did you verify your code works?

Check Result
bun test test/provider/anthropic-messages.test.ts 28 pass, 0 fail
bun turbo typecheck 30/30 tasks pass

Screenshots / recordings

N/A — provider wire-format change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

🤖 Generated with Claude Code

The native Anthropic protocol dropped `tool_search_tool_result` content
blocks at stream-decode time and refused to lower them back onto the
wire. Both gaps keyed off the same hardcoded three-entry server-tool
list, which predates Anthropic's tool-search server tools.

A tool search puts signed `thinking`, `server_tool_use`,
`tool_search_tool_result` and `tool_use` in a single assistant turn.
Dropping the result block means the replayed turn no longer matches the
original response, and Anthropic rejects the signed thinking block:
"`thinking` or `redacted_thinking` blocks in the latest assistant
message cannot be modified."

Also records `server_tool_use` id -> name in the parser state, because
`tool_search_tool_bm25` and `tool_search_tool_regex` both report through
one `tool_search_tool_result` block type and the result block carries no
name of its own.
@lu-zero

lu-zero commented Sep 11, 2026

Copy link
Copy Markdown
Author

Ported to beta as #48485 — same gap at packages/ai/src/protocols/anthropic-messages.ts there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

defer_loading / tool-search support is absent, though #23298 was closed as completed

1 participant