> ## Documentation Index
> Fetch the complete documentation index at: https://daily-mb-reorg-api-reference-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# User Turn Strategies

> Configure how user turns are detected and managed in conversations

## Overview

User turn strategies provide fine-grained control over how user speaking turns are detected in conversations. They determine when a user's turn starts (user begins speaking) and when it stops (user finishes speaking and expects a response).

By default, Pipecat uses a combination of VAD (Voice Activity Detection) and AI-powered turn detection:

* **Start**: VAD detection or transcription received
* **Stop**: AI-powered turn detection using `LocalSmartTurnAnalyzerV3`

You can customize this behavior by providing your own strategies for more sophisticated turn detection, such as requiring a minimum number of words before triggering a turn, or using AI-powered turn detection models.

## How It Works

1. **Turn Start Detection**: When any start strategy triggers, the user aggregator:
   * Marks the start of a user turn
   * Optionally emits `UserStartedSpeakingFrame`
   * Optionally emits an interruption frame (if the bot is speaking)

2. **During User Turn**: The aggregator collects transcriptions and audio frames.

3. **Turn Stop Detection**: When a stop strategy triggers, the user aggregator:
   * Marks the end of the user turn
   * Emits `UserStoppedSpeakingFrame`
   * Pushes the aggregated user message to the LLM context

4. **Timeout Handling**: If no stop strategy triggers within `user_turn_stop_timeout` seconds (default: 5.0), the turn is automatically ended.

## Configuration

User turn strategies are configured via `LLMUserAggregatorParams` when creating an `LLMContextAggregatorPair`:

```python theme={null}
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import (
    LLMContextAggregatorPair,
    LLMUserAggregatorParams,
)
from pipecat.turns.user_turn_strategies import UserTurnStrategies

context = LLMContext(messages)
user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=UserTurnStrategies(
            start=[...],  # List of start strategies
            stop=[...],   # List of stop strategies
        ),
    ),
)
```

## Start Strategies

Start strategies determine when a user's turn begins. Multiple strategies can be provided, and the first one to trigger will signal the start of a user turn.

### Base Parameters

All start strategies inherit these parameters:

<ParamField path="enable_interruptions" type="bool" default="True">
  If True, the user aggregator will emit an interruption frame when the user
  turn starts, allowing the user to interrupt the bot.
</ParamField>

<ParamField path="enable_user_speaking_frames" type="bool" default="True">
  If True, the user aggregator will emit frames indicating when the user starts
  speaking. Disable this if another component (e.g., an STT service) already
  generates these frames.
</ParamField>

### VADUserTurnStartStrategy

Triggers a user turn start based on Voice Activity Detection. This is the most responsive strategy, detecting speech as soon as the VAD indicates the user has started speaking.

```python theme={null}
from pipecat.turns.user_start import VADUserTurnStartStrategy

strategy = VADUserTurnStartStrategy()
```

### TranscriptionUserTurnStartStrategy

Triggers a user turn start when a transcription is received. This serves as a fallback for scenarios where VAD-based detection fails (e.g., when the user speaks very softly) but the STT service still produces transcriptions.

<ParamField path="use_interim" type="bool" default="True">
  Whether to trigger on interim (partial) transcription frames for earlier
  detection.
</ParamField>

```python theme={null}
from pipecat.turns.user_start import TranscriptionUserTurnStartStrategy

strategy = TranscriptionUserTurnStartStrategy(use_interim=True)
```

### MinWordsUserTurnStartStrategy

Requires the user to speak a minimum number of words before triggering a turn start. This is useful for preventing brief utterances like "okay" or "yeah" from triggering responses.

<ParamField path="min_words" type="int" required>
  Minimum number of spoken words required to trigger the start of a user turn.
</ParamField>

<ParamField path="use_interim" type="bool" default="True">
  Whether to consider interim transcription frames for earlier detection.
</ParamField>

```python theme={null}
from pipecat.turns.user_start import MinWordsUserTurnStartStrategy

# Require at least 3 words to start a turn
strategy = MinWordsUserTurnStartStrategy(min_words=3)
```

<Note>
  When the bot is not speaking, this strategy will trigger after just 1 word.
  The `min_words` threshold only applies when the bot is actively speaking,
  preventing short affirmations from interrupting the bot.
</Note>

### WakePhraseUserTurnStartStrategy

Requires a wake phrase to be detected before allowing interaction. This strategy blocks subsequent strategies until a wake phrase is detected in a transcription, then allows interaction for a configurable timeout period.

<ParamField path="phrases" type="List[str]" required>
  List of wake phrases to detect (e.g., `["hey pipecat", "ok pipecat"]`).
</ParamField>

<ParamField path="timeout" type="float" default="10.0">
  Inactivity timeout in seconds before returning to IDLE state. In timeout mode,
  the timer resets on activity. In single activation mode, acts as a keepalive
  window after wake phrase detection.
</ParamField>

<ParamField path="single_activation" type="bool" default="False">
  If True, the wake phrase is required before every turn. The strategy returns
  to IDLE after each turn completes.
</ParamField>

