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.
_parse_tools(tools: List[BaseTool]) -> List[Any]:
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.
get_output_converter(llm, model, instructions):
Abstract method to get the converter class for the agent to create json/pydantic outputs.
@@ -253,7 +253,7 @@ class BaseAgent(ABC, BaseModel):
pass
@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."""
pass

View File

@@ -6,7 +6,7 @@ import warnings
from concurrent.futures import Future
from copy import copy as shallow_copy
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 (
UUID4,
@@ -35,6 +35,7 @@ from crewai.process import Process
from crewai.task import Task
from crewai.tasks.conditional_task import ConditionalTask
from crewai.tasks.task_output import TaskOutput
from crewai.tools import BaseTool
from crewai.tools.agent_tools.agent_tools import AgentTools
from crewai.tools.base_tool import Tool
from crewai.types.usage_metrics import UsageMetrics
@@ -871,8 +872,8 @@ class Crew(BaseModel):
return None
def _prepare_tools(
self, agent: BaseAgent, task: Task, tools: List[Tool]
) -> List[Tool]:
self, agent: BaseAgent, task: Task, tools: Sequence[BaseTool]
) -> Sequence[BaseTool]:
# Add delegation tools if agent allows delegation
if agent.allow_delegation:
if self.process == Process.hierarchical:
@@ -887,10 +888,10 @@ class Crew(BaseModel):
tools = self._add_delegation_tools(task, tools)
# 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)
if agent and agent.multimodal:
if hasattr(agent, "multimodal") and agent.multimodal:
tools = self._add_multimodal_tools(agent, tools)
return tools
@@ -901,8 +902,8 @@ class Crew(BaseModel):
return task.agent
def _merge_tools(
self, existing_tools: List[Tool], new_tools: List[Tool]
) -> List[Tool]:
self, existing_tools: Sequence[BaseTool], new_tools: Sequence[BaseTool]
) -> Sequence[BaseTool]:
"""Merge new tools into existing tools list, avoiding duplicates by tool name."""
if not new_tools:
return existing_tools
@@ -919,20 +920,29 @@ class Crew(BaseModel):
return 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)
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()
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()
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 task.agent and task.agent.delegate_to is not None:
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"
)
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 task.agent:
tools = self._inject_delegation_tools(tools, task.agent, [task.agent])

View File

@@ -15,7 +15,7 @@ class AgentTools:
self.agents = agents
self.i18n = i18n
def tools(self) -> list[BaseTool]:
def tools(self) -> Sequence[BaseTool]:
"""Get all available agent tools"""
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()
# Verify task tools override agent tools
assert task.tools is not None
assert len(task.tools) == 1 # AnotherTestTool
assert any(isinstance(tool, AnotherTestTool) for tool in task.tools)
assert not any(isinstance(tool, TestTool) for tool in task.tools)
# Verify agent tools remain unchanged
assert new_researcher.tools is not None
assert len(new_researcher.tools) == 1
assert isinstance(new_researcher.tools[0], TestTool)
@pytest.mark.vcr(filter_headers=["authorization"])
@@ -1595,6 +1596,8 @@ def test_crew_function_calling_llm():
crew = Crew(agents=[agent1], tasks=[essay])
result = crew.kickoff()
assert result.raw == "Howdy!"
assert agent1.tools is not None
assert len(agent1.tools) == 0
@pytest.mark.vcr(filter_headers=["authorization"])
@@ -4157,6 +4160,7 @@ def test_manager_agent_with_tools_and_delegation():
crew._create_manager_agent()
# Verify that the manager agent has tools
assert manager.tools is not None
assert len(manager.tools) == 1
assert manager.tools[0].name == "Simple Test Tool"