Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
)
from agent_framework._settings import SecretString, load_settings
from agent_framework._telemetry import get_user_agent
from agent_framework._tools import SHELL_TOOL_KIND_VALUE
from agent_framework._tools import SHELL_TOOL_KIND_VALUE, normalize_tools
from agent_framework._types import _get_data_bytes_as_str # type: ignore
from agent_framework.observability import ChatTelemetryLayer
from anthropic import AsyncAnthropic, AsyncAnthropicFoundry
Expand Down Expand Up @@ -950,7 +950,7 @@ def _prepare_tools_for_anthropic(self, options: Mapping[str, Any]) -> dict[str,
tool_list: list[Any] = []
mcp_server_list: list[Any] = []
tool_name_aliases: dict[str, str] = {}
for tool in tools:
for tool in normalize_tools(tools):
if isinstance(tool, FunctionTool) and tool.kind == SHELL_TOOL_KIND_VALUE:
api_type = (tool.additional_properties or {}).get("type", "bash_20250124")
tool_name_aliases["bash"] = tool.name
Expand Down
36 changes: 36 additions & 0 deletions python/packages/anthropic/tests/test_anthropic_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,27 @@ def get_weather(
assert "Get weather for a location" in result["tools"][0]["description"]


def test_prepare_tools_for_anthropic_single_tool(mock_anthropic_client: MagicMock) -> None:
"""Test converting a single FunctionTool to Anthropic format."""
client = create_test_anthropic_client(mock_anthropic_client)

@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="Location to get weather for")],
) -> str:
"""Get weather for a location."""
return f"Weather for {location}"

chat_options = ChatOptions(tools=get_weather)
result = client._prepare_tools_for_anthropic(chat_options)

assert result is not None
assert "tools" in result
assert len(result["tools"]) == 1
assert result["tools"][0]["type"] == "custom"
assert result["tools"][0]["name"] == "get_weather"


def test_prepare_tools_for_anthropic_web_search(
mock_anthropic_client: MagicMock,
) -> None:
Expand Down Expand Up @@ -918,6 +939,21 @@ def test_prepare_tools_for_anthropic_dict_tool(
assert result["tools"][0]["name"] == "custom_tool"


def test_prepare_tools_for_anthropic_single_dict_tool(
mock_anthropic_client: MagicMock,
) -> None:
"""Test passing through a single dict tool."""
client = create_test_anthropic_client(mock_anthropic_client)
chat_options = ChatOptions(tools={"type": "custom", "name": "custom_tool", "description": "A custom tool"})

result = client._prepare_tools_for_anthropic(chat_options)

assert result is not None
assert "tools" in result
assert len(result["tools"]) == 1
assert result["tools"][0]["name"] == "custom_tool"


def test_prepare_tools_for_anthropic_none(mock_anthropic_client: MagicMock) -> None:
"""Test converting None tools."""
client = create_test_anthropic_client(mock_anthropic_client)
Expand Down