```python theme={null}
from pipecat.turns.user_start import WakePhraseUserTurnStartStrategy

# Timeout mode: wake phrase unlocks interaction for 10 seconds
strategy = WakePhraseUserTurnStartStrategy(
    phrases=["hey pipecat", "ok pipecat"],
    timeout=10.0,
)

# Single activation: wake phrase required before every turn
strategy = WakePhraseUserTurnStartStrategy(
    phrases=["hey pipecat"],
    single_activation=True,
)
```

**Event Handlers**

The strategy provides event handlers for wake phrase detection:

| Event                     | Signature                                  | Description                                                    |
| ------------------------- | ------------------------------------------ | -------------------------------------------------------------- |
| `on_wake_phrase_detected` | `async def handler(strategy, phrase: str)` | Called when a wake phrase is matched                           |
| `on_wake_phrase_timeout`  | `async def handler(strategy)`              | Called when the inactivity timeout expires (timeout mode only) |

```python theme={null}
@strategy.event_handler("on_wake_phrase_detected")
async def on_wake_phrase_detected(strategy, phrase):
    print(f"Wake phrase detected: {phrase}")

@strategy.event_handler("on_wake_phrase_timeout")
async def on_wake_phrase_timeout(strategy):
    print("Wake phrase timeout, returning to IDLE")
```

<Note>
  This strategy should be placed **first** in the start strategies list to
  properly gate all subsequent strategies. Use
  `default_user_turn_start_strategies()` to extend the defaults with wake
  phrase detection.
</Note>

### ExternalUserTurnStartStrategy

Delegates turn start detection to an external processor. This strategy listens for `UserStartedSpeakingFrame` frames emitted by other components in the pipeline (such as speech-to-speech services).

```python theme={null}
from pipecat.turns.user_start import ExternalUserTurnStartStrategy

strategy = ExternalUserTurnStartStrategy()
```

<Note>
  This strategy automatically sets `enable_interruptions=False` and
  `enable_user_speaking_frames=False` since these are expected to be handled by
  the external processor.
</Note>

## Stop Strategies

Stop strategies determine when a user's turn ends and the bot should respond.

### Base Parameters

All stop strategies inherit these parameters:

<ParamField path="enable_user_speaking_frames" type="bool" default="True">
  If True, the aggregator will emit frames indicating when the user stops
  speaking. Disable this if another component already generates these frames.
</ParamField>

### SpeechTimeoutUserTurnStopStrategy

Signals the end of a user turn when transcription is received and VAD indicates silence. Waits for a configurable timeout after VAD detects silence before finalizing the turn, and supports finalized transcripts for earlier triggering.

<ParamField path="user_speech_timeout" type="float" default="0.6">
  How long to wait (in seconds) after VAD detects silence before finalizing the
  user turn.
</ParamField>

```python theme={null}
from pipecat.turns.user_stop import SpeechTimeoutUserTurnStopStrategy

strategy = SpeechTimeoutUserTurnStopStrategy(user_speech_timeout=0.6)
```

