From 685f7b9af190fe1754e1c0f3e23943b744603a05 Mon Sep 17 00:00:00 2001 From: Vini Brasil Date: Tue, 13 Jan 2026 18:40:22 +0100 Subject: [PATCH] Increase frame inspection depth to detect `parent_flow` (#4231) This commit fixes a bug where `parent_flow` was not being set because the maximum depth was not sufficient to search for an instance of `Flow` in the current call stack frame during Flow instantiation. --- lib/crewai/src/crewai/flow/flow_trackable.py | 5 +- lib/crewai/tests/test_crew.py | 65 ++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lib/crewai/src/crewai/flow/flow_trackable.py b/lib/crewai/src/crewai/flow/flow_trackable.py index eee558523..974895bc1 100644 --- a/lib/crewai/src/crewai/flow/flow_trackable.py +++ b/lib/crewai/src/crewai/flow/flow_trackable.py @@ -1,4 +1,5 @@ import inspect +from typing import Any from pydantic import BaseModel, Field, InstanceOf, model_validator from typing_extensions import Self @@ -14,14 +15,14 @@ class FlowTrackable(BaseModel): inspecting the call stack. """ - parent_flow: InstanceOf[Flow] | None = Field( + parent_flow: InstanceOf[Flow[Any]] | None = Field( default=None, description="The parent flow of the instance, if it was created inside a flow.", ) @model_validator(mode="after") def _set_parent_flow(self) -> Self: - max_depth = 5 + max_depth = 8 frame = inspect.currentframe() try: diff --git a/lib/crewai/tests/test_crew.py b/lib/crewai/tests/test_crew.py index 4f485f207..0aac88653 100644 --- a/lib/crewai/tests/test_crew.py +++ b/lib/crewai/tests/test_crew.py @@ -4500,6 +4500,71 @@ def test_crew_copy_with_memory(): pytest.fail(f"Copying crew raised an unexpected exception: {e}") +def test_sets_parent_flow_when_using_crewbase_pattern_inside_flow(): + @CrewBase + class TestCrew: + agents_config = None + tasks_config = None + + agents: list[BaseAgent] + tasks: list[Task] + + @agent + def researcher(self) -> Agent: + return Agent( + role="Researcher", + goal="Research things", + backstory="Expert researcher", + ) + + @agent + def writer_agent(self) -> Agent: + return Agent( + role="Writer", + goal="Write things", + backstory="Expert writer", + ) + + @task + def research_task(self) -> Task: + return Task( + description="Test task for researcher", + expected_output="output", + agent=self.researcher(), + ) + + @task + def write_task(self) -> Task: + return Task( + description="Test task for writer", + expected_output="output", + agent=self.writer_agent(), + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + ) + + captured_crew = None + + class MyFlow(Flow): + @start() + def start_method(self): + nonlocal captured_crew + captured_crew = TestCrew().crew() + return captured_crew + + flow = MyFlow() + flow.kickoff() + + assert captured_crew is not None + assert captured_crew.parent_flow is flow + + def test_sets_parent_flow_when_outside_flow(researcher, writer): crew = Crew( agents=[researcher, writer],