File tree Expand file tree Collapse file tree 5 files changed +38
-31
lines changed Expand file tree Collapse file tree 5 files changed +38
-31
lines changed Original file line number Diff line number Diff line change @@ -108,14 +108,10 @@ def find_normalized_tool_name() -> Optional[str]:
108108 # all tools that can be represented with the normalized name
109109 if "_" in name :
110110 filtered_tools = [
111- tool_name
112- for (tool_name , tool ) in tool_registry .items ()
113- if tool_name .replace ("-" , "_" ) == name
111+ tool_name for (tool_name , tool ) in tool_registry .items () if tool_name .replace ("-" , "_" ) == name
114112 ]
115113
116- if len (filtered_tools ) > 1 :
117- raise AttributeError (f"Multiple tools matching '{ name } ' found: { ', ' .join (filtered_tools )} " )
118-
114+ # The registry itself defends against similar names, so we can just take the first match
119115 if filtered_tools :
120116 return filtered_tools [0 ]
121117
Original file line number Diff line number Diff line change 1313
1414from opentelemetry import trace
1515from opentelemetry .exporter .otlp .proto .http .trace_exporter import OTLPSpanExporter
16-
17- # See https://github.com/open-telemetry/opentelemetry-python/issues/4615 for the type ignore
18- from opentelemetry .sdk .resources import Resource # type: ignore[attr-defined]
16+ from opentelemetry .sdk .resources import Resource
1917from opentelemetry .sdk .trace import TracerProvider
2018from opentelemetry .sdk .trace .export import BatchSpanProcessor , ConsoleSpanExporter , SimpleSpanProcessor
2119from opentelemetry .trace import StatusCode
Original file line number Diff line number Diff line change @@ -189,6 +189,21 @@ def register_tool(self, tool: AgentTool) -> None:
189189 tool .is_dynamic ,
190190 )
191191
192+ if self .registry .get (tool .tool_name ) is None :
193+ normalized_name = tool .tool_name .replace ("-" , "_" )
194+
195+ matching_tools = [
196+ tool_name
197+ for (tool_name , tool ) in self .registry .items ()
198+ if tool_name .replace ("-" , "_" ) == normalized_name
199+ ]
200+
201+ if matching_tools :
202+ raise ValueError (
203+ f"Tool name '{ tool .tool_name } ' already exists as '{ matching_tools [0 ]} '."
204+ " Cannot add a duplicate tool which differs by a '-' or '_'"
205+ )
206+
192207 # Register in main registry
193208 self .registry [tool .tool_name ] = tool
194209
Original file line number Diff line number Diff line change @@ -739,28 +739,6 @@ def function(system_prompt: str) -> str:
739739 }
740740
741741
742- def test_agent_tool_with_multiple_normalized_matches (agent , tool_registry , mock_randint ):
743- agent .tool_handler = unittest .mock .Mock ()
744-
745- @strands .tools .tool (name = "system-prompter_1" )
746- def function1 (system_prompt : str ) -> str :
747- return system_prompt
748-
749- @strands .tools .tool (name = "system-prompter-1" )
750- def function2 (system_prompt : str ) -> str :
751- return system_prompt
752-
753- agent .tool_registry .register_tool (strands .tools .tools .FunctionTool (function1 ))
754- agent .tool_registry .register_tool (strands .tools .tools .FunctionTool (function2 ))
755-
756- mock_randint .return_value = 1
757-
758- with pytest .raises (AttributeError ) as err :
759- agent .tool .system_prompter_1 (system_prompt = "tool prompt" )
760-
761- assert str (err .value ) == "Multiple tools matching 'system_prompter_1' found: system-prompter_1, system-prompter-1"
762-
763-
764742def test_agent_tool_with_no_normalized_match (agent , tool_registry , mock_randint ):
765743 agent .tool_handler = unittest .mock .Mock ()
766744
Original file line number Diff line number Diff line change 22Tests for the SDK tool registry module.
33"""
44
5+ from unittest .mock import MagicMock
6+
57import pytest
68
9+ from strands .tools import PythonAgentTool
710from strands .tools .registry import ToolRegistry
811
912
@@ -23,3 +26,20 @@ def test_process_tools_with_invalid_path():
2326
2427 with pytest .raises (ValueError , match = f"Failed to load tool { invalid_path .split ('.' )[0 ]} : Tool file not found:.*" ):
2528 tool_registry .process_tools ([invalid_path ])
29+
30+
31+ def test_register_tool_with_similar_name_raises ():
32+ tool_1 = PythonAgentTool (tool_name = "tool-like-this" , tool_spec = MagicMock (), callback = lambda : None )
33+ tool_2 = PythonAgentTool (tool_name = "tool_like_this" , tool_spec = MagicMock (), callback = lambda : None )
34+
35+ tool_registry = ToolRegistry ()
36+
37+ tool_registry .register_tool (tool_1 )
38+
39+ with pytest .raises (ValueError ) as err :
40+ tool_registry .register_tool (tool_2 )
41+
42+ assert (
43+ str (err .value ) == "Tool name 'tool_like_this' already exists as 'tool-like-this'. "
44+ "Cannot add a duplicate tool which differs by a '-' or '_'"
45+ )
You can’t perform that action at this time.
0 commit comments