<Note>
  Built-in STT P99 latency values assume `VADParams.stop_secs=0.2` (the
  recommended default). If you change `stop_secs`, the strategy will log a
  warning suggesting you re-run the [stt-benchmark](https://github.com/pipecat-ai/stt-benchmark)
  with your VAD settings and pass the measured TTFS P99 latency to your STT
  service constructor via `ttfs_p99_latency`. The strategy will also warn if
  `stop_secs >= STT p99 latency`, which collapses the STT wait timeout to 0s
  and may cause delayed turn detection.
</Note>

### TurnAnalyzerUserTurnStopStrategy

Uses an AI-powered turn detection model to determine when the user has finished speaking. This provides more intelligent end-of-turn detection that can understand conversational context.

<ParamField path="turn_analyzer" type="BaseTurnAnalyzer" required>
  The turn detection analyzer instance to use for end-of-turn detection.
</ParamField>

```python theme={null}
from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3
from pipecat.turns.user_stop import TurnAnalyzerUserTurnStopStrategy

strategy = TurnAnalyzerUserTurnStopStrategy(
    turn_analyzer=LocalSmartTurnAnalyzerV3()
)
```

<Tip>
  See the [Smart Turn
  Detection](/api-reference/server/utilities/turn-detection/smart-turn-overview) documentation for
  more information on available turn analyzers.
</Tip>

<Note>
  Built-in STT P99 latency values assume `VADParams.stop_secs=0.2` (the
  recommended default). If you change `stop_secs`, the strategy will log a
  warning suggesting you re-run the [stt-benchmark](https://github.com/pipecat-ai/stt-benchmark)
  with your VAD settings and pass the measured TTFS P99 latency to your STT
  service constructor via `ttfs_p99_latency`. The strategy will also warn if
  `stop_secs >= STT p99 latency`, which collapses the STT wait timeout to 0s
  and may cause delayed turn detection.
</Note>

### ExternalUserTurnStopStrategy

Delegates turn stop detection to an external processor. This strategy listens for `UserStoppedSpeakingFrame` frames emitted by other components in the pipeline.

<ParamField path="timeout" type="float" default="0.5">
  A short delay in seconds used to handle consecutive or slightly delayed
  transcriptions.
</ParamField>

```python theme={null}
from pipecat.turns.user_stop import ExternalUserTurnStopStrategy

strategy = ExternalUserTurnStopStrategy()
```

## Helper Functions

Pipecat provides helper functions to compose custom strategy lists that extend the defaults.

### default\_user\_turn\_start\_strategies()

Returns the default user turn start strategies: `[VADUserTurnStartStrategy, TranscriptionUserTurnStartStrategy]`.

Useful when building a custom strategy list that extends the defaults, such as adding wake phrase detection before the standard strategies.

```python theme={null}
from pipecat.turns.user_start import WakePhraseUserTurnStartStrategy
from pipecat.turns.user_turn_strategies import default_user_turn_start_strategies

# Add wake phrase detection before the defaults
start_strategies = [
    WakePhraseUserTurnStartStrategy(phrases=["hey pipecat"]),
    *default_user_turn_start_strategies(),
]
```

### default\_user\_turn\_stop\_strategies()

Returns the default user turn stop strategies: `[TurnAnalyzerUserTurnStopStrategy(LocalSmartTurnAnalyzerV3)]`.

Useful when building a custom strategy list that extends or replaces the defaults.

```python theme={null}
from pipecat.turns.user_turn_strategies import default_user_turn_stop_strategies

# Use the defaults
stop_strategies = default_user_turn_stop_strategies()
```

## UserTurnStrategies

Container for configuring user turn start and stop strategies.

<ParamField path="start" type="List[BaseUserTurnStartStrategy]" default="[VADUser...(), TranscriptionUser...()]">
  List of strategies used to detect when the user starts speaking. The first
  strategy to trigger will signal the start of the user's turn.
</ParamField>

<ParamField path="stop" type="List[BaseUserTurnStopStrategy]" default="[TurnAnalyzerUserTurnStopStrategy(turn_analyzer=LocalSmartTurnAnalyzerV3())]">
  List of strategies used to detect when the user stops speaking and expects a
  response. Defaults to AI-powered turn detection using
  `LocalSmartTurnAnalyzerV3`.
</ParamField>

## ExternalUserTurnStrategies

A convenience class that preconfigures `UserTurnStrategies` with external strategies for both start and stop detection. Use this when an external processor (such as a speech-to-speech service) controls turn management.

```python theme={null}
from pipecat.turns.user_turn_strategies import ExternalUserTurnStrategies

user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=ExternalUserTurnStrategies(),
    ),
)
```

## Usage Examples

### Default Behavior

The default configuration uses VAD for turn start detection and AI-powered Smart Turn for turn end detection:

```python theme={null}
from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3
from pipecat.turns.user_turn_strategies import UserTurnStrategies

# This is equivalent to the default behavior
strategies = UserTurnStrategies(
    start=[VADUserTurnStartStrategy(), TranscriptionUserTurnStartStrategy()],
    stop=[TurnAnalyzerUserTurnStopStrategy(turn_analyzer=LocalSmartTurnAnalyzerV3())],
)
```

### Minimum Words for Interruption

Require users to speak at least 3 words before they can interrupt the bot:

```python theme={null}
from pipecat.turns.user_start import MinWordsUserTurnStartStrategy
from pipecat.turns.user_stop import SpeechTimeoutUserTurnStopStrategy
from pipecat.turns.user_turn_strategies import UserTurnStrategies

user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=UserTurnStrategies(
            start=[MinWordsUserTurnStartStrategy(min_words=3)],
            stop=[SpeechTimeoutUserTurnStopStrategy()],
        ),
    ),
)
```

### Wake Phrase Detection

Require a wake phrase before allowing interaction, then use the default turn strategies:

```python theme={null}
from pipecat.turns.user_start import WakePhraseUserTurnStartStrategy
from pipecat.turns.user_turn_strategies import (
    UserTurnStrategies,
    default_user_turn_start_strategies,
)

user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=UserTurnStrategies(
            start=[
                WakePhraseUserTurnStartStrategy(phrases=["hey pipecat"]),
                *default_user_turn_start_strategies(),
            ],
        ),
    ),
)
```

### Local Smart Turn Detection

Use a local turn detection model instead of a cloud service:

```python theme={null}
from pipecat.audio.turn.smart_turn.local_smart_turn_v3 import LocalSmartTurnAnalyzerV3
from pipecat.turns.user_stop import TurnAnalyzerUserTurnStopStrategy
from pipecat.turns.user_turn_strategies import UserTurnStrategies

user_aggregator, assistant_aggregator = LLMContextAggregatorPair(
    context,
    user_params=LLMUserAggregatorParams(
        user_turn_strategies=UserTurnStrategies(
            stop=[
                TurnAnalyzerUserTurnStopStrategy(
                    turn_analyzer=LocalSmartTurnAnalyzerV3()
                )
            ]
        ),
    ),
)
```

## Related

* [User Input Muting](/pipecat/fundamentals/user-input-muting) - Control when user input is ignored
* [Smart Turn Detection](/api-reference/server/utilities/turn-detection/smart-turn-overview) - AI-powered turn detection
