diff --git a/lib/crewai/src/crewai/crew.py b/lib/crewai/src/crewai/crew.py index a8e88ce55..f72dc180d 100644 --- a/lib/crewai/src/crewai/crew.py +++ b/lib/crewai/src/crewai/crew.py @@ -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( diff --git a/lib/crewai/src/crewai/utilities/planning_handler.py b/lib/crewai/src/crewai/utilities/planning_handler.py index c76153020..949d08561 100644 --- a/lib/crewai/src/crewai/utilities/planning_handler.py +++ b/lib/crewai/src/crewai/utilities/planning_handler.py @@ -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: diff --git a/lib/crewai/tests/utilities/test_planning_handler.py b/lib/crewai/tests/utilities/test_planning_handler.py index 6e75e3626..c045fd67a 100644 --- a/lib/crewai/tests/utilities/test_planning_handler.py +++ b/lib/crewai/tests/utilities/test_planning_handler.py @@ -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