Quem realmente fala com o seu chat de suporte com IA?

saas

Você colocou um widget de chat com IA no seu produto. Ele responde com base na sua central de ajuda, segura boa parte dos tickets, e as transcrições ficam todas numa lista. Você as lê na sexta à tarde.

E todas dizem Anônimo.

Você vê que alguém perguntou três vezes na mesma tarde como trocar o e-mail de cobrança. Não vê que era a mesma pessoa, que ela está no seu maior plano e que desistiu e cancelou na segunda-feira.

É essa lacuna que a identidade fecha.

O que um log anônimo mostra e o que não mostra

Uma transcrição anônima tem valor real. Ela mostra o que as pessoas perguntam, quais perguntas a sua documentação não responde e quais páginas confundem. É a base inteira do ciclo de escrever o artigo que falta, e ele funciona sem saber um único nome.

O que ela não faz é ligar uma conversa a qualquer outra coisa que você sabe.

  • Frequência por pessoa, não por sessão. Dez conversas sobre o mesmo recurso podem ser dez usuários confusos ou um só, muito insistente. As duas situações pedem respostas completamente diferentes, e um log anônimo não distingue uma da outra.

  • Quem é afetado. “Três pessoas perguntaram sobre o limite de requisições da API” soa diferente quando uma delas é a sua maior conta.

  • O acompanhamento. Um agente de suporte que abre um ticket não vê o que a IA já disse a esse cliente uma hora antes, então o cliente explica tudo duas vezes.

  • O sinal de cancelamento. Perguntas frustradas repetidas de uma mesma conta, nas duas semanas antes de ela cancelar, são um dos sinais mais claros que você vai ter. Sem identidade, ele fica invisível.

A ideia óbvia e por que ela é perigosa

O passo óbvio é dizer ao widget quem está logado. O seu app já sabe.

JavaScript
KookeeChat.identify({ id: user.id, email: user.email, name: user.name });

O perigo está no passo seguinte. É muito tentador pensar: o widget agora sabe quem é a pessoa, então o assistente pode responder perguntas sobre a conta dela. As faturas dela. O uso dela. Os tickets abertos dela.

Não faça isso. Tudo o que o navegador envia, a pessoa diante do navegador pode alterar. Basta abrir as ferramentas de desenvolvedor e chamar identify() com o e-mail de outra pessoa; se o assistente confiar nesse campo, você construiu um vazamento de dados com uma interface de chat por cima.

Esse tipo de bug não é hipotético. É o mesmo erro de confiar num id de usuário enviado pelo cliente numa requisição de API, e a correção é a mesma.

Identidade para rotular, autenticação para os dados

A saída é manter separadas duas coisas que parecem uma só.

Identidade é um rótulo. Ela diz a quem a conversa provavelmente pertence, para você agrupar, pesquisar e ler as transcrições. Ela não é verificada e não decide nada.

Autenticação é outra coisa, e ela já existe. O seu app autentica usuários. A sua API verifica sessões. Nada disso muda porque apareceu um widget de chat.

Então, quando o assistente realmente precisa de dados privados, ele não deve lê-los do campo de identidade. Deve chamar uma função que roda no navegador do próprio visitante, com o cookie de sessão do próprio visitante, contra a sua própria API:

JavaScript
KookeeChat.init({
  apiKey: 'YOUR_API_KEY',
  visitor: { id: user.id, email: user.email }, // um rótulo, para o seu painel
  tools: [
    {
      name: 'get_my_invoices',
      description: "Look up the signed-in customer's recent invoices.",
      parameters: { type: 'object', properties: {} },
      handler: () => fetch('/api/my/invoices', { credentials: 'include' }).then((r) => r.json()),
    },
  ],
});

Leia com atenção. Não é o campo visitor que torna isso seguro. É o credentials: 'include'. O seu servidor recebe uma requisição autenticada normal e aplica as mesmas regras que aplica em todo o resto. Se alguém falsificar o identify(), continua recebendo as próprias faturas, porque quem decide é o cookie.

Nesse trecho, o campo de identidade faz algo bem mais modesto: põe um nome numa linha do seu painel.

A parte que todo mundo esquece: o logout

Este é o bug que você vai lançar se implementar só o caminho feliz.

