litellm - 💡(How to fix) Fix [Bug] Anthropic chat transformer KeyError on Anthropic-native managed tools (web_search_20250305 et al.) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#27158Fetched 2026-05-06 06:15:53
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
labeled ×1

AnthropicConfig._transform_request in litellm/llms/anthropic/chat/transformation.py raises KeyError: 'function' when callers pass Anthropic-native managed tools such as web_search_20250305, text_editor_*, bash_*, or computer_*. The code path assumes any tool that doesn't already have an input_schema key is an OpenAI-shaped tool that needs unwrapping via tool["function"] — but Anthropic-native managed tools have neither key.

Error Message

File "/usr/local/lib/python3.11/site-packages/litellm/llms/anthropic/chat/transformation.py", line 282, in _transform_request
    new_tool = tool["function"]
               ~~~~^^^^^^^^^^^^
KeyError: 'function'

Root Cause

The else branch in the tool-loop assumes OpenAI shape:

for tool in optional_params["tools"]:
    if "input_schema" in tool:  # assume in anthropic format
        anthropic_tools.append(tool)
    else:  # assume openai tool call
        new_tool = tool["function"]   # <-- KeyError on web_search_20250305
        ...

Anthropic's managed tools are passed through to the API verbatim; they only have {"type": "<provider-version>", "name": "...", ...} — no function, no input_schema.

Fix Action

Fix / Workaround

We've been running this patched transformer in production behind LiteLLM v1.51.0-stable for the last hour. Both tool shapes work end-to-end:

Code Example

import litellm

litellm.completion(
    model="anthropic/claude-sonnet-4-5",
    messages=[{"role": "user", "content": "What's today's news? Use web search."}],
    tools=[{
        "type": "web_search_20250305",
        "name": "web_search",
        "max_uses": 3,
    }],
    max_tokens=200,
)

---

File "/usr/local/lib/python3.11/site-packages/litellm/llms/anthropic/chat/transformation.py", line 282, in _transform_request
    new_tool = tool["function"]
               ~~~~^^^^^^^^^^^^
KeyError: 'function'

---

for tool in optional_params["tools"]:
    if "input_schema" in tool:  # assume in anthropic format
        anthropic_tools.append(tool)
    else:  # assume openai tool call
        new_tool = tool["function"]   # <-- KeyError on web_search_20250305
        ...

---

--- a/litellm/llms/anthropic/chat/transformation.py
+++ b/litellm/llms/anthropic/chat/transformation.py
@@ -272,12 +272,25 @@
                 optional_params[k] = v
 
         ## Handle Tool Calling
+        ANTHROPIC_NATIVE_TOOL_PREFIXES = (
+            "web_search_",
+            "text_editor_",
+            "bash_",
+            "computer_",
+        )
         if "tools" in optional_params:
             _is_function_call = True
             anthropic_tools = []
             for tool in optional_params["tools"]:
                 if "input_schema" in tool:  # assume in anthropic format
                     anthropic_tools.append(tool)
