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

# Host Communication

> Listen to deployment lifecycle events and send interactions to the conversation from your page, with plain DOM APIs or the TavusIntegration helper.

## Overview

Both `<tavus-widget>` and `<tavus-embed>` support two-way communication with the host page:

* **Element → page**: the element dispatches `CustomEvent`s (with `bubbles: true` and `composed: true`) for conversation lifecycle, tool calls, and protocol messages.
* **Page → element**: the element exposes an imperative API at `element.tavus` for starting, ending, and messaging the conversation.

CDN consumers use plain DOM APIs - no extra bundle needed. npm consumers can use the typed `TavusIntegration` helper exported from `@tavus/widget` and `@tavus/embed`.

## Events

Listen on the element itself, or on `document` (events bubble out of the shadow DOM):

```js theme={null}
const el = document.querySelector("tavus-embed");

el.addEventListener("tavus:conversation-started", (e) => {
  console.log("started", e.detail.conversationId);
});

el.addEventListener("tavus:tool-call", (e) => {
  console.log("tool call", e.detail.name, e.detail.arguments);
});
```

| Event                        | `detail`                               | Fires when                                                                                                                      |
| ---------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `tavus:conversation-started` | `{ conversationId }`                   | The visitor joins and the conversation connects.                                                                                |
| `tavus:conversation-ended`   | `{ conversationId }`                   | The conversation ends.                                                                                                          |
| `tavus:state-change`         | `{ state }`                            | The conversation state changes (connecting, connected, ended, …).                                                               |
| `tavus:mode-change`          | `{ mode }`                             | The experience switches mode (for example between screens or modalities).                                                       |
| `tavus:error`                | `{ code, message }`                    | The conversation hits an error.                                                                                                 |
| `tavus:tool-call`            | `{ name, arguments, seq?, turn_idx? }` | The PAL's LLM invokes a tool. `arguments` is a JSON string.                                                                     |
| `tavus:protocol-message`     | varies                                 | Firehose: fires for every observable protocol event (utterances, perception, speaking state, …). Switch on `detail.event_type`. |

<Note>
  `tavus:protocol-message` carries the raw [Interaction Events](/sections/conversational-video-interface/interactions-protocols/overview) protocol - `detail.event_type` values such as `conversation.utterance`, `conversation.tool_call`, `conversation.started_speaking`, and `conversation.stopped_speaking` match the schemas documented there. For speaking state, check `detail.properties.role` (`"user"`, `"pal"`, or legacy `"replica"`). See [Started/Stopped Speaking Event](/sections/event-schemas/conversation-started-stopped-speaking).
</Note>

<Note>
  Magic Canvas card taps are not emitted as `tavus:*` host events - they are delivered to your conversation webhook as [`canvas.interaction`](/sections/event-schemas/canvas-interaction) events. See [Canvas interactions](/sections/conversational-video-interface/magic-canvas/api/interactions).
</Note>

## Imperative API

The element exposes its conversation controls on `element.tavus`:

```js theme={null}
const el = document.querySelector("tavus-widget");

await el.tavus.start();                  // start the conversation
el.tavus.sendChat("Hello!");             // send a chat message as the visitor
el.tavus.sendMessage({                   // send a typed protocol interaction
  event_type: "conversation.echo",
  properties: { text: "Read this aloud" },
});
await el.tavus.end();                    // end the conversation
```

| Method                     | Description                                                                             |
| -------------------------- | --------------------------------------------------------------------------------------- |
| `start()`                  | Starts the conversation, as if the visitor pressed the start button. Returns a promise. |
| `end()`                    | Ends the active conversation. Returns a promise.                                        |
| `sendChat(text)`           | Sends a chat message into the conversation as the visitor.                              |
| `sendMessage(interaction)` | Sends a typed protocol interaction. See [Interactions](#interactions).                  |

<Warning>
  `element.tavus` is attached once the element has mounted and its configuration has loaded. Wait for the element to render (or for a `tavus:state-change` event) before calling into it.
</Warning>

## Interactions

`sendMessage` accepts the same interaction shapes as the [Interactions Protocol](/sections/conversational-video-interface/interactions-protocols/overview):

| `event_type`                         | `properties`  | Effect                                                                                                                    |
| ------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `conversation.echo`                  | `{ text }`    | The PAL speaks the text verbatim. See [Echo](/sections/event-schemas/conversation-echo).                                  |
| `conversation.respond`               | `{ text }`    | The text is sent to the LLM, which responds. See [Respond](/sections/event-schemas/conversation-respond).                 |
| `conversation.interrupt`             | -             | Interrupts the PAL mid-speech. See [Interrupt](/sections/event-schemas/conversation-interrupt).                           |
| `conversation.append_llm_context`    | `{ context }` | Appends to the conversation's LLM context. See [Append Context](/sections/event-schemas/conversation-append-context).     |
| `conversation.overwrite_llm_context` | `{ context }` | Replaces the conversation's LLM context. See [Overwrite Context](/sections/event-schemas/conversation-overwrite-context). |

## TavusIntegration helper (npm)

npm consumers get a typed wrapper around the element from the same package as the registration side effect:

```ts theme={null}
import "@tavus/embed";
import { TavusIntegration, type TavusInteraction } from "@tavus/embed";

// Pass the tag name to target: "tavus-embed" (default) or "tavus-widget".
const integration = new TavusIntegration("tavus-embed");

integration.on("tavus:conversation-started", (e) => {
  console.log("started", e.detail.conversationId);
});

integration.on("tavus:protocol-message", (e) => {
  console.log(e.detail);
});

const interaction: TavusInteraction = {
  event_type: "conversation.respond",
  properties: { text: "Tell me about pricing" },
};
integration.sendMessage(interaction);

// Plain strings are wrapped as conversation.respond for convenience.
integration.sendMessage("Tell me about pricing");
```

| Method                               | Description                                                                     |
| ------------------------------------ | ------------------------------------------------------------------------------- |
| `on(event, handler)`                 | Subscribes to a typed deployment event.                                         |
| `off(event, handler)`                | Removes a previously added handler.                                             |
| `sendMessage(interaction \| string)` | Sends a typed interaction. A plain string is wrapped as `conversation.respond`. |

The helper looks up the element by tag name in the DOM, so construct it (or make the first call) after the element exists on the page.

<Info>
  `TavusIntegration` is bundled into the ESM builds of `@tavus/widget` and `@tavus/embed` - no extra install. The CDN (IIFE) build stays a pure side-effect drop-in; CDN pages use the DOM APIs above instead.
</Info>
