Fix: Set crew attribute on planning agent to prevent EventBus errors

- Added crew parameter to CrewPlanner.__init__() to accept crew reference
- Modified _create_planning_agent() to set crew attribute on planning agent
- Updated Crew._handle_crew_planning() to pass crew reference to CrewPlanner
- Added test to verify planning agent has crew attribute set
- Renamed test class from InternalCrewPlanner to TestCrewPlanner for pytest compatibility

Fixes #3782

Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
Devin AI
2025-10-23 09:59:40 +00:00
parent 9728388ea7
commit edfbec4740
3 changed files with 35 additions and 4 deletions

View File

@@ -779,7 +779,7 @@ class Crew(FlowTrackable, BaseModel):
"""Handles the Crew planning."""
self._logger.log("info", "Planning the crew execution")
result = CrewPlanner(
tasks=self.tasks, planning_agent_llm=self.planning_llm
tasks=self.tasks, planning_agent_llm=self.planning_llm, crew=self
)._handle_crew_planning()
for task, step_plan in zip(

View File

@@ -37,19 +37,25 @@ class CrewPlanner:
Attributes:
tasks: List of tasks to be planned.
planning_agent_llm: Optional LLM model for the planning agent.
crew: Optional reference to the crew instance.
"""
def __init__(
self, tasks: list[Task], planning_agent_llm: str | BaseLLM | None = None
self,
tasks: list[Task],
planning_agent_llm: str | BaseLLM | None = None,
crew: "Any" = None,
) -> None:
"""Initialize CrewPlanner with tasks and optional planning agent LLM.
Args:
tasks: List of tasks to be planned.
planning_agent_llm: Optional LLM model for the planning agent. Defaults to None.
crew: Optional reference to the crew instance. Defaults to None.
"""
self.tasks = tasks
self.planning_agent_llm = planning_agent_llm or "gpt-4o-mini"
self.crew = crew
def _handle_crew_planning(self) -> PlannerTaskPydanticOutput:
"""Handles the Crew planning by creating detailed step-by-step plans for each task.
@@ -80,7 +86,7 @@ class CrewPlanner:
Returns:
An Agent instance configured for planning tasks.
"""
return Agent(
planning_agent = Agent(
role="Task Execution Planner",
goal=(
"Your goal is to create an extremely detailed, step-by-step plan based on the tasks and tools "
@@ -89,6 +95,9 @@ class CrewPlanner:
backstory="Planner agent for crew planning",
llm=self.planning_agent_llm,
)
if self.crew:
planning_agent.crew = self.crew
return planning_agent
@staticmethod
def _create_planner_task(planning_agent: Agent, tasks_summary: str) -> Task:

View File

@@ -13,7 +13,7 @@ from crewai.utilities.planning_handler import (
)
class InternalCrewPlanner:
class TestCrewPlanner:
@pytest.fixture
def crew_planner(self):
tasks = [
@@ -177,3 +177,25 @@ class InternalCrewPlanner:
crew_planner_different_llm.tasks
)
execute.assert_called_once()
def test_planning_agent_has_crew_attribute(self):
"""Test that planning agent has crew attribute set to avoid EventBus errors."""
from crewai.crew import Crew
# Create a crew with planning enabled
agent = Agent(role="Test Agent", goal="Test Goal", backstory="Test Backstory")
task = Task(
description="Test task",
expected_output="Test output",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task], planning=True)
planner = CrewPlanner(tasks=[task], planning_agent_llm="gpt-4o-mini", crew=crew)
planning_agent = planner._create_planning_agent()
# Verify the planning agent has crew attribute set
assert planning_agent.crew is not None
assert planning_agent.crew == crew
# Verify that accessing agent.crew.key doesn't raise an error
assert planning_agent.crew.key is not None