From a07356f8397f6ccb8f9a613ed945f8f4a3c36bfe Mon Sep 17 00:00:00 2001 From: Radhakrishnan Pachyappan Date: Fri, 10 Jul 2026 07:48:52 +0530 Subject: [PATCH] fix(anthropic): add advisor_ prefix to builtin tool recognition (#38686) --- .../langchain_anthropic/chat_models.py | 1 + .../tests/unit_tests/test_chat_models.py | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/libs/partners/anthropic/langchain_anthropic/chat_models.py b/libs/partners/anthropic/langchain_anthropic/chat_models.py index edffea935ad..c926d80eabe 100644 --- a/libs/partners/anthropic/langchain_anthropic/chat_models.py +++ b/libs/partners/anthropic/langchain_anthropic/chat_models.py @@ -161,6 +161,7 @@ _BUILTIN_TOOL_PREFIXES = [ "mcp_toolset", "memory_", "tool_search_", + "advisor_", ] _ANTHROPIC_EXTRA_FIELDS: set[str] = { diff --git a/libs/partners/anthropic/tests/unit_tests/test_chat_models.py b/libs/partners/anthropic/tests/unit_tests/test_chat_models.py index f7c4dc669b9..a1776cb3f18 100644 --- a/libs/partners/anthropic/tests/unit_tests/test_chat_models.py +++ b/libs/partners/anthropic/tests/unit_tests/test_chat_models.py @@ -2575,6 +2575,33 @@ def test_tool_search_is_builtin_tool() -> None: assert not _is_builtin_tool(regular_tool) +def test_advisor_is_builtin_tool() -> None: + """Test that advisor_ tools are recognized as built-in and pass through bind_tools. + + Regression test for https://github.com/langchain-ai/langchain/issues/38644. + advisor_20260301 (Anthropic Advisor native tool) was missing from + _BUILTIN_TOOL_PREFIXES, causing bind_tools() to route it through + convert_to_anthropic_tool() which crashed with KeyError: 'parameters'. + """ + advisor_tool = { + "type": "advisor_20260301", + "name": "advisor", + "model": MODEL_NAME, + "max_uses": 3, + "max_tokens": 1024, + } + assert _is_builtin_tool(advisor_tool) + + # bind_tools() must pass the advisor tool through unchanged, not raise KeyError + model = ChatAnthropic(model=MODEL_NAME) # type: ignore[call-arg] + bound = model.bind_tools([advisor_tool]) + payload = bound._get_request_payload( # type: ignore[attr-defined] + [HumanMessage("hello")], + **bound.kwargs, # type: ignore[attr-defined] + ) + assert advisor_tool in payload["tools"] + + def test_tool_search_beta_headers() -> None: """Test that tool search tools auto-append the correct beta headers.""" # Test regex variant