feat(anthropic): support advisor_20260301 tool type#25525
feat(anthropic): support advisor_20260301 tool type#25525ishaan-berri merged 13 commits intolitellm_ishaan_april10from
Conversation
…03_01 beta header enum
…ader in /messages path
Add advisor-tool-2026-03-01 to anthropic_beta_headers_config.json so the beta headers manager forwards it to Anthropic (was being silently dropped). Mark as null for all non-native providers.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Greptile SummaryThis PR adds support for Anthropic's Confidence Score: 5/5Safe to merge — the single remaining finding is a P2 edge case that requires a caller to explicitly pass unsupported fields on an advisor tool. All changes are isolated to the Anthropic provider directory, 10 new unit tests cover the main code paths without network calls, both transformation paths are handled consistently, and no security or data-integrity issues were found. The only open concern (advisor tool not excluded from cache_control/defer_loading/allowed_callers processing) only triggers if a caller deliberately passes unsupported fields on an advisor tool and does not affect the primary use case. litellm/llms/anthropic/chat/transformation.py — the three post-build processing blocks (cache_control, defer_loading, allowed_callers) should exclude ANTHROPIC_ADVISOR_TOOL_TYPE.
|
| Filename | Overview |
|---|---|
| litellm/llms/anthropic/chat/transformation.py | Core transformation path: adds advisor tool handling in _map_tool_helper, auto-beta-header injection, and auto-strip of advisor blocks; advisor tool type is not excluded from cache_control/defer_loading/allowed_callers processing blocks, which can silently forward unsupported fields. |
| litellm/llms/anthropic/common_utils.py | Adds strip_advisor_blocks_from_messages() helper — logic is correct, strips server_tool_use(name=advisor) and associated advisor_tool_result blocks from assistant message content. |
| litellm/llms/anthropic/experimental_pass_through/messages/transformation.py | Messages pass-through path: mirrors the chat path with advisor beta-header injection and auto-strip; implementation is consistent with the chat path. |
| litellm/types/llms/anthropic.py | Adds AnthropicAdvisorTool TypedDict, ANTHROPIC_ADVISOR_TOOL_TYPE constant, ADVISOR_TOOL_2026_03_01 enum value, and includes AnthropicAdvisorTool in AllAnthropicToolsValues union — all correct. |
| tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py | 10 new unit tests covering tool mapping, beta-header injection, response parsing, and message stripping — all are pure mock/unit tests with no network calls. |
| litellm/anthropic_beta_headers_config.json | Registers advisor-tool-2026-03-01 in the beta headers config so it is forwarded by the headers manager — correct addition. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Incoming request with tools] --> B{advisor_20260301\nin tools?}
B -- Yes --> C[Auto-inject\nadvisor-tool-2026-03-01\nbeta header]
B -- No --> D[strip_advisor_blocks_from_messages\nscan assistant history]
D --> E{Advisor blocks\nfound in history?}
E -- Yes --> F[Remove server_tool_use name=advisor\n+ matching advisor_tool_result blocks]
E -- No --> G[No-op]
C --> H[_map_tool_helper:\nAnthropicAdvisorTool TypedDict\nwith type/name/model/max_uses/caching]
H --> I[Forward to Anthropic API]
F --> I
G --> I
Reviews (4): Last reviewed commit: "refactor(advisor): replace hardcoded "ad..." | Re-trigger Greptile
| break | ||
|
|
||
| # Check for tool search tools | ||
| tools = optional_params.get("tools") |
There was a problem hiding this comment.
tools is fetched from optional_params again here (line 338) even though it was already assigned at line 328 and its value hasn't changed. The existing reference can be reused directly.
| tools = optional_params.get("tools") | |
| # Check for tool search tools | |
| if tools: |
| name=tool_name, | ||
| ) | ||
| elif tool["type"] == "advisor_20260301": | ||
| from litellm.types.llms.anthropic import AnthropicAdvisorTool |
There was a problem hiding this comment.
AnthropicAdvisorTool is imported inside the method body rather than at the module top-level. CLAUDE.md asks to avoid inline imports unless they are strictly needed to break a circular dependency. AnthropicAdvisorTool lives in the same litellm.types.llms.anthropic module that is already imported at the top of this file (line 21), so it can be added there instead — the same way AnthropicMessagesTool, AnthropicComputerTool, etc. are imported. The same pattern exists at lines 489 and 501 for the tool-search types; all three could be moved up together.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| advisor_model = _tool_dict.get("model") | ||
| if not isinstance(advisor_model, str): | ||
| raise ValueError("Advisor tool must have a valid model") |
There was a problem hiding this comment.
Empty-string model passes validation
isinstance("", str) is True, so passing "model": "" will bypass the guard and produce an AnthropicAdvisorTool with an empty model field. Anthropic will reject the request, but the error message will be cryptic. A simple additional check makes the failure fast and clear:
| advisor_model = _tool_dict.get("model") | |
| if not isinstance(advisor_model, str): | |
| raise ValueError("Advisor tool must have a valid model") | |
| advisor_model = _tool_dict.get("model") | |
| if not isinstance(advisor_model, str) or not advisor_model.strip(): | |
| raise ValueError("Advisor tool must have a valid model") |
…l absent Prevents Anthropic 400 invalid_request_error on follow-up turns where the caller has removed the advisor tool but message history still contains server_tool_use(advisor) + advisor_tool_result blocks.
|
|
||
| from ..common_utils import AnthropicError, AnthropicModelInfo, process_anthropic_headers | ||
| from ..common_utils import ( | ||
| AnthropicError, |
| from ..common_utils import AnthropicError, AnthropicModelInfo, process_anthropic_headers | ||
| from ..common_utils import ( | ||
| AnthropicError, | ||
| AnthropicModelInfo, |
| from ..common_utils import ( | ||
| AnthropicError, | ||
| AnthropicModelInfo, | ||
| process_anthropic_headers, |
| AnthropicError, | ||
| AnthropicModelInfo, | ||
| process_anthropic_headers, | ||
| strip_advisor_blocks_from_messages, |
…C_ADVISOR_TOOL_TYPE constant
| from litellm.llms.base_llm.base_utils import type_to_response_format_param | ||
| from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException | ||
| from litellm.types.llms.anthropic import ( | ||
| ANTHROPIC_ADVISOR_TOOL_TYPE, |
Relevant issues
Fixes #25516
Pre-Submission checklist
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unitCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🆕 New Feature / 🐛 Bug Fix
Changes
Adds support for Anthropic's
advisor_20260301tool. Previously LiteLLM raised aValueErroron unknown tool types and stripped the beta header. This also adds auto-strip of staleadvisor_tool_resultblocks to prevent 400s on follow-up turns.Files changed:
litellm/types/llms/anthropic.py—AnthropicAdvisorToolTypedDict +ADVISOR_TOOL_2026_03_01enum valuelitellm/llms/anthropic/chat/transformation.py— handleadvisor_20260301in_map_tool_helper(); auto-inject beta header; auto-strip advisor blocks when tool is absentlitellm/llms/anthropic/experimental_pass_through/messages/transformation.py— same auto-inject + auto-strip for/v1/messagespathlitellm/llms/anthropic/common_utils.py—strip_advisor_blocks_from_messages()helperlitellm/anthropic_beta_headers_config.json— registeradvisor-tool-2026-03-01so the beta headers manager forwards it (was silently dropped)docs/my-website/docs/providers/anthropic_advisor_tool.md— new doc pageAuto-strip behavior: When the advisor tool is not in
tools, LiteLLM stripsserver_tool_use(name=advisor)andadvisor_tool_resultblocks from message history before forwarding. This prevents the Anthropic 400 that happens when a caller removes the advisor tool for cost control but forgets to clean history.Live test results (both paths, both modes):
/v1/messagesnon-streaming:/v1/messagesstreaming:10 unit tests in
tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py.