Skip to content

[Bug]: Multi-turn conversations with Anthropic web search + custom tools broken - server_tool_use incorrectly converted to tool_use #17737

@KeremTurgutlu

Description

@KeremTurgutlu

What happened?

When using Anthropic's web search tool together with custom tools, multi-turn conversations fail because:

  1. server_tool_use blocks are converted to regular tool_use blocks when transforming the response
  2. web_search_tool_result blocks are dropped entirely from the message content
  3. When the conversation continues, Claude expects a tool_result for the server_tool_use (which is server-side and shouldn't need one)

Error Message

messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: srvtoolu_XXX. Each `tool_use` block must have a corresponding `tool_result` block in the next message.

Relevant log output

Raw response from Claude API (correct format):

"content":[
  {"type":"server_tool_use","id":"srvtoolu_XXX","name":"web_search","input":{...}},
  {"type":"web_search_tool_result","tool_use_id":"srvtoolu_XXX","content":[...]},
  {"type":"tool_use","id":"toolu_XXX","name":"add_numbers","input":{...}}
]

What litellm sends back to Claude (incorrect - causes error):

"messages": [
  {"role": "assistant", "content": [
    {"type": "tool_use", "id": "srvtoolu_XXX", "name": "web_search", "input": {...}},
    {"type": "tool_use", "id": "toolu_XXX", "name": "add_numbers", "input": {...}}
  ]},
  {"role": "user", "content": [
    {"type": "tool_result", "tool_use_id": "toolu_XXX", "content": "9600"}
  ]}
]

Problems:

  • server_tool_use became tool_use
  • web_search_tool_result is missing entirely
  • No tool_result for srvtoolu_XXX (which shouldn't need one - it's server-side)

Minimal Reproduction

import litellm

def add_numbers(a: int, b: int) -> int:
    return a + b

tool_def = {
    'type': 'function',
    'function': {
        'name': 'add_numbers',
        'description': 'Add two numbers',
        'parameters': {
            'type': 'object',
            'properties': {
                'a': {'type': 'integer'},
                'b': {'type': 'integer'}
            },
            'required': ['a', 'b']
        }
    }
}

msgs = [{"role": "user", "content": "Search the web for the avg weight in kg of male African and Asian elephants. Then add them."}]

# First call - works
r = litellm.completion(
    model="anthropic/claude-sonnet-4-5",
    messages=msgs,
    tools=[tool_def],
    web_search_options={"search_context_size": "low"}
)

# Add assistant response and tool result
msgs.append(r.choices[0].message.to_dict())

# Find the custom tool call (not the server tool)
for tc in r.choices[0].message.tool_calls:
    if tc.id.startswith('toolu_'):  # Only respond to custom tools
        msgs.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": str(add_numbers(5000, 4000))
        })

# Second call - FAILS
r2 = litellm.completion(
    model="anthropic/claude-sonnet-4-5",
    messages=msgs,
    tools=[tool_def],
    web_search_options={"search_context_size": "low"}
)

Expected Behavior

Multi-turn conversations with web search + custom tools should work. The transformation should:

  1. Preserve server_tool_use as-is (not convert to tool_use)
  2. Preserve web_search_tool_result blocks in the message content
  3. Not require tool_result for server-side tools

Environment

  • litellm version: 1.80.9 (also affects 1.80.6-1.80.8)
  • Python version: 3.12
  • OS: macOS

Related Issues

Additional Context

The raw Claude API correctly returns server_tool_use (with srvtoolu_ prefix) and includes web_search_tool_result immediately after. These are server-side tool executions that don't require user-provided results. The issue is in litellm's response transformation and message reconstruction for multi-turn conversations.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions