Segmentation
The Realtime API returns transcription word by word, leaving you to decide where one piece of speech ends and the next begins. Agent STT does that grouping for you and returns whole segments: punctuated, attributed to a speaker, and ready to pass to an LLM.
Partial and final segments
Two messages carry the transcript:
AddPartialSegment— an interim preview of the segment being built. Each one replaces the previous one, so display the latest and discard the rest. Never concatenate them.AddSegment— the finalized segment. It will not change, and it is the message to act on.
Partials arrive only when transcription_config.enable_partials is true.
What closes a segment
A segment ends at the first boundary it reaches:
Because of this, a single turn often produces several AddSegment messages. To reconstruct everything one speaker said, join the segments for that speaker between StartOfTurn and EndOfTurn. See Turn detection for the turn boundary itself.
Reaching the duration cap is a sign that turn detection is not closing turns, rather than an ordinary boundary.
Segment payload
Every AddSegment and AddPartialSegment has the same shape:
{
"message": "AddSegment",
"segment": {
"transcript": "Hello, I'd like to check on my order.",
"speaker": "S1"
},
"metadata": {
"start_time": 1.02,
"end_time": 3.24
}
}
Speaker labels
Set transcription_config.diarization to speaker to attribute each segment acoustically. Labels are S1, S2 and so on, in the order each speaker is first heard. A segment never spans two speakers, because a speaker change is itself a boundary.
Tune attribution with transcription_config.speaker_diarization_config:
Speaker identification
Labels such as S1 are per-session: the same person is not S1 in the next call. Speaker identification carries a speaker across sessions, under a label you choose.
Enrol. Set get_speakers to true to receive identifiers at the end of the transcript, or send GetSpeakers mid-session with final set to true to wait for the end of the stream. Either way the server replies with SpeakersResult, holding a speaker_identifiers value for each label.
Identify. Store those identifiers and pass them back in a later session as speaker_diarization_config.speakers, each with a label of your own:
{
"diarization": "speaker",
"speaker_diarization_config": {
"speakers": [
{ "label": "Alice", "speaker_identifiers": ["<alice_id>"] }
]
}
}
Alice's segments are then labelled Alice rather than S1, and anyone unenrolled keeps an S1-style label. Your labels must not look like the internal format, so S1, S2 and UU are rejected.
Identifiers are tied to the model that generated them and are scoped to your project, and there is a limit on how many you can send in one session. See Speaker identification for enrollment guidance and the full caveats.
Sentence-level segments
Set emit_sentences to true to add a boundary at every sentence, so each segment holds one sentence. Leave it off when you want the largest coherent chunk per speaker, which is usually what an LLM should receive.