From 46bb7aa79e6d852a926bc8a6c18e1bb852158c03 Mon Sep 17 00:00:00 2001 From: Tiago Freire Date: Mon, 23 Mar 2026 23:51:45 -0300 Subject: [PATCH] fix: resolve first-time trace prompt not appearing for Flows and standalone Crews Two places had the same race condition between FlowStartedEvent / CrewKickoffStartedEvent handlers and DefaultEnvEvent in the thread pool. Commit 929d756ae introduced env-detection events (DefaultEnvEvent etc.) dispatched through _handle_action_event, which has a fallback that calls initialize_batch() without claiming batch ownership. get_env_context() is called at the very top of both Flow.kickoff() and Crew.kickoff(), so DefaultEnvEvent can fire and win the thread pool race before the context event handler runs. When that happened, is_batch_initialized() returned True and _initialize_flow_batch / _initialize_crew_batch were skipped, leaving batch_owner_type=None. The completion checks (batch_owner_type == "flow" / "crew") then failed silently and the first-time trace prompt never appeared. Fix: remove the is_batch_initialized() guard from on_flow_started and replace it with an unconditional call to _initialize_flow_batch. initialize_batch() is already idempotent (lock-guarded early exit), so batch_owner_type="flow" is set regardless of which event initialized the batch first. For on_crew_started, apply the same pattern but guard against overriding a parent flow's ownership: call _initialize_crew_batch unconditionally unless batch_owner_type is already "flow". Also suppress the "Tracing is disabled" panel in ConsoleFormatter when the first-time handler is active, preventing a confusing mid-flow message before the trace prompt appears at the end. --- .../events/listeners/tracing/trace_listener.py | 14 +++++++++++--- .../src/crewai/events/utils/console_formatter.py | 8 ++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py b/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py index b86d77aa1..2feaa18d4 100644 --- a/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py +++ b/lib/crewai/src/crewai/events/listeners/tracing/trace_listener.py @@ -235,8 +235,11 @@ class TraceCollectionListener(BaseEventListener): @event_bus.on(FlowStartedEvent) def on_flow_started(source: Any, event: FlowStartedEvent) -> None: - if not self.batch_manager.is_batch_initialized(): - self._initialize_flow_batch(source, event) + # Always call _initialize_flow_batch to claim ownership. + # If batch was already initialized by a concurrent action event + # (race condition), initialize_batch() returns early but + # batch_owner_type is still correctly set to "flow". + self._initialize_flow_batch(source, event) self._handle_trace_event("flow_started", source, event) @event_bus.on(MethodExecutionStartedEvent) @@ -266,7 +269,12 @@ class TraceCollectionListener(BaseEventListener): @event_bus.on(CrewKickoffStartedEvent) def on_crew_started(source: Any, event: CrewKickoffStartedEvent) -> None: - if not self.batch_manager.is_batch_initialized(): + if self.batch_manager.batch_owner_type != "flow": + # Always call _initialize_crew_batch to claim ownership. + # If batch was already initialized by a concurrent action event + # (race condition with DefaultEnvEvent), initialize_batch() returns + # early but batch_owner_type is still correctly set to "crew". + # Skip only when a parent flow already owns the batch. self._initialize_crew_batch(source, event) self._handle_trace_event("crew_kickoff_started", source, event) diff --git a/lib/crewai/src/crewai/events/utils/console_formatter.py b/lib/crewai/src/crewai/events/utils/console_formatter.py index 0984406e9..744d8365e 100644 --- a/lib/crewai/src/crewai/events/utils/console_formatter.py +++ b/lib/crewai/src/crewai/events/utils/console_formatter.py @@ -127,6 +127,9 @@ To update, run: uv sync --upgrade-package crewai""" def _show_tracing_disabled_message_if_needed(self) -> None: """Show tracing disabled message if tracing is not enabled.""" + from crewai.events.listeners.tracing.trace_listener import ( + TraceCollectionListener, + ) from crewai.events.listeners.tracing.utils import ( has_user_declined_tracing, is_tracing_enabled_in_context, @@ -136,6 +139,11 @@ To update, run: uv sync --upgrade-package crewai""" if should_suppress_tracing_messages(): return + # Don't show "disabled" message when the first-time handler will show + # the trace prompt after execution completes (avoids confusing mid-flow messages) + if TraceCollectionListener._instance and TraceCollectionListener._instance.first_time_handler.is_first_time: + return + if not is_tracing_enabled_in_context(): if has_user_declined_tracing(): message = """Info: Tracing is disabled.