From a29977f4f6ebcef8455dc78d0ccb5c57eea9a7ce Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Tue, 28 Apr 2026 20:53:39 +0800 Subject: [PATCH] fix(crew): bind task-only agents to crew so multimodal input_files reach the LLM --- lib/crewai/src/crewai/crews/utils.py | 9 +++++++- lib/crewai/tests/test_crew.py | 31 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/crewai/src/crewai/crews/utils.py b/lib/crewai/src/crewai/crews/utils.py index e85a48b05..70d624f6f 100644 --- a/lib/crewai/src/crewai/crews/utils.py +++ b/lib/crewai/src/crewai/crews/utils.py @@ -354,9 +354,16 @@ def prepare_kickoff( crew._set_tasks_callbacks() crew._set_allow_crewai_trigger_context_for_first_task() + agents_to_setup: list[BaseAgent] = list(crew.agents) + seen_agent_ids: set[int] = {id(agent) for agent in agents_to_setup} + for task in crew.tasks: + if task.agent is not None and id(task.agent) not in seen_agent_ids: + agents_to_setup.append(task.agent) + seen_agent_ids.add(id(task.agent)) + setup_agents( crew, - crew.agents, + agents_to_setup, crew.embedder, crew.function_calling_llm, crew.step_callback, diff --git a/lib/crewai/tests/test_crew.py b/lib/crewai/tests/test_crew.py index c3b8127a9..071395c91 100644 --- a/lib/crewai/tests/test_crew.py +++ b/lib/crewai/tests/test_crew.py @@ -4798,6 +4798,37 @@ def test_crew_kickoff_started_emits_display_name( assert captured == [expected] +def test_prepare_kickoff_binds_task_only_agent_to_crew(): + """Agents referenced only via task.agent must get .crew set during prepare_kickoff. + + Regression for crewAIInc/crewAI#5534: when Crew is built without + agents=[...], multimodal input_files were silently dropped because the + agent's .crew attribute was never assigned, gating file lookup off in + Task and CrewAgentExecutor. + """ + from crewai.crews.utils import prepare_kickoff + + task_only_agent = Agent( + role="Solo", + goal="Describe inputs", + backstory="Solo agent assigned only via task.agent", + allow_delegation=False, + ) + task = Task( + description="Describe the input.", + expected_output="A description.", + agent=task_only_agent, + ) + crew = Crew(tasks=[task]) + + assert task_only_agent.crew is None + assert crew.agents == [] + + prepare_kickoff(crew, inputs=None) + + assert task_only_agent.crew is crew + + @pytest.mark.vcr() def test_memory_remember_receives_task_content(): """With memory=True, extract_memories receives raw content with task, agent, expected output, and result."""