The TurnTrackingObserver monitors and tracks conversational turns in your Pipecat pipeline, providing events when turns start and end. It intelligently identifies when a user-bot interaction cycle begins and completes.

Turn Lifecycle

A turn represents a complete user-bot interaction cycle:

  1. Start: When the user starts speaking (or pipeline starts for first turn)
  2. Processing: User speaks, bot processes and responds
  3. End: After the bot finishes speaking and either:
    • The user starts speaking again
    • A timeout period elapses with no further activity

Events

The observer emits two main events:

  • on_turn_started: When a new turn begins
    • Parameters: turn_number (int)
  • on_turn_ended: When a turn completes
    • Parameters: turn_number (int), duration (float, in seconds), was_interrupted (bool)

Usage

The observer is automatically created when you initialize a PipelineTask with enable_turn_tracking=True (which is the default):

task = PipelineTask(
    pipeline,
    params=PipelineParams(allow_interruptions=True),
    # Turn tracking is enabled by default
)

# Access the observer
turn_observer = task.turn_tracking_observer

# Register event handlers
@turn_observer.event_handler("on_turn_started")
async def on_turn_started(observer, turn_number):
    logger.info(f"Turn {turn_number} started")

@turn_observer.event_handler("on_turn_ended")
async def on_turn_ended(observer, turn_number, duration, was_interrupted):
    status = "interrupted" if was_interrupted else "completed"
    logger.info(f"Turn {turn_number} {status} in {duration:.2f}s")

Configuration

You can configure the observer’s behavior when creating a PipelineTask:

from pipecat.observers.turn_tracking_observer import TurnTrackingObserver

# Create a custom observer instance
custom_turn_tracker = TurnTrackingObserver(
    turn_end_timeout_secs=3.5,     # Turn end timeout (default: 2.5)
)

# Add it as a regular observer
task = PipelineTask(
    pipeline,
    observers=[custom_turn_tracker],
    # Disable the default one if adding your own
    enable_turn_tracking=False,
)

Interruptions

The observer automatically detects interruptions when the user starts speaking while the bot is still speaking. In this case:

  • The current turn is marked as interrupted (was_interrupted=True)
  • A new turn begins immediately

How It Works

The observer monitors specific frame types to track conversation flow:

  • StartFrame: Initiates the first turn
  • UserStartedSpeakingFrame: Starts user speech or triggers a new turn
  • BotStartedSpeakingFrame: Marks bot speech beginning
  • BotStoppedSpeakingFrame: Starts the turn end timeout

After a bot stops speaking, the observer waits for the configured timeout period. If no further bot speech occurs, the turn ends; otherwise, it continues as part of the same turn.

Use Cases

  • Analytics: Measure turn durations, interruption rates, and conversation flow
  • Logging: Record turn-based logs for diagnostics and analysis
  • Visualization: Show turn-based conversation timelines in UIs
  • Tracing: Group spans and metrics by conversation turns