From 4b474a2646aba5935f82f6bbf0ac2dd386bebfa9 Mon Sep 17 00:00:00 2001 From: Jack Yuan Date: Fri, 29 Aug 2025 15:40:43 -0400 Subject: [PATCH 1/2] fix: fix loading tools with same tool name --- src/strands/tools/registry.py | 8 +++++++ tests/strands/tools/test_registry.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/strands/tools/registry.py b/src/strands/tools/registry.py index fd395ae77..23d03bb70 100644 --- a/src/strands/tools/registry.py +++ b/src/strands/tools/registry.py @@ -190,6 +190,14 @@ def register_tool(self, tool: AgentTool) -> None: tool.is_dynamic, ) + # Check duplicate tool name, throw on duplicate tool names except if hot_reloading is enabled + if tool.tool_name in self.registry: + if not tool.supports_hot_reload: + raise ValueError( + f"Tool name '{tool.tool_name}' already exists. Cannot register tools with exact same name." + ) + + # Check for normalized name conflicts (- vs _) if self.registry.get(tool.tool_name) is None: normalized_name = tool.tool_name.replace("-", "_") diff --git a/tests/strands/tools/test_registry.py b/tests/strands/tools/test_registry.py index 66494c987..ca3cded4c 100644 --- a/tests/strands/tools/test_registry.py +++ b/tests/strands/tools/test_registry.py @@ -120,3 +120,39 @@ def function() -> str: "tool_f", ] assert tru_tool_names == exp_tool_names + + +def test_register_tool_duplicate_name_without_hot_reload(): + """Test that registering a tool with duplicate name raises ValueError when hot reload is not supported.""" + tool_1 = PythonAgentTool(tool_name="duplicate_tool", tool_spec=MagicMock(), tool_func=lambda: None) + tool_2 = PythonAgentTool(tool_name="duplicate_tool", tool_spec=MagicMock(), tool_func=lambda: None) + + tool_registry = ToolRegistry() + tool_registry.register_tool(tool_1) + + with pytest.raises( + ValueError, match="Tool name 'duplicate_tool' already exists. Cannot register tools with exact same name." + ): + tool_registry.register_tool(tool_2) + + +def test_register_tool_duplicate_name_with_hot_reload(): + """Test that registering a tool with duplicate name succeeds when hot reload is supported.""" + # Create mock tools with hot reload support + tool_1 = MagicMock(spec=PythonAgentTool) + tool_1.tool_name = "hot_reload_tool" + tool_1.supports_hot_reload = True + tool_1.is_dynamic = False + + tool_2 = MagicMock(spec=PythonAgentTool) + tool_2.tool_name = "hot_reload_tool" + tool_2.supports_hot_reload = True + tool_2.is_dynamic = False + + tool_registry = ToolRegistry() + tool_registry.register_tool(tool_1) + + tool_registry.register_tool(tool_2) + + # Verify the second tool replaced the first + assert tool_registry.registry["hot_reload_tool"] == tool_2 From 2ddefa2a2d68e4bfaa1f37e987072c8fc5c6fb46 Mon Sep 17 00:00:00 2001 From: Jack Yuan Date: Fri, 29 Aug 2025 16:15:52 -0400 Subject: [PATCH 2/2] simplify if condition --- src/strands/tools/registry.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/strands/tools/registry.py b/src/strands/tools/registry.py index 23d03bb70..6bb76f560 100644 --- a/src/strands/tools/registry.py +++ b/src/strands/tools/registry.py @@ -191,8 +191,7 @@ def register_tool(self, tool: AgentTool) -> None: ) # Check duplicate tool name, throw on duplicate tool names except if hot_reloading is enabled - if tool.tool_name in self.registry: - if not tool.supports_hot_reload: + if tool.tool_name in self.registry and not tool.supports_hot_reload: raise ValueError( f"Tool name '{tool.tool_name}' already exists. Cannot register tools with exact same name." )