Overview
Turn events provide hooks into the conversation turn lifecycle, allowing you to know when users and assistants start or stop speaking. These events are emitted by the context aggregators (LLMUserAggregator and LLMAssistantAggregator) and are particularly useful for:
- Collecting transcriptions - Get complete user and assistant transcripts when turns end
- Turn tracking - Monitor conversation flow and timing
- Analytics - Measure turn durations, detect timeouts, and track conversation patterns
Events Summary
User Turn Events
User turn events are registered on theuser_aggregator from an LLMContextAggregatorPair.
on_user_turn_started
Fired when a user turn is detected to have started, based on the configured start strategies.on_user_turn_inference_triggered
Fired when a stop strategy has enough signal to start LLM inference for the current turn. For the default strategies this fires together withon_user_turn_stopped. When a strategy gates finalization on a separate signal — for example FilterIncompleteUserTurnStrategies, where the public stop event waits for the LLM’s ● verdict — this event fires first (and may fire multiple times in one turn) while on_user_turn_stopped is deferred.
With EagerUserTurnStrategies, this event may fire speculatively from a predicted end of turn before the turn has ended. The UserTurnController adds a third parameter, speculation, carrying the turn text the inference was run against when the turn is still open. Handlers registered on LLMUserAggregator or UserTurnProcessor remain unchanged and do not receive this parameter.
UserTurnController, the handler signature is:
Bind
on_user_turn_inference_triggered to react when inference starts, and
on_user_turn_stopped to react when the turn is semantically final. With the
default strategies the two fire together, so most applications only need
on_user_turn_stopped.on_user_turn_stopped
Fired when a user turn is detected to have ended, based on the configured stop strategies. This event includes the complete user transcript for the turn.In realtime
mode,
which
LLMContextAggregatorPair turns on with a speech-to-speech service, the
user message isn’t finalized at turn-stop time, so message.content is
None. Subscribe to
on_user_turn_message_added instead to get the
finalized user text. Behavior in cascade (STT → LLM → TTS) pipelines is
unchanged.on_user_turn_message_added
Fired when a user message is written to the LLM context, carrying the finalized turn text. In cascade pipelines this coincides withon_user_turn_stopped. In realtime mode (with a speech-to-speech service) the write is triggered by the assistant response start rather than the user-turn-end frame, so this event, not on_user_turn_stopped, is the canonical way to subscribe to “context just updated, here’s the user text.”
on_user_turn_stop_timeout
Fired when an active user turn ends on inactivity: the user isn’t speaking and no VAD event or transcript has arrived foruser_turn_stop_timeout seconds (default: 5.0).
After
on_user_turn_stop_timeout fires, on_user_turn_stopped will also be
called with the accumulated transcript.on_user_turn_idle
Fired when the user has been idle (not speaking) for a configured timeout period. This event is useful for re-engaging users who may have stepped away or need a prompt to continue the conversation. The idle timer starts when the bot finishes speaking and is cancelled when the user or bot starts speaking again.The idle timer starts when the bot stops speaking and is cancelled when the
user or bot starts speaking. It is suppressed during function calls and active
user turns. This event can fire multiple times if the user remains idle.
on_user_mute_started
Fired when user input is muted. See User Input Muting for details on muting.on_user_mute_stopped
Fired when user input is unmuted.on_user_backchannel
Fired when the user says a short acknowledgment while the bot talks, such as “mhm”. It is reported from aUserBackchannelFrame, which is pushed in place of a transcription: the bot keeps talking, and the acknowledgment stays out of the LLM context and the turn events above. It doesn’t fire while the user is muted.
Assistant Turn Events
Assistant turn events are registered on theassistant_aggregator from an LLMContextAggregatorPair.
on_assistant_turn_started
Fired when the assistant begins generating a response.on_assistant_turn_stopped
Fired when the assistant finishes responding or is interrupted. This event includes the complete assistant transcript for the turn.This event fires when the LLM response completes, when the user interrupts, or
when the pipeline ends. The event always fires when a turn ends, even if
content is empty (e.g., the turn was interrupted before any tokens were
generated).on_assistant_thought
Fired when the assistant produces a thought from a reasoning model (e.g., extended thinking in Claude). This event provides visibility into the model’s reasoning process.on_assistant_backchannel
Fired when the assistant starts saying text of typebackchannel, such as a BotBackchannelFrame (“Mm-hmm.”). Backchannels stay out of the LLM context and the assistant turn events.
on_summary_applied
Fired when context summarization is successfully applied. This event is useful for monitoring context management and logging compression metrics.This event requires
enable_auto_context_summarization=True in the
LLMAssistantAggregatorParams or manual triggering via
LLMSummarizeContextFrame. See Context
Summarization for
details.Message Types
UserTurnStoppedMessage
Contains the user’s complete transcript when their turn ends.str | None
The complete transcribed text from the user’s turn.
None in realtime mode
(with a speech-to-speech service), where the user message isn’t finalized at
turn-stop time — subscribe to
on_user_turn_message_added for the finalized
text instead.str
ISO 8601 timestamp indicating when the user turn started.
str | None
Optional identifier for the user, if available from the transport.
UserTurnMessageAddedMessage
Accompanieson_user_turn_message_added, carrying the finalized user text written to the LLM context.
str
The aggregated, finalized user transcript for the turn. Always populated.
str
ISO 8601 timestamp indicating when the user turn started.
str | None
Optional identifier for the user, if available from the transport.
UserBackchannelMessage
Accompanieson_user_backchannel, carrying a short acknowledgment the user said while the bot talks.
str
What the user said.
str
ISO 8601 timestamp indicating when the user said it.
str | None
Optional identifier for the user, if available from the transport.
AssistantTurnStoppedMessage
Contains the assistant’s complete transcript when their turn ends.str
The complete text content from the assistant’s turn. May be empty if the LLM
returned zero tokens (e.g., turn was interrupted before any tokens were
received or pushed).
bool
Whether the assistant turn was interrupted. True if the turn ended due to user
interruption or cancellation, False if it completed normally.
str
ISO 8601 timestamp indicating when the assistant turn started.
AssistantThoughtMessage
Contains an assistant’s thought content from reasoning models.str
The thought/reasoning text from the assistant.
str
ISO 8601 timestamp indicating when the thought started.
AssistantBackchannelMessage
Accompanieson_assistant_backchannel, carrying a short acknowledgment the assistant said while the user talks.
str
What the assistant said.
str
ISO 8601 timestamp indicating when the assistant started saying it.
Related
- Transcriptions - Collect conversation transcripts using turn events
- User Turn Strategies - Configure turn detection behavior
- Turn Tracking Observer - Track complete turn cycles with timing