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

# Add to Website

> Adicione seu agente da Tig.ai a qualquer site para que os visitantes possam conversar com ele por voz ou por chat de texto.

### Como adicionar

Adicione seu agente a qualquer site usando o diálogo Configure Widget nas configurações do seu agente.

Etapa 1: Abra as configurações do agente clicando no ícone de engrenagem no canto superior direito do editor do agente.

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/open-settings.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=19c431e3193b74642cfd4d58a813172e" alt="Abrir configurações do agente" width="2880" height="1557" data-path="images/open-settings.png" />

Etapa 2: Role até a seção **Add to Website** e clique em **Configure Widget**.

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/add-to-website.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=9c6677dd76d51d238e3bbd4caeaffd84" alt="Ir para Add to Website" width="2850" height="1558" data-path="images/add-to-website.png" />

Etapa 3: Ative a incorporação, adicione o domínio do seu site em **Allowed Domains**, escolha um **Widget Type** (Voice ou Chat) e um modo de incorporação (**Floating Widget**, **Inline Component** ou **Headless (Bring Your Own UI)**), personalize o botão (posição, cor, texto) se aplicável e clique em **Save Configurations**.

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/save-configurations.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=7b16e6887fc444e62099954f98fcd285" alt="Salvar configurações" width="1974" height="1534" data-path="images/save-configurations.png" />

Etapa 4: Copie o código de incorporação gerado e cole-o na sua página web para testar seu agente.

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/copy-deployment-code.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=0ca4ff8606fa0f94f905dba52727d284" alt="Copiar código de implantação" width="2880" height="1537" data-path="images/copy-deployment-code.png" />

## Tipos de widget

Cada widget incorporado é um widget de voz ou um widget de chat — escolha o tipo no diálogo Configure Widget. Ambos os tipos suportam os três modos de incorporação.

| Tipo      | Como os visitantes interagem                                                                       |
| --------- | -------------------------------------------------------------------------------------------------- |
| **Voice** | Os visitantes falam com seu agente em uma chamada de áudio ao vivo (WebRTC, microfone necessário). |
| **Chat**  | Os visitantes digitam mensagens em um painel de chat e o agente responde em texto. Sem microfone.  |

Como as conversas de chat se comportam:

* A conversa começa quando o visitante abre o chat (clica no botão de chat) — o agente cumprimenta primeiro. Apenas carregar a página nunca inicia uma conversa.
* Uma sessão de chat dura até **1 hora**. Quando ela expira, é oferecido ao visitante um botão **Start new chat**, que inicia uma nova conversa.
* Recarregar a página inicia uma nova conversa na próxima abertura — o histórico do chat não é levado entre carregamentos de página.
* Cada conversa conta uma vez no limite de uso do token de incorporação, o mesmo que uma chamada de voz.
* As conversas de chat aparecem no histórico de chamadas do seu agente com transcrição completa.

## Modos de incorporação

| Modo                 | O que renderiza                                                                                                      | Quando usar                                                                                                    |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Floating Widget**  | Um botão de CTA em formato de pílula ancorado a um canto da página. Para widgets de chat, alterna um painel de chat. | Você quer uma experiência pronta que não perturbe o layout existente.                                          |
| **Inline Component** | Um painel renderizado dentro de uma `<div id="tig-inline-container">` que você coloca na sua página.                 | Você quer o agente incorporado em uma seção específica (hero da landing page, aba de suporte etc.).            |
| **Headless**         | Sem UI. Apenas o pipeline de áudio/chat mais uma API JavaScript em `window.TigWidget`.                               | Você quer controle total sobre a UI — seus próprios botões, sistema de design, estado do framework, animações. |

## Pré-requisitos

Estes se aplicam aos três modos:

* **Widgets de voz:** sirva sua página por **HTTPS** ou a partir de `http://localhost`. Os navegadores recusam acesso ao microfone em origens HTTP simples ou `file://`. Os widgets de chat não exigem microfone, embora HTTPS ainda seja recomendado.
* Se você definir **Allowed Domains** no painel, inclua sua origem de teste (por exemplo, `localhost`) — caso contrário, as requisições do widget são rejeitadas. Deixe a lista vazia para permitir todos os domínios.
* O trecho de código que você copia do painel é uma única tag `<script>` que carrega `tig-widget.js` **assincronamente**. O widget se inicializa automaticamente quando carrega e expõe `window.TigWidget`. O código que registra callbacks deve aguardar o widget estar disponível.

