# Quickstart

Transcribe a conversation with Agent STT.

Agent STT returns transcription a segment at a time and reports the speech and turn events a voice agent needs, so you know when a speaker has finished and the transcript is ready to send to an LLM.

## Using the Agent STT SDK[​](#using-the-agent-stt-sdk "Direct link to Using the Agent STT SDK")

The Agent STT SDK is a Python client for the Agent STT service. It runs no VAD or turn detection of its own — either the service closes turns, or your application does.

To view the source, see [speechmatics-agent-stt](https://github.com/speechmatics/speechmatics-python-sdk/tree/main/sdk/agent_stt) on GitHub.

### 1. Create an API key[​](#1-create-an-api-key "Direct link to 1. Create an API key")

[Create an API key in the portal](https://portal.speechmatics.com/settings/api-keys), which you'll use to securely access the API. Store the key as a managed secret. See [Authentication](/get-started/authentication.md) for temporary keys and other options.

Enterprise customers may need to speak to [Support](https://support.speechmatics.com) to get your API keys.

### 2. Install the SDK[​](#2-install-the-sdk "Direct link to 2. Install the SDK")

```
pip install speechmatics-agent-stt pyaudio
```

`pyaudio` is required for microphone input in this quickstart.

### 3. Run the example[​](#3-run-the-example "Direct link to 3. Run the example")

Set your API key in the environment, then run the script:

```
export SPEECHMATICS_API_KEY=<your-api-key>
```

```
import asyncio

from speechmatics.agent_stt import AgentSttAsyncClient
from speechmatics.agent_stt import Microphone
from speechmatics.agent_stt import Model
from speechmatics.agent_stt import ServerMessageType
from speechmatics.agent_stt import TranscriptionConfig

SAMPLE_RATE = 16000
CHUNK_SIZE = 1024


async def main() -> None:
    mic = Microphone(sample_rate=SAMPLE_RATE, chunk_size=CHUNK_SIZE)
    if not mic.start():
        print("PyAudio not installed - install with: pip install pyaudio")
        return

    # Uses SPEECHMATICS_API_KEY from the environment
    client = AgentSttAsyncClient(
        transcription_config=TranscriptionConfig(
            model=Model.LINDEN_1,
            language="en",
            enable_partials=True,
            diarization="speaker",
        )
    )

    # Register handlers before the session opens, so no message arrives unhandled
    @client.on(ServerMessageType.ADD_PARTIAL_SEGMENT)
    def handle_partial_segment(message):
        print(f"[partial] {message['segment']['transcript']}")

    @client.on(ServerMessageType.ADD_SEGMENT)
    def handle_segment(message):
        speaker = message["segment"].get("speaker", "?")
        print(f"[final]   {speaker}: {message['segment']['transcript']}")

    @client.on(ServerMessageType.END_OF_TURN)
    def handle_end_of_turn(message):
        print(f"[turn]    end at {message['metadata']['end_time']}s")

    async with client:
        print("\nMicrophone ready - speak now (Ctrl+C to stop)\n")
        try:
            while True:
                await client.send_audio(await mic.read(CHUNK_SIZE))
        except (asyncio.CancelledError, KeyboardInterrupt):
            pass
        finally:
            mic.stop()

    print(f"\nTranscript: {client.transcript_text(speaker_labels=True)}")


try:
    asyncio.run(main())
except KeyboardInterrupt:
    pass
```

Speak into your microphone. You should see partials as you talk, then a final segment when the turn closes:

```
[partial] hello I'd like to check on my
[final]   S1: Hello, I'd like to check on my order.
[turn]    end at 3.24s
```

Press `Ctrl+C` to stop.

## Understanding the output[​](#understanding-the-output "Direct link to Understanding the output")

Read the text from `message["segment"]["transcript"]`, and the speaker label from `message["segment"]["speaker"]`.

* **`AddPartialSegment`** — an interim preview. Each one replaces the previous, so don't concatenate them.
* **`AddSegment`** — the finalized segment, and the stable output to pass to your LLM. Expect several per turn.
* **`EndOfTurn`** — the speaker has finished and your agent can respond.

See [Segmentation](/speech-to-text/agent-stt/segmentation.md) for what closes a segment and how speaker labels work.

## Choosing who closes the turn[​](#choosing-who-closes-the-turn "Direct link to Choosing who closes the turn")

By default the service closes turns itself, from voice activity. If something upstream already detects that a speaker has finished — Pipecat, LiveKit, a push-to-talk button — start the session in `external` mode and close each turn yourself:

```
from speechmatics.agent_stt import TurnConfig, TurnDetectionMode

client = AgentSttAsyncClient(
    transcription_config=TranscriptionConfig(language="en"),
    turn_config=TurnConfig(turn_detection_mode=TurnDetectionMode.EXTERNAL),
)
```

Then close each turn when your side decides speech has ended:

```
client.finalize()
```

The call is stamped with the audio position at the moment it was made, so the service cuts the turn where you heard speech stop rather than wherever the message lands. In this mode nothing else closes a turn — an application that stops calling `finalize()` never sees another `EndOfTurn`. See [Turn detection](/speech-to-text/agent-stt/turn-detection.md).

## Next steps[​](#next-steps "Direct link to Next steps")

#### [Turn detection](/speech-to-text/agent-stt/turn-detection.md)

[Choose which side decides that a speaker has finished](/speech-to-text/agent-stt/turn-detection.md)

#### [Speech to Text languages](/speech-to-text/languages.md)

[The languages you can pass as language](/speech-to-text/languages.md)

#### [Agent STT Reference](/api-ref/agent-stt-websocket.md)

[Every WebSocket message, handshake response and error code](/api-ref/agent-stt-websocket.md)
