Skip to content

feat(anthropic): support advisor_20260301 tool type#25525

Merged
ishaan-berri merged 13 commits intolitellm_ishaan_april10from
feat/anthropic-advisor-tool
Apr 10, 2026
Merged

feat(anthropic): support advisor_20260301 tool type#25525
ishaan-berri merged 13 commits intolitellm_ishaan_april10from
feat/anthropic-advisor-tool

Conversation

@ishaan-berri
Copy link
Copy Markdown
Contributor

@ishaan-berri ishaan-berri commented Apr 10, 2026

Relevant issues

Fixes #25516

Pre-Submission checklist

  • I have Added testing in the tests/test_litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

CI (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_20260301 tool. Previously LiteLLM raised a ValueError on unknown tool types and stripped the beta header. This also adds auto-strip of stale advisor_tool_result blocks to prevent 400s on follow-up turns.

Files changed:

  • litellm/types/llms/anthropic.pyAnthropicAdvisorTool TypedDict + ADVISOR_TOOL_2026_03_01 enum value
  • litellm/llms/anthropic/chat/transformation.py — handle advisor_20260301 in _map_tool_helper(); auto-inject beta header; auto-strip advisor blocks when tool is absent
  • litellm/llms/anthropic/experimental_pass_through/messages/transformation.py — same auto-inject + auto-strip for /v1/messages path
  • litellm/llms/anthropic/common_utils.pystrip_advisor_blocks_from_messages() helper
  • litellm/anthropic_beta_headers_config.json — register advisor-tool-2026-03-01 so the beta headers manager forwards it (was silently dropped)
  • docs/my-website/docs/providers/anthropic_advisor_tool.md — new doc page

Auto-strip behavior: When the advisor tool is not in tools, LiteLLM strips server_tool_use(name=advisor) and advisor_tool_result blocks 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/messages non-streaming:

[server_tool_use] name=advisor, id=srvtoolu_016tba5RDoFRrti7ycatWiLV
[advisor_tool_result] tool_use_id=srvtoolu_016tba5RDoFRrti7ycatWiLV
[text] Here is an efficient Python primality check...
usage: 2223 in / 635 out

/v1/messages streaming:

[server_tool_use] name=advisor, id=srvtoolu_01HS2LKg3iGsCL3kRtZLoYbV
[advisor_tool_result] tool_use_id=srvtoolu_01HS2LKg3iGsCL3kRtZLoYbV
[text] Here is an efficient Python function to check if a number is prime...

10 unit tests in tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Apr 10, 2026 11:01pm

Request Review

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Apr 10, 2026

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing feat/anthropic-advisor-tool (9897c6d) with main (d67b5f8)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

❌ Patch coverage is 95.38462% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/llms/anthropic/chat/transformation.py 92.59% 2 Missing ⚠️
litellm/llms/anthropic/common_utils.py 94.73% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 10, 2026

Greptile Summary

This PR adds support for Anthropic's advisor_20260301 tool type across both the Chat Completions and /v1/messages paths, including automatic injection of the advisor-tool-2026-03-01 beta header and a new strip_advisor_blocks_from_messages() helper that scrubs stale advisor blocks from message history when the advisor tool is absent (preventing Anthropic 400s on follow-up turns). The implementation is thorough — TypedDict, enum value, JSON config, and two transformation paths are all updated together — and 10 unit tests cover the main scenarios.

Confidence Score: 5/5

Safe 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.

Important Files Changed

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
Loading

Reviews (4): Last reviewed commit: "refactor(advisor): replace hardcoded "ad..." | Re-trigger Greptile

break

# Check for tool search tools
tools = optional_params.get("tools")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant tools fetch

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.

Suggested change
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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Inline import inside method

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!

Comment on lines +515 to +517
advisor_model = _tool_dict.get("model")
if not isinstance(advisor_model, str):
raise ValueError("Advisor tool must have a valid model")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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:

Suggested change
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")


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,
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,
@ishaan-berri ishaan-berri changed the base branch from main to litellm_ishaan_april10 April 10, 2026 23:39
@ishaan-berri ishaan-berri merged commit 831083b into litellm_ishaan_april10 Apr 10, 2026
49 of 51 checks passed
@ishaan-berri ishaan-berri deleted the feat/anthropic-advisor-tool branch April 10, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(advisor): Anthropic Claude Code /advisor rollout

3 participants