> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tazolabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming decisions

> Stream audio over a WebSocket connection and receive decisions as it arrives.

Use streaming decisions to evaluate audio as it arrives. Your application sends
audio chunks over a WebSocket connection and receives answers with probabilities
throughout the stream.

See [Stream decisions](https://docs.tazolabs.com/api-reference/streaming/decisions.md) for the full message
reference.

> [!NOTE]
>
> Tazo Small is currently unavailable through the API, including streaming.
> Requests return `model_unavailable`. For assistance, contact
> [support@tazolabs.com](mailto:support@tazolabs.com). Use `tazo-large` for API requests.

## Start a session

Open a connection to:

```text theme={null}
wss://api.tazolabs.com/v1/decisions/stream
```

Send `session.start` within five seconds of connecting. Include your
[API key](https://docs.tazolabs.com/authentication.md), the context, and one question:

```json theme={null}
{
  "type": "session.start",
  "authorization": "Bearer YOUR_API_KEY",
  "model": "tazo-large",
  "audio_scope": "chunk",
  "evaluation_interval_ms": 1000,
  "state": {"context": "Choose the tool matching the spoken request."},
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "Which action should be taken?",
      "criteria": {
        "NO_TOOL": "Respond directly without calling a tool.",
        "get_weather": "Get weather for a city."
      }
    }
  },
  "input_audio": {"encoding": "pcm_s16le", "sample_rate_hz": 16000, "channels": 1}
}
```

The server returns `session.ready` with the accepted configuration and limits.
Wait for this event before sending audio.

## Send audio

Declare the source format in `session.start.input_audio`, then send the matching
raw mono samples as binary WebSocket messages:

| `encoding` | `sample_rate_hz` | Bytes per sample |
| - | - | - |
| `pcm_s16le` | Any integer from 8000 to 48000 | 2, signed little-endian |
| `mulaw` (G.711 μ-law) | 8000 | 1 |
| `alaw` (G.711 A-law) | 8000 | 1 |

`channels` must be `1`. The default remains PCM16 at 16 kHz. A telephone stream
using μ-law declares `{"encoding":"mulaw","sample_rate_hz":8000,"channels":1}`.
Read the format from your provider's configuration or stream metadata; raw samples
do not contain enough information to discover it. Unwrap provider JSON/base64 or
RTP before forwarding the audio payload. File containers and codecs such as Opus
and AAC are not supported here. Unsupported declarations return
`unsupported_audio_format`; a new session is required to change the format.

Messages must contain complete samples and at most 200 ms of source audio.
Read `session.ready.max_audio_message_bytes`: 3,200 bytes for 8 kHz PCM16,
1,600 for G.711, 6,400 for 16 kHz PCM16, or 19,200 for 48 kHz PCM16. Send only
samples, without WAV headers or base64 text. A 100 ms message is recommended.

The server decodes and resamples to mono 16 kHz PCM16 before evaluation, retaining
filter state across messages and flushing the final samples at commit/finish.
Resampling adds buffering delay; decision offsets use the converted sample clock.
When a turn limit applies, it counts all incoming audio, including audio held by the filter.
Existing 16 kHz PCM16 is passed through unchanged.

The default `audio_scope` is `chunk`: each evaluation uses new audio since the
previous evaluation and can stream continuously without periodic commits.
Set `audio_scope` to `turn` explicitly to evaluate all audio received in the
current turn.

Set `evaluation_interval_ms` to a value from 250 to 30,000 ms to choose the
evaluation interval. The default is 1,000 ms. Responses may arrive less often
when an evaluation takes longer. The server may shorten the accepted interval to
fit the model's input limit; read `session.ready.evaluation_interval_ms`.
Each evaluation counts against the account's rate limit. The example uses
1,000 ms, which can use 60 of the account's 500 requests per rolling minute
for that model. The default 1,000 ms interval can use 60 requests per minute
per continuous stream. Allow room for other streams and uploaded decisions.

## Receive decisions

Listen for `decision.updated` events while continuing to send audio. For example,
a request about the weather can produce:

```json theme={null}
{
  "type": "decision.updated",
  "session_id": "ses_example",
  "sequence": 2,
  "turn_id": "turn_1",
  "config_revision": 1,
  "id": "dec_example",
  "model": "tazo-large",
  "audio_start_ms": 0,
  "audio_end_ms": 1000,
  "answers": {
    "action": {
      "type": "choice",
      "choice": "get_weather",
      "probabilities": {"NO_TOOL": 0.08, "get_weather": 0.92},
      "confidence": 0.92
    }
  },
  "usage": {"audio_seconds": 1.0},
  "elapsed_ms": 52.0
}
```

`answers` uses the question and option IDs from your request. `audio_start_ms`
and `audio_end_ms` identify the evaluated audio range within the current turn.
Your application decides how to act on each result.

## Complete a turn

A turn is a group of audio chunks that your application submits for evaluation.
To complete it, stop sending audio and send:

```json theme={null}
{"type": "input.commit"}
```

The server evaluates any remaining audio and returns `decision.finalized`.
In `chunk` mode, this final answer covers the last chunk. Keep earlier updates
if your application needs results from the rest of the turn.

Wait for `decision.finalized` before sending the next turn on the same connection.
Buffer any incoming audio during this wait. To end the session, send
`{"type": "input.finish"}`; the server finishes pending audio and sends
`session.closed` before closing the connection.

In `chunk` mode, `session.ready.max_turn_audio_ms` is `null`: there is no total
audio-duration cap and no need to commit periodically. The server releases audio
after handing it to inference and keeps each evaluation within the model's input
limit. Call `input.commit` when you want a turn boundary, or `input.finish` when done.
The playground keeps its own 30-second recording limit.

In `turn` mode, `session.ready.max_turn_audio_ms` is a number reflecting the
model and server limits. Commit before exceeding it. Send audio at real-time
speed in either mode; `audio_buffer_full` means pending audio exceeded the
server's buffer capacity. See [Limits](https://docs.tazolabs.com/guides/limits.md#streaming-limits).

If the server sends an `error` event, read `error.code` and `error.message`.
When `fatal` is `true`, the connection closes.

## Audio credits

When usage billing is enabled, one WebSocket session is one billing operation,
including all turns. Tazo adds received samples across the session and rounds
the total up once to a whole second, storing the deduction in milliseconds.
A 100 ms stream costs 1 second; ten 100 ms chunks in one stream also cost
1 second. Intermediate evaluations do not create extra usage
charges. See [Credits and audio usage](https://docs.tazolabs.com/guides/billing.md) for exhaustion, disconnect,
and shared balance behavior.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.