Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/crewai/src/crewai/crew.py
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,7 @@ def _update_manager_tools(
) -> list[BaseTool]:
if self.manager_agent:
if task.agent:
tools = self._inject_delegation_tools(tools, task.agent, [task.agent])
tools = self._inject_delegation_tools(tools, task.agent, self.agents)
else:
tools = self._inject_delegation_tools(
tools, self.manager_agent, self.agents
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,4 +517,103 @@ interactions:
- req_8a1b3f7a05a8699dfb93ea93be9788f9
http_version: HTTP/1.1
status_code: 200
- request:
body: '{"trace_id": "2a3bfdec-b59a-4ab1-8be2-3c07dd2457d9", "execution_type":
"crew", "user_identifier": null, "execution_context": {"crew_fingerprint": null,
"crew_name": "crew", "flow_name": null, "crewai_version": "1.4.1", "privacy_level":
"standard"}, "execution_metadata": {"expected_duration_estimate": 300, "agent_count":
0, "task_count": 0, "flow_method_count": 0, "execution_started_at": "2025-11-11T11:04:11.109473+00:00"},
"ephemeral_trace_id": "2a3bfdec-b59a-4ab1-8be2-3c07dd2457d9"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '488'
Content-Type:
- application/json
User-Agent:
- CrewAI-CLI/1.4.1
X-Crewai-Version:
- 1.4.1
method: POST
uri: https://app.crewai.com/crewai_plus/api/v1/tracing/ephemeral/batches
response:
body:
string: '{"id":"ed5f3778-b549-4c32-b7b4-1c43eedb314e","ephemeral_trace_id":"2a3bfdec-b59a-4ab1-8be2-3c07dd2457d9","execution_type":"crew","crew_name":"crew","flow_name":null,"status":"running","duration_ms":null,"crewai_version":"1.4.1","total_events":0,"execution_context":{"crew_fingerprint":null,"crew_name":"crew","flow_name":null,"crewai_version":"1.4.1","privacy_level":"standard"},"created_at":"2025-11-11T11:04:11.451Z","updated_at":"2025-11-11T11:04:11.451Z","access_code":"TRACE-72181a84cb","user_identifier":null}'
headers:
Connection:
- keep-alive
Content-Length:
- '515'
Content-Type:
- application/json; charset=utf-8
Date:
- Tue, 11 Nov 2025 11:04:11 GMT
cache-control:
- no-store
content-security-policy:
- 'default-src ''self'' *.app.crewai.com app.crewai.com; script-src ''self''
''unsafe-inline'' *.app.crewai.com app.crewai.com https://cdn.jsdelivr.net/npm/apexcharts
https://www.gstatic.com https://run.pstmn.io https://apis.google.com https://apis.google.com/js/api.js
https://accounts.google.com https://accounts.google.com/gsi/client https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css.map
https://*.google.com https://docs.google.com https://slides.google.com https://js.hs-scripts.com
https://js.sentry-cdn.com https://browser.sentry-cdn.com https://www.googletagmanager.com
https://js-na1.hs-scripts.com https://js.hubspot.com http://js-na1.hs-scripts.com
https://bat.bing.com https://cdn.amplitude.com https://cdn.segment.com https://d1d3n03t5zntha.cloudfront.net/
https://descriptusercontent.com https://edge.fullstory.com https://googleads.g.doubleclick.net
https://js.hs-analytics.net https://js.hs-banner.com https://js.hsadspixel.net
https://js.hscollectedforms.net https://js.usemessages.com https://snap.licdn.com
https://static.cloudflareinsights.com https://static.reo.dev https://www.google-analytics.com
https://share.descript.com/; style-src ''self'' ''unsafe-inline'' *.app.crewai.com
app.crewai.com https://cdn.jsdelivr.net/npm/apexcharts; img-src ''self'' data:
*.app.crewai.com app.crewai.com https://zeus.tools.crewai.com https://dashboard.tools.crewai.com
https://cdn.jsdelivr.net https://forms.hsforms.com https://track.hubspot.com
https://px.ads.linkedin.com https://px4.ads.linkedin.com https://www.google.com
https://www.google.com.br; font-src ''self'' data: *.app.crewai.com app.crewai.com;
connect-src ''self'' *.app.crewai.com app.crewai.com https://zeus.tools.crewai.com
https://connect.useparagon.com/ https://zeus.useparagon.com/* https://*.useparagon.com/*
https://run.pstmn.io https://connect.tools.crewai.com/ https://*.sentry.io
https://www.google-analytics.com https://edge.fullstory.com https://rs.fullstory.com
https://api.hubspot.com https://forms.hscollectedforms.net https://api.hubapi.com
https://px.ads.linkedin.com https://px4.ads.linkedin.com https://google.com/pagead/form-data/16713662509
https://google.com/ccm/form-data/16713662509 https://www.google.com/ccm/collect
https://worker-actionkit.tools.crewai.com https://api.reo.dev; frame-src ''self''
*.app.crewai.com app.crewai.com https://connect.useparagon.com/ https://zeus.tools.crewai.com
https://zeus.useparagon.com/* https://connect.tools.crewai.com/ https://docs.google.com
https://drive.google.com https://slides.google.com https://accounts.google.com
https://*.google.com https://app.hubspot.com/ https://td.doubleclick.net https://www.googletagmanager.com/
https://www.youtube.com https://share.descript.com'
etag:
- W/"0108bfa1b1646d9b56d1c8bfafae33c3"
expires:
- '0'
permissions-policy:
- camera=(), microphone=(self), geolocation=()
pragma:
- no-cache
referrer-policy:
- strict-origin-when-cross-origin
strict-transport-security:
- max-age=63072000; includeSubDomains
vary:
- Accept
x-content-type-options:
- nosniff
x-frame-options:
- SAMEORIGIN
x-permitted-cross-domain-policies:
- none
x-request-id:
- 2bc7f5a5-7082-4864-8f9e-dafe6bff32b5
x-runtime:
- '0.070395'
x-xss-protection:
- 1; mode=block
status:
code: 201
message: Created
version: 1
194 changes: 191 additions & 3 deletions lib/crewai/tests/test_crew.py
Original file line number Diff line number Diff line change
Expand Up @@ -1864,7 +1864,10 @@ def test_hierarchical_crew_creation_tasks_with_agents(researcher, writer):
@pytest.mark.vcr(filter_headers=["authorization"])
def test_hierarchical_crew_creation_tasks_with_async_execution(researcher, writer, ceo):
"""
Tests that async tasks in hierarchical crews are handled correctly with proper delegation tools
Tests that async tasks in hierarchical crews are handled correctly with proper delegation tools.

After fix for issue #3887, the manager should be able to delegate to ALL crew agents,
not just the task's assigned agent.
"""
task = Task(
description="Write one amazing paragraph about AI.",
Expand Down Expand Up @@ -1906,13 +1909,15 @@ def test_hierarchical_crew_creation_tasks_with_async_execution(researcher, write

# Verify the delegation tools were passed correctly
assert len(tools) == 2

# After fix for issue #3887, manager can delegate to ALL crew agents
assert any(
"Delegate a specific task to one of the following coworkers: Senior Writer\n"
"Delegate a specific task to one of the following coworkers: Senior Writer, Researcher, CEO"
in tool.description
for tool in tools
)
assert any(
"Ask a specific question to one of the following coworkers: Senior Writer\n"
"Ask a specific question to one of the following coworkers: Senior Writer, Researcher, CEO"
in tool.description
for tool in tools
)
Expand Down Expand Up @@ -4772,3 +4777,186 @@ def test_ensure_exchanged_messages_are_propagated_to_external_memory():
assert "Researcher" in messages[0]["content"]
assert messages[1]["role"] == "user"
assert "Research a topic to teach a kid aged 6 about math" in messages[1]["content"]


def test_hierarchical_manager_can_delegate_to_crew_agents_issue_3887():
"""
Test that reproduces and fixes issue #3887.

When using hierarchical process with a custom manager_agent and tasks assigned
to that manager, the manager should be able to delegate to all agents in the
crew's agents list, not just the task's assigned agent.

Bug scenario from issue #3887:
- Crew has agents=[planner]
- manager_agent=coordinator
- Task is assigned to coordinator (the manager)
- Manager tries to delegate to "planner"
- Before fix: Error "coworker mentioned not found, it must be one of the following options: - coordinator"
- After fix: Manager can successfully delegate to "planner"
"""
# Create agents matching the bug report scenario
coordinator = Agent(
role="Coordinator",
goal="Coordinate the team to complete tasks",
backstory="You're a coordinator who delegates work to team members.",
allow_delegation=True,
)

planner = Agent(
role="Planner",
goal="Create technical plans",
backstory="You're a planner who creates detailed technical plans.",
allow_delegation=False,
)

# Create a task assigned to the coordinator (manager agent)
task = Task(
description="Create a technical plan for the project",
expected_output="A detailed technical plan",
agent=coordinator,
)

# Create hierarchical crew with custom manager_agent
crew = Crew(
agents=[planner], # Only planner in crew agents
tasks=[task],
process=Process.hierarchical,
manager_agent=coordinator, # Coordinator is the manager
)

mock_task_output = TaskOutput(
description="Mock description",
raw="mocked output",
agent="mocked agent",
messages=[]
)
task.output = mock_task_output

with patch.object(
Task, "execute_sync", return_value=mock_task_output
) as mock_execute_sync:
crew.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 the delegation tools were passed correctly
# The manager should be able to delegate to "planner" (from crew.agents)
assert len(tools) == 2

# Check that the delegation tool includes "Planner" as a coworker
delegation_tool = next(
(tool for tool in tools if "Delegate" in tool.name), None
)
assert delegation_tool is not None
assert "Planner" in delegation_tool.description, (
f"Expected 'Planner' in delegation tool description, "
f"but got: {delegation_tool.description}"
)

# Verify the delegation tool has the planner agent in its agents list
assert hasattr(delegation_tool, "agents")
agent_roles = [agent.role for agent in delegation_tool.agents]
assert "Planner" in agent_roles, (
f"Expected 'Planner' in delegation tool agents, "
f"but got: {agent_roles}"
)

# Verify that "Coordinator" is NOT in the coworkers list
# (manager should not delegate to itself)
assert "Coordinator" not in delegation_tool.description or (
"Coordinator" in delegation_tool.description and "Planner" in delegation_tool.description
), "Manager should be able to delegate to crew agents"


def test_hierarchical_manager_can_delegate_to_multiple_crew_agents():
"""
Test that the manager can delegate to multiple crew agents.

This extends the fix for issue #3887 to ensure it works with multiple agents.
"""
# Create manager agent
manager = Agent(
role="Manager",
goal="Manage the team",
backstory="You're a manager who coordinates team members.",
allow_delegation=True,
)

# Create multiple crew agents
researcher = Agent(
role="Researcher",
goal="Research topics",
backstory="You're a researcher.",
allow_delegation=False,
)

writer = Agent(
role="Writer",
goal="Write content",
backstory="You're a writer.",
allow_delegation=False,
)

analyst = Agent(
role="Analyst",
goal="Analyze data",
backstory="You're an analyst.",
allow_delegation=False,
)

# Create a task assigned to the manager
task = Task(
description="Coordinate the team to complete the project",
expected_output="Project completed",
agent=manager,
)

# Create hierarchical crew with multiple agents
crew = Crew(
agents=[researcher, writer, analyst],
tasks=[task],
process=Process.hierarchical,
manager_agent=manager,
)

mock_task_output = TaskOutput(
description="Mock description",
raw="mocked output",
agent="mocked agent",
messages=[]
)
task.output = mock_task_output

with patch.object(
Task, "execute_sync", return_value=mock_task_output
) as mock_execute_sync:
crew.kickoff()

# Get the tools argument from the call
_, kwargs = mock_execute_sync.call_args
tools = kwargs["tools"]

# Find the delegation tool
delegation_tool = next(
(tool for tool in tools if "Delegate" in tool.name), None
)
assert delegation_tool is not None

# Verify all crew agents are available for delegation
assert hasattr(delegation_tool, "agents")
agent_roles = [agent.role for agent in delegation_tool.agents]

assert "Researcher" in agent_roles
assert "Writer" in agent_roles
assert "Analyst" in agent_roles

# Verify all agents are mentioned in the description
assert "Researcher" in delegation_tool.description
assert "Writer" in delegation_tool.description
assert "Analyst" in delegation_tool.description