litellm - ✅(Solved) Fix Remove overly strict tool_calls validation for Anthropic/Bedrock providers [2 pull requests, 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#24712Fetched 2026-04-08 01:42:03
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2referenced ×2labeled ×1

Fix Action

Workaround

Set litellm.modify_params = True (or litellm_settings::modify_params: True) — this injects a dummy tool instead of raising, but it's wasteful and shouldn't be needed.

PR fix notes

PR #24713: fix: remove overly strict tool_calls validation for Anthropic/Bedrock

Description (problem / solution / changelog)

Summary

  • Remove validation blocks that raise UnsupportedParamsError when messages contain tool_calls in history but no tools= param is passed
  • Affects both Anthropic (transformation.py) and Bedrock (converse_transformation.py)
  • The Anthropic API handles this natively — the validation is unnecessary

Problem

When conversation history includes tool use (e.g. from an agentic session) but the current follow-up call doesn't need tools, LiteLLM blocks the request. This breaks structured output follow-up calls after agentic tool-calling sessions.

Fix

Remove both validation blocks entirely. No stripping, no dummy tools — just let the messages pass through to the provider.

Verified working against Anthropic direct API and Bedrock — all models respond correctly with the blocks removed.

Fixes #24712

Changed files

  • .circleci/config.yml (modified, +1/-0)
  • CLAUDE.md (modified, +1/-1)
  • ci_cd/security_scans.sh (modified, +1/-1)
  • litellm/cost_calculator.py (modified, +8/-1)
  • litellm/llms/anthropic/chat/transformation.py (modified, +0/-16)
  • litellm/llms/bedrock/chat/converse_transformation.py (modified, +0/-18)
  • litellm/proxy/_experimental/out/404/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/_not-found/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/api-reference/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/api-playground/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/budgets/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/caching/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/claude-code-plugins/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/old-usage/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/prompts/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/experimental/tag-management/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/guardrails/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/login/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/logs/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/mcp/oauth/callback/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/model-hub/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/model_hub/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/model_hub_table/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/models-and-endpoints/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/onboarding/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/organizations/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/playground/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/policies/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/settings/admin-settings/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/settings/logging-and-alerts/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/settings/router-settings/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/settings/ui-theme/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/teams/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/test-key/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/tools/mcp-servers/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/tools/vector-stores/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/usage/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/users/index.html (renamed, +0/-0)
  • litellm/proxy/_experimental/out/virtual-keys/index.html (renamed, +0/-0)
  • litellm/proxy/example_config_yaml/custom_auth_basic.py (modified, +2/-1)
  • litellm/proxy/proxy_cli.py (modified, +7/-0)
  • pyproject.toml (modified, +2/-2)
  • tests/local_testing/test_router_utils.py (modified, +2/-1)
  • tests/mcp_tests/test_mcp_server.py (modified, +3/-0)
  • tests/test_litellm/proxy/test_prometheus_cleanup.py (modified, +24/-0)
  • tests/test_litellm/proxy/test_proxy_cli.py (modified, +2/-2)
  • tests/test_litellm/test_cost_calculator.py (modified, +59/-0)

PR #24714: fix: remove overly strict tool_calls validation for Anthropic/Bedrock

Description (problem / solution / changelog)

Summary

  • Remove validation blocks that raise UnsupportedParamsError when messages contain tool_calls in history but no tools= param is passed
  • Affects both Anthropic (transformation.py) and Bedrock (converse_transformation.py)
  • The Anthropic API handles this natively — the validation is unnecessary

Problem

When conversation history includes tool use (e.g. from an agentic session) but the current follow-up call doesn't need tools, LiteLLM blocks the request. This breaks structured output follow-up calls after agentic tool-calling sessions.

Fix

Remove both validation blocks entirely. No stripping, no dummy tools — just let the messages pass through to the provider.

Verified working against Anthropic direct API and Bedrock — all models respond correctly with the blocks removed.

Fixes #24712

Changed files

  • litellm/llms/anthropic/chat/transformation.py (modified, +0/-19)
  • litellm/llms/bedrock/chat/converse_transformation.py (modified, +9/-4)

Code Example

from litellm import completion

# First: an agentic call with tools (produces tool_calls in history)
# Then: a follow-up call reusing that conversation history, but without tools=
response = completion(
    model="anthropic/claude-sonnet-4-6",
    messages=[
        {"role": "user", "content": "What's the weather?"},
        {"role": "assistant", "content": None, "tool_calls": [
            {"id": "call_1", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"NYC\"}"}}
        ]},
        {"role": "tool", "tool_call_id": "call_1", "content": "72°F sunny"},
        {"role": "assistant", "content": "It's 72°F and sunny in NYC."},
        {"role": "user", "content": "Summarize our conversation."}
    ]
    # No tools= param — this is intentional, we don't need tools for this call
)
RAW_BUFFERClick to expand / collapse

