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

# Controlling the Bot

> The three ways to drive the bot in a live meeting: speak, chat, and running an assistant.

While the meeting is `active`, the bot does three things, and you choose how each is driven:

* [**Speak**](/docs/meeting/control/speak) -- say text out loud, and stop mid-utterance.
* [**Chat**](/docs/meeting/control/chat) -- post to the meeting's native chat.
* [**Automate**](/docs/meeting/ai-assistants) -- hand the *speaking* to a Telnyx AI Assistant, which listens and answers on its own.

The first two are manual: every word is a call you make. The third is designed to own the *speaking* -- an attached assistant holds the conversation -- while `send_chat` keeps working exactly as it does without one. `speak` is **not** refused with an assistant attached: the bot becomes a webpage-output bot and speak audio routes through the assistant's output page instead of the bot mic (see [Speak](/docs/meeting/control/speak)). The assistant is still meant to do the talking, so pick between speaking modes before the meeting rather than discovering the difference during it; [Telnyx AI Assistants](/docs/meeting/ai-assistants) sets out what the assistant takes over.

All manual actions return `202 Accepted` and complete asynchronously.

## Same Commands over WebSocket

The same actions can be sent as frames on the [live transcript stream](/docs/meeting/live-transcript) instead of over REST:

```json theme={null}
{ "action": "speak", "text": "Let's recap what we agreed on.", "interrupt": false }
```

```json theme={null}
{ "action": "send_chat", "text": "Noted. I will send the summary after the call." }
```

The stream is convenient for low-latency bots, but it allows at most 8 commands in flight or queued and gives no per-command acknowledgement. Prefer REST actions when you need a durable, acknowledged response.

The socket's own limits -- frame size, close codes, and cursor resumption on reconnect -- are covered in [Live Transcript](/docs/meeting/live-transcript#connect-to-the-websocket-stream).

## Errors

Action requests fail with a non-2xx status and an error envelope, for example when the session is not `active`:

```json theme={null}
{
  "error": {
    "code": "invalid_state",
    "message": "session must be active to perform this action (current status: ended)"
  }
}
```

<Note>
  Not every failure carries a body. A `502` from [`speak`](/docs/meeting/control/speak) — for instance when the audio cannot be handed to an [assistant](/docs/meeting/ai-assistants) or avatar output page — can come back with no JSON, so branch on the status code before parsing the body.
</Note>

Every code the Meeting API returns is listed in [Meeting API Errors](/docs/meeting/errors).

## Related

* [Speak](/docs/meeting/control/speak) -- make the bot say something, and stop it
* [Chat](/docs/meeting/control/chat) -- post to the meeting chat and read replies
* [Telnyx AI Assistants](/docs/meeting/ai-assistants) -- let an assistant hold the conversation
* [Live Transcript](/docs/meeting/live-transcript) -- follow the transcript stream in real time