Alguém entra na conta num computador de biblioteca, faz três perguntas ao assistente sobre a própria conta e sai. A próxima pessoa senta, abre o chat, e a conversa anterior continua lá — porque o widget a guardou no navegador e ninguém avisou o widget de que algo tinha mudado.

Identidade não é só algo que você define. É algo que muda, e a mudança é o evento importante:

JavaScript
// no login
KookeeChat.identify({ id: user.id, email: user.email, name: user.name });

// no logout — não pule esta parte
KookeeChat.reset();

Um widget de chat com suporte a identidade precisa tratar a troca de pessoa como uma fronteira rígida: descartar a transcrição, começar uma nova sessão, não guardar nada. No Kookee isso acontece automaticamente quando a identidade passa para outra pessoa ou para ninguém. Mas o widget só reage ao que você informa, então a chamada reset() no logout é você quem escreve.

Há uma sutileza que vale conhecer, porque ela pega até quem acertou a chamada de logout. A maioria dos apps não sabe quem é o usuário na primeira renderização. Eles buscam a sessão e só então conseguem identificar alguém. Se “ainda não sei” e “ninguém está logado” parecem a mesma coisa para o widget, cada carregamento de página joga fora a conversa antes de a checagem de sessão terminar. Por isso os dois casos precisam ser distinguíveis: deixe o valor como undefined enquanto ainda está carregando e passe um null explícito quando souber que a resposta é ninguém.

O que enviar

Menos do que você imagina.

Você precisa de algo estável para agrupar. Um id de usuário do seu próprio banco de dados cumpre esse papel perfeitamente e não significa nada para quem não tem o seu banco. Um e-mail é mais útil no suporte, porque é por ele que você pesquisa quando um cliente escreve, mas também é dado pessoal, com prazo de retenção.

Um padrão razoável:

  • Sempre envie o id. É a chave de agrupamento, e é opaco.

  • Envie o e-mail se o seu fluxo de suporte pesquisa por ele. A maioria pesquisa.

  • Envie o nome, para facilitar a leitura. Com ele, o painel se lê de relance.

  • Não envie mais nada. Plano, papel e idade da conta parecem úteis, mas pertencem ao contexto que você dá ao assistente, não ao rótulo de identidade. Misturar os dois cria um repositório de dados pessoais que você não pretendia construir.

E registre isso na sua política de privacidade. Transcrições de chat já são dados pessoais; anexar um e-mail a elas não muda a categoria, mas muda o quanto isso fica evidente para um órgão regulador e para os seus usuários.

O assistente deve saber o nome?

Aqui surge uma ideia atraente: se o widget sabe que a visitante é a Alice, o assistente poderia começar com “Oi, Alice”.

O Kookee não faz isso, de propósito. A identidade fica salva com a conversa e nunca é enviada ao modelo. Dados pessoais não entram numa requisição ao modelo, a menos que você decida que devem entrar.

Se você quer a saudação, pode ter, mas precisa pedi-la explicitamente pelo campo de contexto separado, feito para o que o assistente deve saber:

JavaScript
KookeeChat.init({
  apiKey: 'YOUR_API_KEY',
  visitor: { id: user.id, email: user.email, name: user.name }, // o seu painel
  appContext: { firstName: user.firstName, plan: user.plan },   // o assistente
});

Dois campos, dois públicos. Parece duplicação até o dia em que alguém pergunta quais dados pessoais saem da sua infraestrutura, e você consegue responder com precisão.

O que você ganha

Quando as conversas têm identidade, perguntas comuns passam a ter resposta.

Pesquise o e-mail de um cliente nas transcrições antes de uma ligação de renovação e você vai saber o que o confundiu neste trimestre. Perceba a mesma conta perguntando a mesma coisa quatro vezes e você terá achado uma lacuna na documentação ou no onboarding. Entregue ao agente de suporte a conversa com a IA que veio antes do ticket, e o cliente para de se repetir.

Nada disso exige um assistente mais inteligente. Exige que o log pare de dizer Anônimo.


O widget de chat com IA do Kookee aceita a identidade do visitante tanto no pacote React quanto na tag script simples. Veja Identifique quem está conversando para as regras completas, incluindo exatamente quando uma conversa é descartada.