Skip to content

[Bug]: Anthropic endpoint converts a client tool_use named web_search/web_fetch into a server tool call, orphaning its tool_result (Bedrock 400) #8078

Description

@jacob-pattern

Prerequisites

  • I have searched existing issues and discussions to avoid duplicates
  • I am using the latest version (or have tested against main/nightly)

Description

On the Anthropic-compatible endpoint (/anthropic/v1/messages), a client tool named web_search or web_fetch (a regular tool_use block for a function tool the caller defined) is converted to a web_search_call / web_fetch_call instead of a function_call.

anthropicToolUseBlockToResponsesMessage (core/providers/anthropic/responses.go) decides by name alone. It is used by the grouped converter for both tool_use and server_tool_use blocks, so it cannot tell our function tool apart from Anthropic's server tool. The ungrouped converter already switches on block type and does not have this problem.

The matching tool_result stays a function_call_output. On Bedrock the web_search_call is rewritten as a nova_grounding server tool with its own synthetic result, so the real tool_result has no toolUse left in the previous assistant turn and Bedrock rejects the request.

Because the bad item is in the replayed history, every later turn in that conversation fails too, including turns that don't search.

Steps to reproduce

  1. Route a Claude model to Bedrock (e.g. bedrock/global.anthropic.claude-sonnet-4-6).
  2. Send /anthropic/v1/messages with a function tool named web_search (e.g. {"name":"web_search","input_schema":{"type":"object","properties":{"query":{"type":"string"}}}}).
  3. Replay a turn where the assistant called it and the user returned the result:
    • assistant: {"type":"tool_use","id":"toolu_1","name":"web_search","input":{"query":"x"}}
    • user: {"type":"tool_result","tool_use_id":"toolu_1","content":"..."}
  4. Observe the 400 below. The same payload sent directly to Bedrock (Converse or InvokeModel) succeeds; tools with any other name take the normal function_call path.

Expected behavior

A tool_use block for a client tool named web_search / web_fetch is converted to a function_call with its name and arguments, like any other function tool.

Actual behavior

It becomes a web_search_call / web_fetch_call, the tool_result is orphaned, and Bedrock returns 400 ValidationException.

Affected area(s)

Core (Go)

Version

transports/v2.1.0 and transports/v2.2.2. Still present on dev (955ffa3).

Relevant logs/output

{"type":"ValidationException","is_bifrost_error":false,"status_code":400,"error":{"type":"ValidationException","message":"The number of toolResult blocks at messages.10.content exceeds the number of toolUse blocks of previous turn."},"extra_fields":{"provider":"bedrock","request_type":"responses_stream"}}

Severity

High (major functionality broken)


Fix with regression tests: #8079. It only maps these names when the block type is server_tool_use.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions