Skip to main content

Speechmatics Agent STT SDK

Python client for the Speechmatics Agent STT service, built on speechmatics-rt.

The Agent STT service works in segments rather than word groups, and reports the speech and turn events a voice agent needs. This SDK runs no VAD and no turn detection of its own - either the service's VAD closes turns, or your application's does.

pip install speechmatics-agent-stt

Quick start

import asyncio
from speechmatics.agent_stt import AgentSttAsyncClient, ServerMessageType, TranscriptionConfig

async def main():
    # Uses SPEECHMATICS_API_KEY from the environment
    client = AgentSttAsyncClient(
        transcription_config=TranscriptionConfig(language="en", enable_partials=True)
    )

    # Register handlers before opening the session, so no message can arrive unhandled
    @client.on(ServerMessageType.ADD_SEGMENT)
    def handle_segment(message):
        print(message["segment"]["transcript"])

    async with client:
        while chunk := next_audio_chunk():
            await client.send_audio(chunk)

    print(client.transcript)

asyncio.run(main())

Who closes the turn

The service needs a boundary to close a segment on. Pick where it comes from:

from speechmatics.agent_stt import TurnConfig, TurnDetectionMode

# The service's VAD (default). It emits SpeechStarted/SpeechEnded and StartOfTurn/EndOfTurn.
turn_config = TurnConfig(turn_detection_mode=TurnDetectionMode.VAD)

# Your endpointing - Pipecat, LiveKit, or your own. The service's VAD stays off.
turn_config = TurnConfig(turn_detection_mode=TurnDetectionMode.EXTERNAL)

client = AgentSttAsyncClient(
    transcription_config=TranscriptionConfig(language="en"), turn_config=turn_config
)

With TurnDetectionMode.EXTERNAL, close each turn when your side decides speech has ended:

client.finalize()              # from a sync callback
await client.force_end_of_utterance()   # from async code

Either sends ForceEndOfUtterance stamped with the audio position at the moment of the call, so the service cuts the turn where you heard the end of speech rather than wherever the send lands. The flushed segment comes back as a normal AddSegment.

What decides that is entirely yours - a VAD, an ML turn model, or a push-to-talk button. The SDK only cares that something calls finalize().

Session output

Every server message is dispatched to your handlers and also kept on the client:

client.transcript          # final segments joined by the language's word delimiter
client.segments            # list[Segment] - transcript, timing, speaker, is_final
client.partial_segment     # the segment currently in flight, or None
client.timeline            # list[TimedEvent] - the speech and turn events, in order
client.events              # every raw message, including ones this SDK does not model
client.session_info        # session id and the language pack the service reported

client.transcript_text(speaker_labels=True, include_partial=False)

Pass record_events=False to AgentSttAsyncClient for long-running sessions where the raw log is not wanted.

Messages

Emitted by the service:

Message Payload
AddSegment segment.transcript, optional segment.speaker, metadata.start_time, metadata.end_time
AddPartialSegment interim preview of the segment being built
SpeechStarted / SpeechEnded metadata.start_time / metadata.end_time (service VAD)
StartOfTurn / EndOfTurn metadata.start_time / metadata.end_time (service turn detection)

Passed through from the RT engine: RecognitionStarted, AudioAdded, EndOfTranscript, SpeakersResult, Info, Warning, Error.

Anything else the engine sends - the word-level AddTranscript/AddPartialTranscript, audio events - is not modelled here, but still reaches client.events and any handler registered under its name.

Configuration

TranscriptionConfig is the RT transcription config with the service's own model names. Turn taking is configured separately, and is fixed for the life of the session:

Config Field Meaning
TurnConfig turn_detection_mode TurnDetectionMode.VAD (default) or TurnDetectionMode.EXTERNAL

model takes an Agent STT Model and defaults to DEFAULT_MODEL (Model.LINDEN_1):

from speechmatics.agent_stt import Model, TranscriptionConfig

transcription_config = TranscriptionConfig(model=Model.LINDEN_1)

The proxy in front of the service resolves the Agent STT model name onto the engine's operating point, so the transcriber never sees a name it has no notion of. The RT models (enhanced, standard) are not Agent STT models and are not accepted here; the deprecated operating_point still passes through, and suppresses the model default so the two never arrive together.

emit_sentences splits a segment after each end-of-sentence punctuation mark (such as ., ? or !), so each segment carries one sentence: "Hi there. How are you?" arrives as two segments rather than one. Off unless you ask for it, and fixed for the life of the session:

transcription_config = TranscriptionConfig(language="en", emit_sentences=True)

Engine silence-based end of utterance is not offered here. A turn ends either because the service's VAD said so, or because you called finalize().

Endpoint

The Agent STT endpoint is the RT endpoint plus /agent:

AgentSttAsyncClient(url="wss://eu2.rt.speechmatics.com/v2")  # -> /v2/agent
AgentSttAsyncClient(url="ws://localhost:8000/v2")            # -> /v2/agent
AgentSttAsyncClient(app="pipecat/1.0")                       # reported as sm-app

Resolution order: the url argument, SPEECHMATICS_RT_URL, then the EU endpoint. The /agent segment is appended when it is missing.

Audio

The service accepts raw PCM (pcm_s16le or pcm_f32le) at 16 kHz (the default) or 8 kHz. Any other sample rate raises ValueError. To send 8 kHz audio, pass an AudioFormat:

from speechmatics.agent_stt import AgentSttAsyncClient, AudioEncoding, AudioFormat

client = AgentSttAsyncClient(
    audio_format=AudioFormat(encoding=AudioEncoding.PCM_S16LE, sample_rate=8000, chunk_size=1024),
)

Set chunk_size explicitly: AudioFormat defaults to 4096 bytes, not the client's default of 1024.

Audio sent before the session is ready, or after it closes, is dropped rather than raising, so an audio callback does not have to track session state.

Examples

See examples/agent_stt.

Metadata

Release files for speechmatics-agent-stt 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for speechmatics-agent-stt 0.3.0
File Size Uploaded Provenance
speechmatics_agent_stt-0.3.0.tar.gz 17.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for speechmatics-agent-stt 0.3.0
File Interpreter ABI Platform
speechmatics_agent_stt-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 35.8 kB

Release files / speechmatics_agent_stt-0.3.0.tar.gz

Download URL speechmatics_agent_stt-0.3.0.tar.gz
Size 17.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9296481150af27686839f2d263bba50fa15fc17183a74b004af0e8d72dd31246
BLAKE2b-256 checksum
How to use checksums
875176479daa3874002aec0468cc8ee0fd5e92b284ca2fef59b9a269b3992ebb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / speechmatics_agent_stt-0.3.0-py3-none-any.whl

Download URL speechmatics_agent_stt-0.3.0-py3-none-any.whl
Size 18.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94386c9f721987496b0f887ae626be846fc8024f5fb8f7aed38f06aff4643eb5
BLAKE2b-256 checksum
How to use checksums
5fcdfc66de6ce21c049bbb069f26df26aab3dec610678fddf7595addef027513
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for speechmatics-agent-stt 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page