## Passar contexto para o agente

Sua página geralmente sabe algo sobre o visitante — o nome, o plano, o valor do carrinho, o artigo que ele estava lendo. Passe essas informações e seu agente poderá usá-las desde a primeira palavra.

<Warning>
  Os nomes de chaves de Contexto não podem conter pontos, espaços, barras verticais ou chaves, pois esses
  caracteres têm significado estrutural nas expressões de template. Entradas inválidas são
  descartadas sem impedir que a conversa comece.
</Warning>

O trecho de código que você copia do painel carrega um atributo `data-tig-context` — um objeto JSON com detalhes do visitante. O trecho é uma pequena função de bootstrap: `js` é o elemento `<script>` do widget que ela cria, e o contexto é anexado a esse elemento antes de ser adicionado à página. A parte relevante do trecho gerado se parece com isto (mantenha o valor `js.src` gerado, que contém seu token de incorporação):

```html theme={null}
<script>
  (function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s);
    js.id = id;
    js.src = '<dashboard-generated widget URL>';
    js.setAttribute('data-tig-context', JSON.stringify({
      page_url: window.location.href,
      today: new Date().toISOString().slice(0, 10)
    }));
    js.async = true;
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'tig-widget'));
</script>
```

Como isso é construído em JavaScript no carregamento da página, você pode colocar qualquer coisa que sua página saiba — o nome de um cliente logado, seu plano, o conteúdo do carrinho. Substitua o objeto dentro de `JSON.stringify(...)` no trecho gerado, por exemplo:

```js theme={null}
{
  customer_name: currentUser.firstName,
  plan: currentUser.plan,
  cart: { items: cart.length, total: cart.total }
}
```

Cada chave fica então disponível em qualquer prompt de nó como `{{initial_context.<name>}}`:

```text theme={null}
Greet {{initial_context.customer_name | there}} and mention their {{initial_context.plan}} plan.
```

Os valores podem ser strings, números, booleanos ou objetos aninhados. Isso funciona tanto para widgets de voz quanto de chat, e os valores são registrados na conversa para que você possa ver o que foi dado ao agente.

### Atualizar o contexto depois que a página carrega

O atributo é fixo no carregamento da página, o que não se adapta a uma aplicação de página única — o visitante faz login, muda de rota ou preenche um carrinho muito depois de o trecho rodar. Para isso, chame `setContext()`:

```js theme={null}
window.TigWidget.setContext({
  customer_name: user.firstName,
  plan: user.plan
});
```

Cada chamada mescla os dados no contexto já coletado, então você pode adicionar detalhes conforme eles chegam e reenviar um nome para corrigi-lo. `getContext()` retorna o conjunto atual.

O contexto é lido quando uma conversa começa, então `setContext()` se aplica à **próxima** conversa — chamá-lo no meio de uma chamada ou chat não altera a conversa em andamento (o widget registra um aviso no console se você fizer isso). Para widgets de chat, "próxima" inclui a nova conversa iniciada por **Start new chat** depois que uma sessão expira.

<Note>
  O script do widget carrega assincronamente, então `window.TigWidget` pode ainda não existir quando o código do seu aplicativo rodar pela primeira vez. Chame `setContext()` a partir de um evento que dispara após o carregamento — um listener de `window.load` ou uma ação do usuário, como clicar no seu próprio botão "Fale conosco". Consulte [Lifecycle callbacks](#lifecycle-callbacks-todos-os-modos) para a mesma regra de temporização.
</Note>

Use o que for adequado: `data-tig-context` para o que a página sabe na renderização, `setContext()` para o que ela aprende depois. Eles se mesclam, e `setContext()` vence em um nome repetido.

<Warning>
  O contexto vem da página, então um visitante pode tanto lê-lo quanto alterá-lo antes que ele chegue ao seu agente. Nunca passe segredos e não deixe que isso controle o que o agente fará ou divulgará — trate `plan: "pro"` como uma dica de tom, não como prova de direito. Para dados que o agente deve confiar, passe um id opaco como `customer_id` e deixe a Tig.ai buscar os detalhes reais na sua API com [Pre-Call Data Fetch](/pt/voice-agent/pre-call-data-fetch).
</Warning>

Limites, aplicados por conversa: até 50 variáveis, 64 caracteres por nome, 2000 caracteres por valor e 8 KB no total. Qualquer coisa além do limite é descartada e a conversa ainda começa. Os nomes `provider` e `runtime_configuration` são reservados e ignorados.

## Floating Widget

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/floating-widget-example.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=0bd32f2b54e310979a8602f0de3cddac" alt="Widget flutuante mostrado no canto de uma página host" width="2880" height="1555" data-path="images/floating-widget-example.png" />

Renderiza um botão em formato de pílula ancorado a um canto da página.

* **Voz:** clicar no botão (ícone de microfone + texto) inicia uma chamada; clicar novamente a encerra. O botão atualiza automaticamente o rótulo e a cor ao longo do ciclo de vida da chamada: texto configurado → "Connecting…" → "End Call" → "Retry" em caso de falha.
* **Chat:** clicar no botão (ícone de chat + texto) abre um painel de chat ancorado ao mesmo canto; o agente cumprimenta o visitante e a conversa acontece no painel. Clicar no botão (ou no × do painel) fecha o painel sem encerrar a conversa — reabrir mostra a mesma transcrição.

Configure **Button Text**, **Button Color** e **Position** (cima/baixo + esquerda/direita) a partir do painel.

Todas as outras palavras que um visitante vê também são editáveis, em uma seção recolhível do mesmo diálogo, para que você possa rodar o widget no idioma do seu site: **Chat Panel Text** para widgets de chat (botão de encerrar chat, mensagem de conversa encerrada, botões de iniciar novo chat e tentar novamente, placeholder de mensagem e rótulos de leitor de tela de enviar/fechar), ou **Voice Call Text** para widgets de voz. Deixe um campo em branco para manter o padrão em inglês.

A página host não escreve nenhum JavaScript — colar o trecho de incorporação é a integração inteira. Se você quiser assinar os eventos do ciclo de vida da chamada (por exemplo, para análise), veja [Lifecycle callbacks](#lifecycle-callbacks-todos-os-modos) abaixo.

## Inline Component

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/inline-widget-example.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=0114babe549c9cd0553f3925aab6975c" alt="Widget inline renderizado dentro de uma seção da página" width="2844" height="1555" data-path="images/inline-widget-example.png" />

Renderiza um painel dentro de uma `<div>` que você coloca na sua página.

* **Voz:** um painel de status (ícone de status + texto de status + botão de CTA). As mudanças de status atualizam o painel no lugar.
* **Chat:** uma tela de chamada para ação primeiro; clicar no botão a substitui por um painel de chat que preenche o contêiner. Nenhum JavaScript extra é necessário.

Configure **Button Text**, **Button Color** e **Call to Action Text** a partir do painel, além da seção **Chat Panel Text** / **Voice Call Text** descrita em [Floating Widget](#floating-widget). Os widgets de voz inline mostram mais texto do que qualquer outro modo — um título e um subtítulo para cada estado: ready, connecting, connected, ended, failed e lost — então essa seção carrega o conjunto completo aqui.

### HTML simples

Coloque uma `<div>` de contêiner onde você quer que o widget seja renderizado. O widget se anexa automaticamente a ela.

```html theme={null}
<!-- Paste the tig embed snippet from the dashboard somewhere on the page -->
<div id="tig-inline-container"></div>
```

### React

Como o React monta depois que o script do widget pode já ter carregado, integre via `initInline` na primeira montagem e `refresh` na remontagem. Conte com polling de `window.TigWidget` para lidar com o carregamento assíncrono do script.

```tsx theme={null}
import { useEffect } from 'react';

declare global {
  interface Window {
    TigWidget?: {
      initInline: (options: { container: HTMLElement }) => void;
      refresh: () => void;
      getState: () => { isInitialized: boolean };
    };
  }
}

export function Assistant() {
  useEffect(() => {
    let retries = 0;
    const tryInit = () => {
      const container = document.getElementById('tig-inline-container');
      if (window.TigWidget && container) {
        const { isInitialized } = window.TigWidget.getState();
        if (isInitialized) window.TigWidget.refresh();
        else window.TigWidget.initInline({ container });
      } else if (retries++ < 50) {
        setTimeout(tryInit, 100);
      }
    };
    tryInit();
  }, []);

  return <div id="tig-inline-container" />;
}
```

## Modo Headless

<img src="https://mintcdn.com/callguard/w-VUnJAq_m6hhmzP/images/headless-widget-example.png?fit=max&auto=format&n=w-VUnJAq_m6hhmzP&q=85&s=aa1c0968a879ee295a0886985849da0a" alt="Widget headless controlado pela UI da página host" width="2842" height="1548" data-path="images/headless-widget-example.png" />

No modo Headless, o widget não injeta nenhuma UI própria. Você renderiza os botões, banners ou interfaces de chat que quiser e controla o agente por meio da API JavaScript.

### API JavaScript (widgets de voz)

| Método / Callback                         | Descrição                                                                                                                                                                                      |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `window.TigWidget.start()`                | Inicia uma chamada de voz. Deve ser chamado de dentro de um manipulador de gesto do usuário (por exemplo, `click`) para que o navegador conceda acesso ao microfone.                           |
| `window.TigWidget.end()`                  | Encerra a chamada ativa.                                                                                                                                                                       |
| `window.TigWidget.onCallStart(cb)`        | Dispara quando `start()` é invocado (status `connecting`). Sem payload.                                                                                                                        |
| `window.TigWidget.onCallConnected(cb)`    | Dispara quando a conexão WebRTC é estabelecida. Payload: `{ agentId, workflowRunId, token }`.                                                                                                  |
| `window.TigWidget.onCallDisconnected(cb)` | Dispara somente se a chamada tiver se conectado, quando o teardown roda. Payload: `{ agentId, workflowRunId, token, durationSeconds }`.                                                        |
| `window.TigWidget.onCallEnd(cb)`          | Dispara sempre que a sessão da chamada é derrubada (incluindo tentativas que falharam ao conectar). Sem payload.                                                                               |
| `window.TigWidget.onStatusChange(cb)`     | Dispara a cada mudança de status. O callback recebe `(status, text, subtext)`. Valores de status: `idle`, `connecting`, `connected`, `failed`.                                                 |
| `window.TigWidget.onError(cb)`            | Dispara em erros (permissão de microfone negada, erro de servidor etc.). O callback recebe um objeto `Error`.                                                                                  |
| `window.TigWidget.setContext(vars)`       | Mescla o contexto do visitante para a próxima chamada — veja [Passar contexto para o agente](#passar-contexto-para-o-agente). Funciona em todos os modos de incorporação, não apenas headless. |

Todos os setters `on*` são de listener único — chamar o mesmo novamente substitui o manipulador anterior.

### API JavaScript (widgets de chat)

| Método / Callback                        | Descrição                                                                                                                                                                                       |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `window.TigWidget.startChat()`           | Inicia uma conversa. A saudação do agente chega via `onMessage`.                                                                                                                                |
| `window.TigWidget.sendMessage(text)`     | Envia uma mensagem do visitante. Retorna uma Promise que resolve com a transcrição atualizada (array de turnos) ou `null` se a mensagem não puder ser entregue.                                 |
| `window.TigWidget.getMessages()`         | Transcrição atual como um array de turnos: `{ id, status, user_message, assistant_message }`, sendo cada mensagem `{ text, created_at }`.                                                       |
| `window.TigWidget.onMessage(cb)`         | Dispara uma vez por nova resposta do agente. O callback recebe `(text, turn)`.                                                                                                                  |
| `window.TigWidget.onChatStateChange(cb)` | Dispara a cada mudança de estado do chat. Estados: `idle`, `starting`, `ready`, `waiting` (o agente está respondendo), `ended`, `expired`, `error`.                                             |
| `window.TigWidget.onError(cb)`           | Dispara em erros. O callback recebe um objeto `Error`.                                                                                                                                          |
| `window.TigWidget.setContext(vars)`      | Mescla o contexto do visitante para a próxima conversa — veja [Passar contexto para o agente](#passar-contexto-para-o-agente). Funciona em todos os modos de incorporação, não apenas headless. |

No modo chat, `start()` é um alias de `startChat()` e `end()` é um teardown no-op (sessões de chat não precisam de um), para que trechos genéricos continuem funcionando. Os envios são serializados — `sendMessage` enquanto uma resposta está pendente (`waiting`) resolve para `null`.

```html theme={null}
<button id="open-chat">Chat with us</button>
<div id="transcript"></div>
<input id="chat-input" /><button id="send-btn">Send</button>

<script>
  window.addEventListener('load', () => {
    window.TigWidget.onMessage((text) => {
      const p = document.createElement('p');
      p.textContent = 'Agent: ' + text;
      document.getElementById('transcript').appendChild(p);
    });

    document.getElementById('open-chat').addEventListener('click', () => {
      window.TigWidget.startChat();
    });

    document.getElementById('send-btn').addEventListener('click', async () => {
      const input = document.getElementById('chat-input');
      const p = document.createElement('p');
      p.textContent = 'You: ' + input.value;
      document.getElementById('transcript').appendChild(p);
      await window.TigWidget.sendMessage(input.value);
      input.value = '';
    });
  });
</script>
```

<Note>
  **Sobre a temporização.** O script do widget carrega assincronamente, então `window.TigWidget` pode não existir no momento em que seu `<script>` inline roda pela primeira vez. Os exemplos abaixo assumem que `window.TigWidget` já está disponível quando o registro roda. Para garantir isso:

  * **Vanilla JS:** envolva seu código de registro em `window.addEventListener('load', () => { /* registrar aqui */ })`.
  * **React:** dentro de `useEffect`, registre imediatamente se `document.readyState === 'complete'`; caso contrário, adicione um listener `window.load` de uso único que registra ao disparar.
  * **Manipuladores de clique** que chamam `start()` / `end()` não precisam de guarda — quando o usuário clica, o widget já carregou há muito tempo.
</Note>

### Vanilla JS

```html theme={null}
<button id="talk-btn">Talk to AI</button>

<script>
  let callStatus = 'idle';
  const btn = document.getElementById('talk-btn');

  function render() {
    btn.textContent =
      callStatus === 'connected' ? 'End Call'
      : callStatus === 'connecting' ? 'Connecting…'
      : callStatus === 'failed' ? 'Retry'
      : 'Talk to AI';
  }

  window.TigWidget.onStatusChange((status) => {
    callStatus = status;
    render();
  });

  window.TigWidget.onError((err) => {
    console.error('Tig.ai error:', err.message);
  });

  btn.addEventListener('click', () => {
    if (callStatus === 'connected' || callStatus === 'connecting') {
      window.TigWidget.end();
    } else {
      window.TigWidget.start();
    }
  });
</script>
```

### React + TypeScript

```tsx theme={null}
import { useEffect, useState } from 'react';

type CallStatus = 'idle' | 'connecting' | 'connected' | 'failed';

declare global {
  interface Window {
    TigWidget: {
      start: () => void;
      end: () => void;
      onStatusChange: (cb: (status: CallStatus, text?: string, subtext?: string) => void) => void;
      onError: (cb: (err: Error) => void) => void;
    };
  }
}

export function TalkButton() {
  const [status, setStatus] = useState<CallStatus>('idle');

  useEffect(() => {
    window.TigWidget.onStatusChange((s) => setStatus(s));
    window.TigWidget.onError((err) => console.error('Tig.ai error:', err.message));
  }, []);

  const isLive = status === 'connected' || status === 'connecting';
  const label = { idle: 'Talk to AI', connecting: 'Connecting…', connected: 'End Call', failed: 'Retry' }[status];

  return (
    <button onClick={() => (isLive ? window.TigWidget.end() : window.TigWidget.start())}>
      {label}
    </button>
  );
}
```

<Note>
  `start()` deve rodar dentro de um manipulador de gesto do usuário real (`click`, `touchend` etc.). Os navegadores recusam conceder acesso ao microfone aos scripts que o solicitam fora de um — chamar `start()` a partir de um `setTimeout` ou no carregamento da página falhará com um erro de permissão.
</Note>

## Lifecycle callbacks (todos os modos)

Os callbacks `on*` da [API JavaScript Headless](#api-javascript-widgets-de-voz) funcionam em **todos os três modos de incorporação**, não apenas no Headless. Use-os para análise ou para disparar UI na página host mesmo quando o widget estiver renderizando sua própria UI (Floating ou Inline). Os callbacks de chamada (`onCall*`) disparam para widgets de voz; para widgets de chat, use `onMessage` e `onChatStateChange` da mesma forma.

```js theme={null}
window.TigWidget.onCallConnected(({ agentId, workflowRunId }) => {
  analytics.track('voice_call_started', { agentId, workflowRunId });
});

window.TigWidget.onCallDisconnected(({ workflowRunId, durationSeconds }) => {
  analytics.track('voice_call_ended', { workflowRunId, durationSeconds });
});
```

`onCallConnected` e `onCallDisconnected` só disparam quando a chamada realmente estabelece uma conexão de mídia — tentativas que falharam ao conectar (por exemplo, microfone negado, falha de rede) não os acionam, então a análise permanece limpa.
