> ## 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.

# Telnyx AI Assistants

> Run a configured Telnyx AI Assistant inside a meeting as the bot's intelligence, answering questions and acting on what is discussed.

Bring a [Telnyx AI Assistant](/docs/inference/ai-assistants/no-code-voice-assistant) into the meeting as the bot's intelligence. The assistant hears the room through the bot, reasons with the model and tools you configured, and responds in its own configured voice -- effectively running your assistant inside the meeting. This turns the bot from a recorder into a participant that can answer questions, take notes, and act on what is discussed.

<Callout icon="users" color="#FFC107" iconType="solid" title="Multiple participants">
  If you intend to use an AI Assistant in a meeting with more than one participant, you will need to do some additional configuration to avoid the Assistant addressing every person speaking. See [Suggested Assistant configuration](#suggested-assistant-configuration).
</Callout>

## How It Works

The Meeting service connects your Assistant to the meeting directly. Meeting audio reaches the Assistant, the Assistant's speech is played into the room, and everything in between is handled for you.

There is nothing to wire up: supply the Assistant's ID and the service does the rest. Earlier versions required a Call Control connection, a caller ID and a loopback SIP URI to bridge audio to the Assistant. That machinery is gone, and so are the fields — sending them now returns `400 invalid_request`.

Attach an assistant with the `assistant` parameter at session creation:

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/meeting_sessions \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "meeting_url": "https://meet.google.com/abc-defg-hij",
    "bot_name": "AI Assistant",
    "assistant": {
      "id": "assistant-6207ab25-b185-478f-b2ef-85159e226727",
      "audio_gate": "half_duplex"
    }
  }'
