Repository: huggingface/smolagents

Issue:
[BUG] ValueError: Each tool or managed_agent should have a unique name! You passed these duplicate names ['inspect_file_as_text', 'inspect_file_as_text']
**Describe the bug**
`ValueError: Each tool or managed_agent should have a unique name! You passed these duplicate names: ['inspect_file_as_text', 'inspect_file_as_text']`

**Code to reproduce the error**
Installed and ran Open Deep Search using this page: https://github.com/huggingface/smolagents/tree/main/examples/open_deep_research

EXCEPT, I used this instead for installing smolagents from the main branch as instructed in [this Issue: ](https://github.com/huggingface/smolagents/issues/777): `pip install -e ../../.[dev]`

My run command is: `python run.py --model-id "o1" "$(cat /path/file.txt)"` where my path is to a file containing the prompt text 

**Error logs**
```
Traceback (most recent call last):
  File "/Users/m/Projects/smolagents/examples/open_deep_research/run.py", line 146, in <module>
    main()
    ~~~~^^
  File "/Users/m/Projects/smolagents/examples/open_deep_research/run.py", line 130, in main
    manager_agent = CodeAgent(
        model=model,
    ...<5 lines>...
        managed_agents=[text_webbrowser_agent],
    )
  File "/Users/m/Projects/smolagents/src/smolagents/agents.py", line 1161, in __init__
    super().__init__(
    ~~~~~~~~~~~~~~~~^
        tools=tools,
        ^^^^^^^^^^^^
    ...<4 lines>...
        **kwargs,
        ^^^^^^^^^
    )
    ^
  File "/Users/m/Projects/smolagents/src/smolagents/agents.py", line 225, in __init__
    self._validate_tools_and_managed_agents(tools, managed_agents)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/m/Projects/smolagents/src/smolagents/agents.py", line 266, in _validate_tools_and_managed_agents
    raise ValueError(
    ...<2 lines>...
    )
ValueError: Each tool or managed_agent should have a unique name! You passed these duplicate names: ['inspect_file_as_text', 'inspect_file_as_text']
```

**Expected behavior**
_I expected Open DeepResearch to run and produce results in the form of OpenAI Deep Research. I certainly expected it to be able to do google searches as part of that process._

**Packages version:**
```
openinference-instrumentation-smolagents==0.1.6
-e git+ssh://git@github.com/huggingface/smolagents.git@99102f1baa884730a42f0614165b03c08b658a04#egg=smolagents
```

**Additional context**
N/A



Discussion:

Patch:
diff --git a/src/smolagents/agents.py b/src/smolagents/agents.py
index d7134ba9a..f2b881f39 100644
--- a/src/smolagents/agents.py
+++ b/src/smolagents/agents.py
@@ -257,11 +257,9 @@ def _setup_tools(self, tools, add_base_tools):
     def _validate_tools_and_managed_agents(self, tools, managed_agents):
         tool_and_managed_agent_names = [tool.name for tool in tools]
         if managed_agents is not None:
-            for agent in managed_agents:
-                tool_and_managed_agent_names.append(agent.name)
-                for tool in agent.tools.values():
-                    if tool.name != "final_answer":
-                        tool_and_managed_agent_names.append(tool.name)
+            tool_and_managed_agent_names += [agent.name for agent in managed_agents]
+        if self.name:
+            tool_and_managed_agent_names.append(self.name)
         if len(tool_and_managed_agent_names) != len(set(tool_and_managed_agent_names)):
             raise ValueError(
                 "Each tool or managed_agent should have a unique name! You passed these duplicate names: "


Test patch:
diff --git a/tests/test_agents.py b/tests/test_agents.py
index b20027b92..16ab5a749 100644
--- a/tests/test_agents.py
+++ b/tests/test_agents.py
@@ -16,6 +16,7 @@
 import tempfile
 import unittest
 import uuid
+from contextlib import nullcontext as does_not_raise
 from pathlib import Path
 from unittest.mock import MagicMock
 
@@ -41,7 +42,7 @@
     MessageRole,
     TransformersModel,
 )
-from smolagents.tools import tool
+from smolagents.tools import Tool, tool
 from smolagents.utils import BASE_BUILTIN_MODULES
 
 
@@ -574,6 +575,24 @@ def forward(self, answer) -> str:
         return answer + "CUSTOM"
 
 
+class MockTool(Tool):
+    def __init__(self, name):
+        self.name = name
+        self.description = "Mock tool description"
+        self.inputs = {}
+        self.output_type = "string"
+
+    def forward(self):
+        return "Mock tool output"
+
+
+class MockAgent:
+    def __init__(self, name, tools, description="Mock agent description"):
+        self.name = name
+        self.tools = {t.name: t for t in tools}
+        self.description = description
+
+
 class TestMultiStepAgent:
     def test_instantiation_disables_logging_to_terminal(self):
         fake_model = MagicMock()
@@ -784,6 +803,51 @@ def test_provide_final_answer(self, images, expected_messages_list):
                 for content, expected_content in zip(message["content"], expected_message["content"]):
                     assert content == expected_content
 
+    @pytest.mark.parametrize(
+        "tools, managed_agents, name, expectation",
+        [
+            # Valid case: no duplicates
+            (
+                [MockTool("tool1"), MockTool("tool2")],
+                [MockAgent("agent1", [MockTool("tool3")])],
+                "test_agent",
+                does_not_raise(),
+            ),
+            # Invalid case: duplicate tool names
+            ([MockTool("tool1"), MockTool("tool1")], [], "test_agent", pytest.raises(ValueError)),
+            # Invalid case: tool name same as managed agent name
+            (
+                [MockTool("tool1")],
+                [MockAgent("tool1", [MockTool("final_answer")])],
+                "test_agent",
+                pytest.raises(ValueError),
+            ),
+            # Valid case: tool name same as managed agent's tool name
+            ([MockTool("tool1")], [MockAgent("agent1", [MockTool("tool1")])], "test_agent", does_not_raise()),
+            # Invalid case: duplicate managed agent name and managed agent tool name
+            ([MockTool("tool1")], [], "tool1", pytest.raises(ValueError)),
+            # Valid case: duplicate tool names across managed agents
+            (
+                [MockTool("tool1")],
+                [
+                    MockAgent("agent1", [MockTool("tool2"), MockTool("final_answer")]),
+                    MockAgent("agent2", [MockTool("tool2"), MockTool("final_answer")]),
+                ],
+                "test_agent",
+                does_not_raise(),
+            ),
+        ],
+    )
+    def test_validate_tools_and_managed_agents(self, tools, managed_agents, name, expectation):
+        fake_model = MagicMock()
+        with expectation:
+            MultiStepAgent(
+                tools=tools,
+                model=fake_model,
+                name=name,
+                managed_agents=managed_agents,
+            )
+
 
 class TestCodeAgent:
     @pytest.mark.parametrize("provide_run_summary", [False, True])