Skip to content
Merged
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
7 changes: 7 additions & 0 deletions src/strands/tools/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ 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 and 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("-", "_")

Expand Down
36 changes: 36 additions & 0 deletions tests/strands/tools/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading