mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-27 09:08:14 +00:00
getting ready
This commit is contained in:
@@ -227,7 +227,6 @@ class Agent(BaseAgent):
|
|||||||
task_prompt += crew_knowledge_context
|
task_prompt += crew_knowledge_context
|
||||||
|
|
||||||
tools = tools or self.tools or []
|
tools = tools or self.tools or []
|
||||||
print(f"tools: {tools}")
|
|
||||||
self.create_agent_executor(tools=tools, task=task)
|
self.create_agent_executor(tools=tools, task=task)
|
||||||
|
|
||||||
if self.crew and self.crew._train:
|
if self.crew and self.crew._train:
|
||||||
|
|||||||
@@ -739,14 +739,15 @@ class Crew(BaseModel):
|
|||||||
def _create_manager_agent(self):
|
def _create_manager_agent(self):
|
||||||
i18n = I18N(prompt_file=self.prompt_file)
|
i18n = I18N(prompt_file=self.prompt_file)
|
||||||
if self.manager_agent is not None:
|
if self.manager_agent is not None:
|
||||||
|
# Ensure delegation is enabled for the manager agent
|
||||||
self.manager_agent.allow_delegation = True
|
self.manager_agent.allow_delegation = True
|
||||||
# Set the delegate_to property to all agents in the crew
|
|
||||||
self.manager_agent.delegate_to = self.agents
|
|
||||||
manager = self.manager_agent
|
|
||||||
|
|
||||||
# Instead, we ensure it has delegation tools
|
# Set the delegate_to property to all agents in the crew
|
||||||
if not manager.allow_delegation:
|
# If delegate_to is already set, it will be used instead of all agents
|
||||||
manager.allow_delegation = True
|
if self.manager_agent.delegate_to is None:
|
||||||
|
self.manager_agent.delegate_to = self.agents
|
||||||
|
|
||||||
|
manager = self.manager_agent
|
||||||
else:
|
else:
|
||||||
self.manager_llm = create_llm(self.manager_llm)
|
self.manager_llm = create_llm(self.manager_llm)
|
||||||
# Create delegation tools
|
# Create delegation tools
|
||||||
@@ -802,11 +803,8 @@ class Crew(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Determine which tools to use - task tools take precedence over agent tools
|
# Determine which tools to use - task tools take precedence over agent tools
|
||||||
tools_for_task: Sequence[BaseTool] = task.tools or agent_to_use.tools or []
|
initial_tools = task.tools or agent_to_use.tools or []
|
||||||
# Ensure tools_for_task is a Sequence[BaseTool]
|
prepared_tools = self._prepare_tools(agent_to_use, task, initial_tools)
|
||||||
if not isinstance(tools_for_task, Sequence):
|
|
||||||
tools_for_task = list(tools_for_task) if tools_for_task else []
|
|
||||||
tools_for_task = self._prepare_tools(agent_to_use, task, tools_for_task)
|
|
||||||
|
|
||||||
self._log_task_start(task, agent_to_use.role)
|
self._log_task_start(task, agent_to_use.role)
|
||||||
|
|
||||||
@@ -825,7 +823,7 @@ class Crew(BaseModel):
|
|||||||
future = task.execute_async(
|
future = task.execute_async(
|
||||||
agent=agent_to_use,
|
agent=agent_to_use,
|
||||||
context=context,
|
context=context,
|
||||||
tools=tools_for_task,
|
tools=prepared_tools,
|
||||||
)
|
)
|
||||||
futures.append((task, future, task_index))
|
futures.append((task, future, task_index))
|
||||||
else:
|
else:
|
||||||
@@ -837,7 +835,7 @@ class Crew(BaseModel):
|
|||||||
task_output = task.execute_sync(
|
task_output = task.execute_sync(
|
||||||
agent=agent_to_use,
|
agent=agent_to_use,
|
||||||
context=context,
|
context=context,
|
||||||
tools=tools_for_task,
|
tools=prepared_tools,
|
||||||
)
|
)
|
||||||
task_outputs.append(task_output)
|
task_outputs.append(task_output)
|
||||||
self._process_task_result(task, task_output)
|
self._process_task_result(task, task_output)
|
||||||
@@ -891,13 +889,15 @@ 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 hasattr(agent, "allow_code_execution") and agent.allow_code_execution:
|
if hasattr(agent, "allow_code_execution") and getattr(
|
||||||
|
agent, "allow_code_execution", False
|
||||||
|
):
|
||||||
tools = self._add_code_execution_tools(agent, tools)
|
tools = self._add_code_execution_tools(agent, tools)
|
||||||
|
|
||||||
if hasattr(agent, "multimodal") and agent.multimodal:
|
if hasattr(agent, "multimodal") and getattr(agent, "multimodal", False):
|
||||||
tools = self._add_multimodal_tools(agent, tools)
|
tools = self._add_multimodal_tools(agent, tools)
|
||||||
|
|
||||||
return list(tools) # Ensure we return a list, not just a Sequence
|
return list(tools)
|
||||||
|
|
||||||
def _get_agent_to_use(self, task: Task) -> Optional[BaseAgent]:
|
def _get_agent_to_use(self, task: Task) -> Optional[BaseAgent]:
|
||||||
if self.process == Process.hierarchical:
|
if self.process == Process.hierarchical:
|
||||||
@@ -934,14 +934,18 @@ class Crew(BaseModel):
|
|||||||
def _add_multimodal_tools(
|
def _add_multimodal_tools(
|
||||||
self, agent: BaseAgent, tools: Sequence[BaseTool]
|
self, agent: BaseAgent, tools: Sequence[BaseTool]
|
||||||
) -> Sequence[BaseTool]:
|
) -> Sequence[BaseTool]:
|
||||||
multimodal_tools = agent.get_multimodal_tools()
|
if hasattr(agent, "get_multimodal_tools"):
|
||||||
return self._merge_tools(tools, multimodal_tools)
|
multimodal_tools = getattr(agent, "get_multimodal_tools")()
|
||||||
|
return self._merge_tools(tools, multimodal_tools)
|
||||||
|
return tools
|
||||||
|
|
||||||
def _add_code_execution_tools(
|
def _add_code_execution_tools(
|
||||||
self, agent: BaseAgent, tools: Sequence[BaseTool]
|
self, agent: BaseAgent, tools: Sequence[BaseTool]
|
||||||
) -> Sequence[BaseTool]:
|
) -> Sequence[BaseTool]:
|
||||||
code_tools = agent.get_code_execution_tools()
|
if hasattr(agent, "get_code_execution_tools"):
|
||||||
return self._merge_tools(tools, code_tools)
|
code_tools = getattr(agent, "get_code_execution_tools")()
|
||||||
|
return self._merge_tools(tools, code_tools)
|
||||||
|
return tools
|
||||||
|
|
||||||
def _add_delegation_tools(
|
def _add_delegation_tools(
|
||||||
self, task: Task, tools: Sequence[BaseTool]
|
self, task: Task, tools: Sequence[BaseTool]
|
||||||
|
|||||||
@@ -283,12 +283,10 @@ def tool(*args):
|
|||||||
return _make_tool
|
return _make_tool
|
||||||
|
|
||||||
if len(args) == 1 and callable(args[0]):
|
if len(args) == 1 and callable(args[0]):
|
||||||
# Direct function decoration
|
|
||||||
if isinstance(args[0], BaseTool):
|
if isinstance(args[0], BaseTool):
|
||||||
return args[0] # Already a BaseTool, return as-is
|
return args[0]
|
||||||
return _make_with_name(args[0].__name__)(args[0])
|
return _make_with_name(args[0].__name__)(args[0])
|
||||||
elif len(args) == 1 and isinstance(args[0], str):
|
elif len(args) == 1 and isinstance(args[0], str):
|
||||||
# Name provided, return a decorator
|
|
||||||
return _make_with_name(args[0])
|
return _make_with_name(args[0])
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid arguments")
|
raise ValueError("Invalid arguments")
|
||||||
|
|||||||
@@ -4270,3 +4270,202 @@ def test_crew_with_default_delegation():
|
|||||||
assert "Researcher" in ask_tool.description
|
assert "Researcher" in ask_tool.description
|
||||||
assert "Writer" in ask_tool.description
|
assert "Writer" in ask_tool.description
|
||||||
assert "Editor" in ask_tool.description
|
assert "Editor" in ask_tool.description
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||||
|
def test_update_manager_tools_functionality():
|
||||||
|
"""Test that _update_manager_tools correctly adds delegation tools to the manager agent."""
|
||||||
|
# Create agents
|
||||||
|
researcher = Agent(
|
||||||
|
role="Researcher",
|
||||||
|
goal="Research information",
|
||||||
|
backstory="You're an expert researcher",
|
||||||
|
)
|
||||||
|
|
||||||
|
writer = Agent(
|
||||||
|
role="Writer",
|
||||||
|
goal="Write content",
|
||||||
|
backstory="You're an expert writer",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a manager agent
|
||||||
|
manager = Agent(
|
||||||
|
role="Manager",
|
||||||
|
goal="Manage the team",
|
||||||
|
backstory="You're an expert manager",
|
||||||
|
allow_delegation=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a crew with the manager agent
|
||||||
|
crew = Crew(
|
||||||
|
agents=[researcher, writer],
|
||||||
|
manager_agent=manager,
|
||||||
|
process=Process.hierarchical,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure the manager agent is set up
|
||||||
|
crew._create_manager_agent()
|
||||||
|
|
||||||
|
# Case 1: Task with an assigned agent
|
||||||
|
task_with_agent = Task(
|
||||||
|
description="Research a topic",
|
||||||
|
expected_output="Research results",
|
||||||
|
agent=researcher,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create an initial set of tools
|
||||||
|
from crewai.tools.base_tool import BaseTool
|
||||||
|
|
||||||
|
class TestTool(BaseTool):
|
||||||
|
name: str = "Test Tool"
|
||||||
|
description: str = "A test tool"
|
||||||
|
|
||||||
|
def _run(self) -> str:
|
||||||
|
return "Tool executed"
|
||||||
|
|
||||||
|
initial_tools = [TestTool()]
|
||||||
|
|
||||||
|
# Test _update_manager_tools with a task that has an agent
|
||||||
|
updated_tools = crew._update_manager_tools(task_with_agent, initial_tools)
|
||||||
|
|
||||||
|
# Verify that delegation tools for the task's agent were added
|
||||||
|
assert len(updated_tools) > len(initial_tools)
|
||||||
|
assert any(
|
||||||
|
f"Delegate a specific task to one of the following coworkers: {researcher.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in updated_tools
|
||||||
|
)
|
||||||
|
assert any(
|
||||||
|
f"Ask a specific question to one of the following coworkers: {researcher.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in updated_tools
|
||||||
|
)
|
||||||
|
|
||||||
|
# Case 2: Task without an assigned agent
|
||||||
|
task_without_agent = Task(
|
||||||
|
description="General task",
|
||||||
|
expected_output="Task completed",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test _update_manager_tools with a task that doesn't have an agent
|
||||||
|
updated_tools = crew._update_manager_tools(task_without_agent, initial_tools)
|
||||||
|
|
||||||
|
# Verify that delegation tools for all agents were added
|
||||||
|
assert len(updated_tools) > len(initial_tools)
|
||||||
|
assert any(
|
||||||
|
f"Delegate a specific task to one of the following coworkers: {researcher.role}, {writer.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in updated_tools
|
||||||
|
)
|
||||||
|
assert any(
|
||||||
|
f"Ask a specific question to one of the following coworkers: {researcher.role}, {writer.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in updated_tools
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.vcr(filter_headers=["authorization"])
|
||||||
|
def test_manager_tools_during_task_execution():
|
||||||
|
"""Test that manager tools are correctly added during task execution in a hierarchical process."""
|
||||||
|
# Create agents
|
||||||
|
researcher = Agent(
|
||||||
|
role="Researcher",
|
||||||
|
goal="Research information",
|
||||||
|
backstory="You're an expert researcher",
|
||||||
|
)
|
||||||
|
|
||||||
|
writer = Agent(
|
||||||
|
role="Writer",
|
||||||
|
goal="Write content",
|
||||||
|
backstory="You're an expert writer",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create tasks
|
||||||
|
task_with_agent = Task(
|
||||||
|
description="Research a topic",
|
||||||
|
expected_output="Research results",
|
||||||
|
agent=researcher,
|
||||||
|
)
|
||||||
|
|
||||||
|
task_without_agent = Task(
|
||||||
|
description="General task",
|
||||||
|
expected_output="Task completed",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a crew with hierarchical process
|
||||||
|
crew_with_agent_task = Crew(
|
||||||
|
agents=[researcher, writer],
|
||||||
|
tasks=[task_with_agent],
|
||||||
|
process=Process.hierarchical,
|
||||||
|
manager_llm="gpt-4o",
|
||||||
|
)
|
||||||
|
|
||||||
|
crew_without_agent_task = Crew(
|
||||||
|
agents=[researcher, writer],
|
||||||
|
tasks=[task_without_agent],
|
||||||
|
process=Process.hierarchical,
|
||||||
|
manager_llm="gpt-4o",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mock task execution to capture the tools
|
||||||
|
mock_task_output = TaskOutput(
|
||||||
|
description="Mock description", raw="mocked output", agent="mocked agent"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test case 1: Task with an assigned agent
|
||||||
|
with patch.object(
|
||||||
|
Task, "execute_sync", return_value=mock_task_output
|
||||||
|
) as mock_execute_sync:
|
||||||
|
# Set the output attribute to avoid None errors
|
||||||
|
task_with_agent.output = mock_task_output
|
||||||
|
|
||||||
|
# Execute the crew
|
||||||
|
crew_with_agent_task.kickoff()
|
||||||
|
|
||||||
|
# Verify execute_sync was called
|
||||||
|
mock_execute_sync.assert_called_once()
|
||||||
|
|
||||||
|
# Get the tools argument from the call
|
||||||
|
_, kwargs = mock_execute_sync.call_args
|
||||||
|
tools = kwargs["tools"]
|
||||||
|
|
||||||
|
# Verify that delegation tools for the task's agent were added
|
||||||
|
assert any(
|
||||||
|
f"Delegate a specific task to one of the following coworkers: {researcher.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in tools
|
||||||
|
)
|
||||||
|
assert any(
|
||||||
|
f"Ask a specific question to one of the following coworkers: {researcher.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in tools
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test case 2: Task without an assigned agent
|
||||||
|
with patch.object(
|
||||||
|
Task, "execute_sync", return_value=mock_task_output
|
||||||
|
) as mock_execute_sync:
|
||||||
|
# Set the output attribute to avoid None errors
|
||||||
|
task_without_agent.output = mock_task_output
|
||||||
|
|
||||||
|
# Execute the crew
|
||||||
|
crew_without_agent_task.kickoff()
|
||||||
|
|
||||||
|
# Verify execute_sync was called
|
||||||
|
mock_execute_sync.assert_called_once()
|
||||||
|
|
||||||
|
# Get the tools argument from the call
|
||||||
|
_, kwargs = mock_execute_sync.call_args
|
||||||
|
tools = kwargs["tools"]
|
||||||
|
|
||||||
|
# Verify that delegation tools for all agents were added
|
||||||
|
assert any(
|
||||||
|
f"Delegate a specific task to one of the following coworkers: {researcher.role}, {writer.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in tools
|
||||||
|
)
|
||||||
|
assert any(
|
||||||
|
f"Ask a specific question to one of the following coworkers: {researcher.role}, {writer.role}"
|
||||||
|
in tool.description
|
||||||
|
for tool in tools
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user