```

The Assistant must belong to the authenticated customer account.

| Field               | Type    | Description                                                                                                                                                                                                                  |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                | string  | The AI Assistant to attach, from your [Assistants](/docs/inference/ai-assistants/no-code-voice-assistant) configuration. 1-255 characters.                                                                                   |
| `audio_gate`        | string  | How meeting audio reaches the assistant: `half_duplex` (default) or `full_duplex`. `full_duplex` allows participants to interrupt the assistant and **costs significantly more** -- see [Audio Gate](#assistant-parameters). |
| `dynamic_variables` | object  | Values for the [dynamic variables](/docs/inference/ai-assistants/dynamic-variables) in the Assistant's instructions, greeting, or tools. String-to-string, at most 63 entries.                                               |
| `leave_on_end`      | boolean | Leave the meeting when the Assistant's conversation ends or fails. `false` by default.                                                                                                                                       |

The assistant listens to the meeting, runs its configured model and tools (webhooks, handoff, knowledge bases, MCP servers, and more), and speaks in the voice configured on the Assistant itself -- the session's own `voice` applies to [manual speech](/docs/meeting/control/speak) and is not used while an assistant is attached. Its conversation is captured in the [live transcript](/docs/meeting/live-transcript) and [artifacts](/docs/meeting/collect-results) like any other participant.

## Assistant Parameters

Each `assistant` parameter has its own configuration and constraints. Select a tab for details.

<Tabs>
  <Tab title="Assistant" icon="robot">
    `id` <Badge color="red" size="sm">Required</Badge>

    Supply the ID of an existing Telnyx AI Assistant in your account. The Assistant's instructions, model, voice, tools, transcription configuration, and other behavior all come from that Assistant resource.

    * Supply the resource ID, not the Assistant's display name.
    * The Assistant must be owned by the authenticated customer account.
    * Test the Assistant on a normal Voice API call before using it in a meeting.
    * Do not include an Assistant API key in the request. Meeting obtains a short-lived delegated credential from the authenticated customer context.
  </Tab>

  <Tab title="Audio Gate" icon="wave-square">
    `audio_gate` <Badge color="yellow" size="sm">Optional</Badge>

    `audio_gate` decides how meeting audio reaches the Assistant, and the two options differ in what the Assistant receives -- one mixed stream or one stream per participant. That difference is what makes interruption possible, and it is also what drives the cost.

    **`half_duplex`** <Badge color="yellow" size="xs">default</Badge> -- The Assistant receives a single **mixed** stream of the meeting. While Assistant audio is playing, that stream is replaced with silence, and the gate stays closed for 300 ms after the last Assistant audio frame. The Assistant cannot hear itself, and it also cannot be interrupted: speech during the gate, including the 300 ms hangover, is not heard. One stream, so cost does not change with the number of people in the room.

    **`full_duplex`** -- The Assistant receives a **separate stream per participant**. Nothing is muted, so participants can interrupt the Assistant mid-sentence and it responds. Because the Assistant's own output is not in any participant's stream, it does not hear itself either -- this is genuine barge-in, not the gate switched off.

    <Warning>
      **`full_duplex` costs significantly more, and the increase scales with attendance.** One stream per participant means the per-minute cost is multiplied by the number of participants: a six-person meeting ingests roughly six times the audio of a one-person meeting for the same wall-clock duration. Choose it when interruption genuinely matters to the experience, not as a default. Per-participant audio is metered separately from the flat per-minute rates and will be billed on top of them.
    </Warning>

    `half_duplex` is a coarse audio gate, not acoustic echo cancellation.
  </Tab>

  <Tab title="Leave on End" icon="right-from-bracket">
    `leave_on_end` <Badge color="yellow" size="sm">Optional</Badge>

    When the Assistant's conversation reaches a terminal state, the bot leaves the meeting:

    ```json theme={null}
    {
      "assistant": {
        "id": "assistant-id",
        "leave_on_end": true
      }
    }
    ```

    **Terminal means `ended` or `failed`, deliberately.** A session whose purpose was the Assistant has nothing left to offer once the Assistant is dead, and the alternative is the failure mode this exists to remove: a silent bot sitting in the meeting until somebody notices and removes it by hand.

    Off by default, so a session that does not ask for it behaves exactly as before -- the bot stays after the Assistant stops, and removing it is your job.

    * Fires **once**. A second terminal transition does not leave twice.
    * A leave the meeting platform refuses is logged and the session settles as it otherwise would; the leave is best-effort, not a new failure path.
    * It does not change how the session ends elsewhere. Normal teardown remains the source of truth, so the session still reaches its usual terminal status.

    Echoed back as `assistant.leave_on_end`, `false` when unset.
  </Tab>

  <Tab title="Dynamic Variables" icon="code">
    `dynamic_variables` <Badge color="yellow" size="sm">Optional</Badge>

    One Assistant, many meetings, different facts each time. If the Assistant's instructions, greeting, or tools use [dynamic variables](/docs/inference/ai-assistants/dynamic-variables), supply this meeting's values when you create the session:

    ```json theme={null}
    {
      "meeting_url": "https://meet.google.com/abc-defg-hij",
      "assistant": {
        "id": "assistant-id",
        "dynamic_variables": {
          "candidate_name": "Ada Lovelace",
          "role": "Staff Engineer"
        }
      }
    }
    ```

    They are delivered before the Assistant's first utterance, so a greeting that reads `Hi {{candidate_name}}` is already filled in when the Assistant opens the conversation -- the same guarantee as the [realtime conversation API](/docs/inference/ai-assistants/realtime-conversations#pass-dynamic-variables), where the values ride the opening `session.update` frame.

    The limits, each rejected with `400 invalid_request`:

    * At most **63 entries**.
    * Keys **1-128 characters**.
    * Values must be **strings**. A number or a nested object is rejected rather than coerced. There is no per-value length cap; the whole map is budgeted in aggregate at **1,047,552 bytes (1023 KiB)**.
    * `streaming_audio`, `ai_assistant_streaming_audio` and `meeting_session_id` are **reserved**. They toggle provider infrastructure or are set by the service rather than fill a prompt template, so they are refused instead of quietly ignored.

    Echoed back as `assistant.dynamic_variables`, and `null` when none were supplied. They are fixed for the session: there is no way to change them once the bot is on its way.

    <Note>
      The `telnyx_` prefix is [reserved for system variables](/docs/inference/ai-assistants/dynamic-variables) and is not the place to put your own, but the Meeting service does not filter it -- so `telnyx_end_user_target` reaches an Edge Compute [dynamic-variables webhook](/docs/edge-compute/guides/ai-assistant-backend) as it would on any other channel.
    </Note>
  </Tab>
</Tabs>

## Suggested Assistant Configuration

Everything above is sent on the meeting session. This section is the other half -- settings on the **Assistant resource itself**, in the [Portal](https://portal.telnyx.com/#/ai/assistants) or through the Assistants API. Nothing here is required to attach an Assistant to a meeting, and nothing here is meeting-specific API surface.

### For meetings with more than one participant

A one-to-one call has an obvious turn structure: the caller speaks, the Assistant answers. A meeting does not. People talk to each other, and an Assistant that answers every turn it hears will talk over a discussion it was never part of.

**Add the `skip_turn` tool.** It lets the Assistant choose to say nothing on a turn -- in effect, to speak only when spoken to. Without it the Assistant has no way to decline a turn, so it will attempt a response to whatever it just heard.

```json Tools theme={null}
{
  "type": "skip_turn",
  "skip_turn": {}
}
```

**Then tell the Assistant when to use it.** The tool gives the Assistant the ability to stay quiet; the instructions decide when it should. This is a starting point drawn from testing, not a required form of words -- adapt it to your Assistant's own voice:

```text Instructions theme={null}
The call may include the main user and one or more additional participants. Pay close attention to who is speaking and who they are addressing.