Bug Description

When messages contain tool_calls in conversation history but the current request doesn't include a tools= parameter, LiteLLM raises UnsupportedParamsError for Anthropic and Bedrock providers. This is overly strict — the Anthropic API handles this fine natively.

This breaks structured output follow-up calls after agentic tool-calling sessions, where the conversation history includes tool use but the current turn doesn't need tools.

Steps to Reproduce

from litellm import completion

# First: an agentic call with tools (produces tool_calls in history)
# Then: a follow-up call reusing that conversation history, but without tools=
response = completion(
    model="anthropic/claude-sonnet-4-6",
    messages=[
        {"role": "user", "content": "What's the weather?"},
        {"role": "assistant", "content": None, "tool_calls": [
            {"id": "call_1", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"NYC\"}"}}
        ]},
        {"role": "tool", "tool_call_id": "call_1", "content": "72°F sunny"},
        {"role": "assistant", "content": "It's 72°F and sunny in NYC."},
        {"role": "user", "content": "Summarize our conversation."}
    ]
    # No tools= param — this is intentional, we don't need tools for this call
)

Expected: Request passes through to the provider, which handles it fine.

Actual: UnsupportedParamsError: Anthropic doesn't support tool calling without tools= param specified.

Affected Code

  1. litellm/llms/anthropic/chat/transformation.py ~line 1331 — if "tools" not in optional_params and has_tool_call_blocks(messages)
  2. litellm/llms/bedrock/chat/converse_transformation.py ~line 1399 — identical block

Suggested Fix

Remove both validation blocks entirely. The Anthropic API accepts messages with tool_calls in history without requiring a tools= parameter. The modify_params / add_dummy_tool workaround is unnecessary.

Verified working against Anthropic direct API and Bedrock with the blocks removed — all models respond correctly.

Workaround

Set litellm.modify_params = True (or litellm_settings::modify_params: True) — this injects a dummy tool instead of raising, but it's wasteful and shouldn't be needed.

extent analysis

Fix Plan

To resolve the issue, we need to remove the validation blocks that check for the presence of the tools parameter when tool_calls are present in the conversation history.

Here are the steps:

  • Remove the validation block in litellm/llms/anthropic/chat/transformation.py at line 1331.
  • Remove the validation block in litellm/llms/bedrock/chat/converse_transformation.py at line 1399.

Example of removed code:

# Remove this block
if "tools" not in optional_params and has_tool_call_blocks(messages):
    raise UnsupportedParamsError("Anthropic doesn't support tool calling without tools= param specified.")

Replace the above code with nothing, effectively removing the check.

Verification

To verify that the fix worked, run the following test:

from litellm import completion

response = completion(
    model="anthropic/claude-sonnet-4-6",
    messages=[
        {"role": "user", "content": "What's the weather?"},
        {"role": "assistant", "content": None, "tool_calls": [
            {"id": "call_1", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\": \"NYC\"}"}}
        ]},
        {"role": "tool", "tool_call_id": "call_1", "content": "72°F sunny"},
        {"role": "assistant", "content": "It's 72°F and sunny in NYC."},
        {"role": "user", "content": "Summarize our conversation."}
    ]
)

print(response)

This should now pass through to the provider without raising an UnsupportedParamsError.

Extra Tips

  • Make sure to test this fix against both the Anthropic and Bedrock APIs to ensure it works as expected.
  • Consider adding tests to prevent similar issues in the future.

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