This commit is contained in:
Brandon Hancock
2025-03-13 11:02:28 -04:00
parent bd27d03bc7
commit 403890d8e8
4 changed files with 30 additions and 16 deletions

View File

@@ -62,7 +62,7 @@ class BaseAgent(ABC, BaseModel):
Abstract method to create an agent executor. Abstract method to create an agent executor.
_parse_tools(tools: List[BaseTool]) -> List[Any]: _parse_tools(tools: List[BaseTool]) -> List[Any]:
Abstract method to parse tools. Abstract method to parse tools.
get_delegation_tools(agents: Sequence["BaseAgent"]) -> List[BaseTool]: get_delegation_tools(agents: Sequence["BaseAgent"]) -> Sequence[BaseTool]:
Abstract method to set the agents task tools for handling delegation and question asking to other agents in crew. Abstract method to set the agents task tools for handling delegation and question asking to other agents in crew.
get_output_converter(llm, model, instructions): get_output_converter(llm, model, instructions):
Abstract method to get the converter class for the agent to create json/pydantic outputs. Abstract method to get the converter class for the agent to create json/pydantic outputs.
@@ -253,7 +253,7 @@ class BaseAgent(ABC, BaseModel):
pass pass
@abstractmethod @abstractmethod
def get_delegation_tools(self, agents: Sequence["BaseAgent"]) -> List[BaseTool]: def get_delegation_tools(self, agents: Sequence["BaseAgent"]) -> Sequence[BaseTool]:
"""Set the task tools that init BaseAgenTools class.""" """Set the task tools that init BaseAgenTools class."""
pass pass

View File

@@ -6,7 +6,7 @@ import warnings
from concurrent.futures import Future from concurrent.futures import Future
from copy import copy as shallow_copy from copy import copy as shallow_copy
from hashlib import md5 from hashlib import md5
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Union
from pydantic import ( from pydantic import (
UUID4, UUID4,
@@ -35,6 +35,7 @@ from crewai.process import Process
from crewai.task import Task from crewai.task import Task
from crewai.tasks.conditional_task import ConditionalTask from crewai.tasks.conditional_task import ConditionalTask
from crewai.tasks.task_output import TaskOutput from crewai.tasks.task_output import TaskOutput
from crewai.tools import BaseTool
from crewai.tools.agent_tools.agent_tools import AgentTools from crewai.tools.agent_tools.agent_tools import AgentTools
from crewai.tools.base_tool import Tool from crewai.tools.base_tool import Tool
from crewai.types.usage_metrics import UsageMetrics from crewai.types.usage_metrics import UsageMetrics
@@ -871,8 +872,8 @@ class Crew(BaseModel):
return None return None
def _prepare_tools( def _prepare_tools(
self, agent: BaseAgent, task: Task, tools: List[Tool] self, agent: BaseAgent, task: Task, tools: Sequence[BaseTool]
) -> List[Tool]: ) -> Sequence[BaseTool]:
# Add delegation tools if agent allows delegation # Add delegation tools if agent allows delegation
if agent.allow_delegation: if agent.allow_delegation:
if self.process == Process.hierarchical: if self.process == Process.hierarchical:
@@ -887,10 +888,10 @@ class Crew(BaseModel):
tools = self._add_delegation_tools(task, tools) tools = self._add_delegation_tools(task, tools)
# Add code execution tools if agent allows code execution # Add code execution tools if agent allows code execution
if agent.allow_code_execution: if hasattr(agent, "allow_code_execution") and agent.allow_code_execution:
tools = self._add_code_execution_tools(agent, tools) tools = self._add_code_execution_tools(agent, tools)
if agent and agent.multimodal: if hasattr(agent, "multimodal") and agent.multimodal:
tools = self._add_multimodal_tools(agent, tools) tools = self._add_multimodal_tools(agent, tools)
return tools return tools
@@ -901,8 +902,8 @@ class Crew(BaseModel):
return task.agent return task.agent
def _merge_tools( def _merge_tools(
self, existing_tools: List[Tool], new_tools: List[Tool] self, existing_tools: Sequence[BaseTool], new_tools: Sequence[BaseTool]
) -> List[Tool]: ) -> Sequence[BaseTool]:
"""Merge new tools into existing tools list, avoiding duplicates by tool name.""" """Merge new tools into existing tools list, avoiding duplicates by tool name."""
if not new_tools: if not new_tools:
return existing_tools return existing_tools
@@ -919,20 +920,29 @@ class Crew(BaseModel):
return tools return tools
def _inject_delegation_tools( def _inject_delegation_tools(
self, tools: List[Tool], task_agent: BaseAgent, agents: List[BaseAgent] self,
tools: Sequence[BaseTool],
task_agent: BaseAgent,
agents: Sequence[BaseAgent],
): ):
delegation_tools = task_agent.get_delegation_tools(agents) delegation_tools = task_agent.get_delegation_tools(agents)
return self._merge_tools(tools, delegation_tools) return self._merge_tools(tools, delegation_tools)
def _add_multimodal_tools(self, agent: BaseAgent, tools: List[Tool]): def _add_multimodal_tools(
self, agent: BaseAgent, tools: Sequence[BaseTool]
) -> Sequence[BaseTool]:
multimodal_tools = agent.get_multimodal_tools() multimodal_tools = agent.get_multimodal_tools()
return self._merge_tools(tools, multimodal_tools) return self._merge_tools(tools, multimodal_tools)
def _add_code_execution_tools(self, agent: BaseAgent, tools: List[Tool]): def _add_code_execution_tools(
self, agent: BaseAgent, tools: Sequence[BaseTool]
) -> Sequence[BaseTool]:
code_tools = agent.get_code_execution_tools() code_tools = agent.get_code_execution_tools()
return self._merge_tools(tools, code_tools) return self._merge_tools(tools, code_tools)
def _add_delegation_tools(self, task: Task, tools: List[Tool]): def _add_delegation_tools(
self, task: Task, tools: Sequence[BaseTool]
) -> Sequence[BaseTool]:
# If the agent has specific agents to delegate to, use those # If the agent has specific agents to delegate to, use those
if task.agent and task.agent.delegate_to is not None: if task.agent and task.agent.delegate_to is not None:
agents_for_delegation = task.agent.delegate_to agents_for_delegation = task.agent.delegate_to
@@ -956,7 +966,7 @@ class Crew(BaseModel):
task_name=task.name, task=task.description, agent=role, status="started" task_name=task.name, task=task.description, agent=role, status="started"
) )
def _update_manager_tools(self, task: Task, tools: List[Tool]): def _update_manager_tools(self, task: Task, tools: Sequence[BaseTool]):
if self.manager_agent: if self.manager_agent:
if task.agent: if task.agent:
tools = self._inject_delegation_tools(tools, task.agent, [task.agent]) tools = self._inject_delegation_tools(tools, task.agent, [task.agent])