If the participants are talking to each other and are not addressing you, use the Skip Turn tool and remain silent.

If someone addresses you directly, respond normally.
```

**Give it a name people can use.** There is no wake word. Nothing listens for a trigger phrase and switches the Assistant on -- "addressed directly" is a judgement it makes from the conversation, which is why the instructions above have to describe it.

What it answers to is the Assistant's own **name**, set on the Assistant resource. An Assistant named `Weather Assistant` is addressed as "Weather Assistant"; one named `Nyx` is addressed as "Nyx". Nothing extra is wired up for meetings -- name the Assistant and that is the name in the room.

So the name is worth choosing for a room rather than for a list. It is spoken aloud by people over compressed audio, so two or three syllables carry better than one, and a name that collides with ordinary meeting speech -- "signal", "echo", "central" -- will pull the Assistant into conversations it was not part of. It is also worth naming in the instructions, so the Assistant recognises itself when somebody says it:

```text Instructions theme={null}
You are in this meeting as Nyx. Participants will address you by that name.
```

<Note>
  How an Assistant handles several speakers at once is not specific to meetings. [Multi-participant calls](/docs/inference/ai-assistants/multi-participant-calls) covers the underlying behaviour and is worth reading alongside this.
</Note>

### To let the Assistant end its own session

**Add the `hangup` tool** if the Assistant should be able to decide it is no longer needed and end the conversation, rather than staying until something else removes it.

```json Tools theme={null}
{
  "type": "hangup",
  "hangup": {}
}
```

This composes with [`leave_on_end`](#assistant-parameters): the tool ends the Assistant's conversation, and `leave_on_end: true` on the session turns that into the bot leaving the meeting. Set the tool alone and the Assistant stops talking while the bot stays in the room; set both and the bot goes when the Assistant decides it is done.

## Authentication and Resource Ownership

For production requests:

* The request must pass through the authenticated production Gateway, which supplies an account and actor identity.
* The Assistant must belong to that customer.
* The Meeting service acts on the customer's behalf using short-lived delegated credentials resolved immediately before each command.
* API keys, bearer tokens, and webhook public keys must not be included in the `assistant` object.

Unknown fields are rejected. For example, this is invalid:

```json theme={null}
{
  "assistant": {
    "id": "assistant-id",
    "api_key": "***"
  }
}
```

The API response returns `id`, `audio_gate`, `dynamic_variables` and `leave_on_end` — the whole of the assistant configuration.

## Session Restrictions

Assistant-backed meeting sessions are currently:

* **Immediate-only** -- `join_at` cannot be supplied.
* **Incompatible with `barge_in: true`** -- the Telnyx AI Assistant owns interruption behavior. To let participants interrupt the Assistant, set `audio_gate: "full_duplex"` rather than `barge_in`.
* **Compatible with an avatar** -- an Assistant and an anam avatar can be used together; Assistant speech is then delivered through the lip-synced avatar output.

## Troubleshooting

| Symptom                                                     | Typical cause                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 invalid_request`                                       | `id` is empty or over 255 characters; `audio_gate` is not `half_duplex` or `full_duplex`; `dynamic_variables` exceeds 63 entries, has a key outside 1-128 characters, has a non-string value, exceeds the aggregate 1,047,552-byte budget, or uses a reserved key; `barge_in: true` or `join_at` was supplied; or the object carries a field that is not `id`, `audio_gate`, `dynamic_variables` or `leave_on_end` — including `call_control_connection_id`, `from` and `loopback_sip_uri`, which are no longer part of the API. |
| `503 not_configured`                                        | Production Assistant support or dedicated Assistant Recall ingress is not configured for the deployment.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Assistant reaches `connected` but is silent                 | Check the Assistant itself: test it on a normal Voice API call, and confirm it has a voice configured.                                                                                                                                                                                                                                                                                                                                                                                                                           |
| A greeting or instruction still shows `{{a_variable}}`      | No value was supplied for that key. Variables are per session and set only at create time, so check the `dynamic_variables` echoed back on the session rather than the Assistant's own configuration.                                                                                                                                                                                                                                                                                                                            |
| `assistant_state` becomes `failed`                          | The Assistant could not be started. Confirm the ID is correct and the Assistant belongs to this account.                                                                                                                                                                                                                                                                                                                                                                                                                         |
| The Assistant answers when people are talking to each other | It has no way to decline a turn. Add the `skip_turn` tool and the instructions in [Suggested Assistant configuration](#suggested-assistant-configuration) — this is the most common complaint in meetings with more than two people.                                                                                                                                                                                                                                                                                             |
| The Assistant stopped but the bot is still in the meeting   | Expected without `leave_on_end`. The Assistant reaching `ended` or `failed` does not remove the bot on its own — set `assistant.leave_on_end: true` at create time, or remove the bot yourself when you see the state change.                                                                                                                                                                                                                                                                                                    |
| Assistant responds to itself                                | You are on `full_duplex` with an unusual audio path, or on a build predating it. `half_duplex` prevents it outright, at the cost of mid-speech interruption.                                                                                                                                                                                                                                                                                                                                                                     |
| Participants cannot interrupt the Assistant                 | Expected on `half_duplex`, including for 300 ms after it stops speaking. Set `audio_gate: "full_duplex"` -- and read the cost note first.                                                                                                                                                                                                                                                                                                                                                                                        |

## Combine with a Digital Avatar

The `assistant` and `avatar` parameters are independent, so you can use them together or separately:

| Assistant | Avatar | Result                                                                                                                        |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
| yes       | no     | AI Assistant runs the conversation as a plain roster participant                                                              |
| yes       | yes    | AI Assistant runs the conversation, rendered as a [speaking avatar](/docs/meeting/digital-avatars). Either `audio_gate` works |
| no        | yes    | Scripted bot presence rendered as a speaking avatar (see [Digital avatars](/docs/meeting/digital-avatars))                    |

## Related

* [Multi-participant calls](/docs/inference/ai-assistants/multi-participant-calls) -- how the Assistant behaves when multiple people are in the conversation
* [Controlling the Bot](/docs/meeting/control) -- the manual alternative: speak and chat by hand
* [Meeting Presence](/docs/meeting/presence) -- the bot's roster name and on-camera identity
* [Digital avatars](/docs/meeting/digital-avatars) -- render the bot as a speaking avatar on camera
