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

# Voice agents

> Turns, barge-in, and pushing text as your LLM writes it.

A **turn** is one thing your agent says — usually one LLM reply, often several
sentences. You choose its `context_id`.

<Steps>
  <Step title="Open the socket and start">
    One connection carries the whole conversation. Send `start` first, then read
    `metadata`.

    ```python theme={null}
    await ws.send(json.dumps({"type": "start", "v2": True,
                              "voice": "Ananya", "language": "hi"}))
    await ws.recv()
    ```
  </Step>

  <Step title="Push sentences as they are written">
    Same `context_id`, `continue: true` until the last one. **Do not wait
    between sentences** — fire them as fast as your LLM produces them.

    ```python theme={null}
    await ws.send(json.dumps({"type": "text", "context_id": "t1",
                              "text": "आपका ऑर्डर कल पहुँच जाएगा।",
                              "continue": True}))
    await ws.send(json.dumps({"type": "text", "context_id": "t1",
                              "text": "कुछ और चाहिए?",
                              "continue": False}))
    ```
  </Step>

  <Step title="Cancel the moment the user speaks">
    Barge-in drops the whole turn — queued and in-flight — and replies
    `cancelled` instead of `end`.

    ```python theme={null}
    await ws.send(json.dumps({"type": "cancel", "context_id": "t1"}))
    ```
  </Step>
</Steps>

## The rules that matter

<AccordionGroup>
  <Accordion title="One end per turn, always">
    Closing a turn gives you exactly one `end`, tagged with its `context_id`.
    A cancelled turn gives you `cancelled` instead — never both.
  </Accordion>

  <Accordion title="context_id cannot be reused">
    Once a turn has ended, that id is spent. Reusing it is an error rather than
    a second turn, because two terminators for one id desynchronises everything
    after it.
  </Accordion>

  <Accordion title="Cancel before you close the socket">
    Closing alone leaves the GPU finishing audio nobody will hear. Send
    `cancel`, then close.
  </Accordion>

  <Accordion title="Audio arrives in order">
    Sentences are spoken in the order you sent them, tagged with the
    `context_id`, and streamed as they are generated.
  </Accordion>
</AccordionGroup>

## Latency

Measured against Mumbai, eight turns on one socket:

|                      |                   |
| :------------------- | ----------------: |
| Per-turn first audio | **83 ms** (79–95) |
| Handshake            | 269 ms, paid once |