View File

@@ -15,7 +15,7 @@ class AgentTools:
self.agents = agents self.agents = agents
self.i18n = i18n self.i18n = i18n
def tools(self) -> list[BaseTool]: def tools(self) -> Sequence[BaseTool]:
"""Get all available agent tools""" """Get all available agent tools"""
coworkers = ", ".join([f"{agent.role}" for agent in self.agents]) coworkers = ", ".join([f"{agent.role}" for agent in self.agents])

View File

@@ -723,13 +723,14 @@ def test_task_tools_override_agent_tools():
crew.kickoff() crew.kickoff()
# Verify task tools override agent tools # Verify task tools override agent tools
assert task.tools is not None
assert len(task.tools) == 1 # AnotherTestTool assert len(task.tools) == 1 # AnotherTestTool
assert any(isinstance(tool, AnotherTestTool) for tool in task.tools) assert any(isinstance(tool, AnotherTestTool) for tool in task.tools)
assert not any(isinstance(tool, TestTool) for tool in task.tools) assert not any(isinstance(tool, TestTool) for tool in task.tools)
# Verify agent tools remain unchanged # Verify agent tools remain unchanged
assert new_researcher.tools is not None
assert len(new_researcher.tools) == 1 assert len(new_researcher.tools) == 1
assert isinstance(new_researcher.tools[0], TestTool)
@pytest.mark.vcr(filter_headers=["authorization"]) @pytest.mark.vcr(filter_headers=["authorization"])
@@ -1595,6 +1596,8 @@ def test_crew_function_calling_llm():
crew = Crew(agents=[agent1], tasks=[essay]) crew = Crew(agents=[agent1], tasks=[essay])
result = crew.kickoff() result = crew.kickoff()
assert result.raw == "Howdy!" assert result.raw == "Howdy!"
assert agent1.tools is not None
assert len(agent1.tools) == 0
@pytest.mark.vcr(filter_headers=["authorization"]) @pytest.mark.vcr(filter_headers=["authorization"])
@@ -4157,6 +4160,7 @@ def test_manager_agent_with_tools_and_delegation():
crew._create_manager_agent() crew._create_manager_agent()
# Verify that the manager agent has tools # Verify that the manager agent has tools
assert manager.tools is not None
assert len(manager.tools) == 1 assert len(manager.tools) == 1
assert manager.tools[0].name == "Simple Test Tool" assert manager.tools[0].name == "Simple Test Tool"