+                elif any(
+                    str(tool.get("type", "")).startswith(p)
+                    for p in ANTHROPIC_NATIVE_TOOL_PREFIXES
+                ):
+                    # Anthropic-native managed tool (web_search_20250305,
+                    # text_editor_*, bash_*, computer_*); pass through verbatim.
+                    anthropic_tools.append(tool)
                 else:  # assume openai tool call
                     new_tool = tool["function"]
                     parameters = new_tool.pop(
RAW_BUFFERClick to expand / collapse

Summary

AnthropicConfig._transform_request in litellm/llms/anthropic/chat/transformation.py raises KeyError: 'function' when callers pass Anthropic-native managed tools such as web_search_20250305, text_editor_*, bash_*, or computer_*. The code path assumes any tool that doesn't already have an input_schema key is an OpenAI-shaped tool that needs unwrapping via tool["function"] — but Anthropic-native managed tools have neither key.

Affected versions

Reproduces on v1.51.0-stable (the main-v1.51.0-stable Docker image). The same code path appears unchanged on later 1.51.x tags.

Affected routes

Both the Anthropic-direct provider (anthropic/...) and the Vertex AI Anthropic provider (vertex_ai/claude-...) hit this — the transformer module is shared.

Repro

import litellm

litellm.completion(
    model="anthropic/claude-sonnet-4-5",
    messages=[{"role": "user", "content": "What's today's news? Use web search."}],
    tools=[{
        "type": "web_search_20250305",
        "name": "web_search",
        "max_uses": 3,
    }],
    max_tokens=200,
)

Stack trace

File "/usr/local/lib/python3.11/site-packages/litellm/llms/anthropic/chat/transformation.py", line 282, in _transform_request
    new_tool = tool["function"]
               ~~~~^^^^^^^^^^^^
KeyError: 'function'

Root cause

The else branch in the tool-loop assumes OpenAI shape:

for tool in optional_params["tools"]:
    if "input_schema" in tool:  # assume in anthropic format
        anthropic_tools.append(tool)
    else:  # assume openai tool call
        new_tool = tool["function"]   # <-- KeyError on web_search_20250305
        ...

Anthropic's managed tools are passed through to the API verbatim; they only have {"type": "<provider-version>", "name": "...", ...} — no function, no input_schema.

Proposed fix

Add an elif that recognizes the Anthropic-native tool prefixes and passes them through untouched. Diff against the v1.51.0-stable file:

--- a/litellm/llms/anthropic/chat/transformation.py
+++ b/litellm/llms/anthropic/chat/transformation.py
@@ -272,12 +272,25 @@
                 optional_params[k] = v
 
         ## Handle Tool Calling
+        ANTHROPIC_NATIVE_TOOL_PREFIXES = (
+            "web_search_",
+            "text_editor_",
+            "bash_",
+            "computer_",
+        )
         if "tools" in optional_params:
             _is_function_call = True
             anthropic_tools = []
             for tool in optional_params["tools"]:
                 if "input_schema" in tool:  # assume in anthropic format
                     anthropic_tools.append(tool)
+                elif any(
+                    str(tool.get("type", "")).startswith(p)
+                    for p in ANTHROPIC_NATIVE_TOOL_PREFIXES
+                ):
+                    # Anthropic-native managed tool (web_search_20250305,
+                    # text_editor_*, bash_*, computer_*); pass through verbatim.
+                    anthropic_tools.append(tool)
                 else:  # assume openai tool call
                     new_tool = tool["function"]
                     parameters = new_tool.pop(

The check is by type prefix rather than exact match so it survives provider version bumps (web_search_20251201, etc.) without code changes.

Verification

We've been running this patched transformer in production behind LiteLLM v1.51.0-stable for the last hour. Both tool shapes work end-to-end:

  • {"type": "web_search_20250305", "name": "web_search", "max_uses": 3} → 200, web search fires upstream (large prompt-token count confirms results were injected)
  • {"type": "function", "function": {"name": "...", "parameters": {...}}} → 200, model emits tool_calls correctly

The fix branch (against v1.51.0-stable) is at:

Happy to open a PR if maintainers prefer.

extent analysis

TL;DR

Add an elif branch to recognize Anthropic-native tool prefixes and pass them through untouched to fix the KeyError: 'function' issue.

Guidance

  • Identify the tool type by checking the type key in the tool dictionary, and add an elif condition to handle Anthropic-native tools.
  • Use a tuple of prefixes (ANTHROPIC_NATIVE_TOOL_PREFIXES) to match the tool types, allowing for future version updates without code changes.
  • Verify the fix by testing both Anthropic-native and OpenAI-shaped tools, ensuring they work end-to-end without errors.
  • Consider opening a PR with the proposed fix for maintainers to review and merge.

Example

ANTHROPIC_NATIVE_TOOL_PREFIXES = (
    "web_search_",
    "text_editor_",
    "bash_",
    "computer_",
)
...
elif any(
    str(tool.get("type", "")).startswith(p)
    for p in ANTHROPIC_NATIVE_TOOL_PREFIXES
):
    # Anthropic-native managed tool; pass through verbatim.
    anthropic_tools.append(tool)

Notes

The proposed fix assumes that the type key in the tool dictionary is sufficient to identify Anthropic-native tools. If this assumption is incorrect, additional checks may be necessary.

Recommendation

Apply the proposed workaround by adding the elif branch to recognize Anthropic-native tool prefixes, as it provides a clear and effective solution to the KeyError: 'function' issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING