From 6d42f67dfc7fe0046821793b1528c09f02a491a2 Mon Sep 17 00:00:00 2001 From: Lucas Gomide Date: Wed, 4 Jun 2025 10:53:25 -0300 Subject: [PATCH] feat: load Tool from Agent repository by their own module (#2940) Previously, we only supported tools from the crewai-tools open-source repository. Now, we're introducing improved support for private tool repositories. --- src/crewai/utilities/agent_utils.py | 2 +- tests/agent_test.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/crewai/utilities/agent_utils.py b/src/crewai/utilities/agent_utils.py index 83294408b..673134f94 100644 --- a/src/crewai/utilities/agent_utils.py +++ b/src/crewai/utilities/agent_utils.py @@ -486,7 +486,7 @@ def load_agent_from_repository(from_repository: str) -> Dict[str, Any]: attributes[key] = [] for tool in value: try: - module = importlib.import_module("crewai_tools") + module = importlib.import_module(tool["module"]) tool_class = getattr(module, tool["name"]) attributes[key].append(tool_class()) except Exception as e: diff --git a/tests/agent_test.py b/tests/agent_test.py index 22748ab2e..ecbbbd4ee 100644 --- a/tests/agent_test.py +++ b/tests/agent_test.py @@ -2038,7 +2038,7 @@ def mock_get_auth_token(): @patch("crewai.cli.plus_api.PlusAPI.get_agent") def test_agent_from_repository(mock_get_agent, mock_get_auth_token): - from crewai_tools import SerperDevTool + from crewai_tools import SerperDevTool, XMLSearchTool mock_get_response = MagicMock() mock_get_response.status_code = 200 @@ -2046,7 +2046,10 @@ def test_agent_from_repository(mock_get_agent, mock_get_auth_token): "role": "test role", "goal": "test goal", "backstory": "test backstory", - "tools": [{"name": "SerperDevTool"}], + "tools": [ + {"module": "crewai_tools", "name": "SerperDevTool"}, + {"module": "crewai_tools", "name": "XMLSearchTool"}, + ], } mock_get_agent.return_value = mock_get_response agent = Agent(from_repository="test_agent") @@ -2054,8 +2057,9 @@ def test_agent_from_repository(mock_get_agent, mock_get_auth_token): assert agent.role == "test role" assert agent.goal == "test goal" assert agent.backstory == "test backstory" - assert len(agent.tools) == 1 + assert len(agent.tools) == 2 assert isinstance(agent.tools[0], SerperDevTool) + assert isinstance(agent.tools[1], XMLSearchTool) @patch("crewai.cli.plus_api.PlusAPI.get_agent") @@ -2068,7 +2072,7 @@ def test_agent_from_repository_override_attributes(mock_get_agent, mock_get_auth "role": "test role", "goal": "test goal", "backstory": "test backstory", - "tools": [{"name": "SerperDevTool"}], + "tools": [{"name": "SerperDevTool", "module": "crewai_tools"}], } mock_get_agent.return_value = mock_get_response agent = Agent(from_repository="test_agent", role="Custom Role") @@ -2088,7 +2092,7 @@ def test_agent_from_repository_with_invalid_tools(mock_get_agent, mock_get_auth_ "role": "test role", "goal": "test goal", "backstory": "test backstory", - "tools": [{"name": "DoesNotExist"}], + "tools": [{"name": "DoesNotExist", "module": "crewai_tools",}], } mock_get_agent.return_value = mock_get_response with pytest.raises(