Blog

Sinal de abandono no chat: detectar a desistência antes do cliente sumir

O cliente insatisfeito que reclama é o barato de tratar: ele diz o que está errado, aceita uma correção e continua na conversa. O caro é o que simplesmente para de responder. Não abre chamado, não avalia o atendimento, não aparece em nenhuma métrica de qualidade, e o sistema registra a conversa como concluída porque tecnicamente ninguém a interrompeu. Esse é o abandono silencioso, e ele costuma ser a maior fatia de perda de um atendimento automatizado justamente porque é invisível por construção. Este artigo mostra por que o abandono não é um evento e sim a ausência de um, como transformar essa ausência em sinal usando evidência que já existe no fluxo, qual é a diferença entre um cliente que desistiu e um que só foi almoçar, como decidir se vale intervir antes do silêncio e por que a intervenção errada acelera exatamente a saída que ela tentava evitar.

2026-08-18 / IA Aplicada / 15 min

01

Abandono não é um evento, é a ausência de um

Todo sistema de atendimento sabe registrar o que acontece. Mensagem recebida, resposta enviada, transferência para humano, avaliação preenchida. O abandono não é nada disso: é o momento em que a próxima mensagem esperada não chega. Como não existe um evento correspondente, ele não pode ser capturado por um handler, e é por isso que a maior parte dos times descobre o problema meses depois, ao cruzar o funil de conversas com o de conversões e notar que um terço das conversas termina sem desfecho registrado.

A consequência prática é que detectar abandono exige inverter a arquitetura do fluxo. Em vez de reagir a mensagens, o sistema precisa agendar uma verificação futura a cada turno e cancelá-la quando o cliente responde. O abandono é o disparo dessa verificação sem cancelamento. Isso parece detalhe de implementação, mas define tudo o que vem depois: significa que a detecção tem custo por conversa aberta e não por mensagem trocada, e que qualquer política de abandono precisa ser barata o suficiente para rodar sobre cem por cento do tráfego.

turno N: cliente envia mensagem
   |
   +-- cancela verificacao pendente da conversa
   +-- agente responde
   +-- agenda verificacao em T (deadline de silencio)
   |
   +--> cliente responde antes de T
   |       -> cancela, volta ao turno N+1, conversa saudavel
   |
   +--> T expira sem resposta
           -> avalia estado no momento do silencio
              |
              +-- desfecho ja alcancado -> conclusao natural, nao e abandono
              +-- sem desfecho + risco baixo -> abandono passivo, so registra
              +-- sem desfecho + risco alto  -> abandono ativo, dispara acao

O ramo mais importante do diagrama é o primeiro do bloco de expiração, e é o que quase todo time esquece. Silêncio depois de "obrigado, era isso mesmo" não é abandono, é encerramento. Contar os dois juntos produz uma taxa de abandono inflada que ninguém consegue acionar, porque metade dela é composta de conversas bem-sucedidas. A primeira coisa a fazer antes de medir abandono é definir o que conta como desfecho no seu domínio, e essa definição é de produto, não de engenharia.

02

Silêncio não é desistência: separar pausa de saída

O erro mais comum na primeira versão de uma detecção de abandono é usar um único tempo de silêncio para tudo. Trinta segundos sem resposta num chat de site é anormal, e trinta minutos no WhatsApp é completamente normal, porque o canal é assíncrono por natureza e o cliente foi almoçar. Um limiar fixo aplicado a canais diferentes produz falso positivo em massa no canal assíncrono e falso negativo no síncrono, e o time conclui que a métrica não funciona quando o que não funciona é o limiar.

O limiar precisa ser derivado da distribuição real de intervalos entre turnos, por canal e por etapa da conversa. Um bom ponto de partida é o percentil noventa dos intervalos observados em conversas que terminaram com desfecho positivo: se noventa por cento das pausas de clientes que resolveram o problema são menores que quatro minutos, uma pausa de doze minutos naquele canal carrega informação. E o limiar precisa variar por etapa, porque a pausa depois de uma pergunta simples significa algo bem diferente da pausa depois de um pedido de dado sensível, em que o cliente legitimamente saiu para procurar um documento.

CanalEtapa da conversaSilêncio esperado (p90)Limiar de riscoLeitura do silêncio
Widget no sitePergunta inicial40 s3 minAlta chance de saída, aba fechada
Widget no siteColeta de dado cadastral90 s6 minPode estar buscando informação
WhatsAppPergunta inicial4 min25 minAssíncrono, pausa é comum
WhatsAppConfirmação de pagamento2 min10 minHesitação, não distração
App autenticadoDiagnóstico técnico3 min15 minCliente pode estar testando
E-mailQualquer etapa4 h48 hSilêncio não é sinal útil

A última linha existe para deixar explícito que o e-mail é o caso em que a detecção por silêncio simplesmente não paga. Quando o canal é lento por natureza, o intervalo entre turnos carrega tão pouca informação sobre a intenção do cliente que qualquer limiar vira ruído, e o esforço deve ir para sinais de conteúdo. Reconhecer onde a técnica não se aplica economiza um trimestre de ajuste de parâmetro que nunca convergiria.

03

Sinais que aparecem antes do silêncio

Silêncio é o sinal mais tardio possível: quando ele chega, o cliente já decidiu. O valor real está nos sinais que precedem a decisão, e todos eles já existem no fluxo sem instrumentação nova. Três famílias cobrem quase tudo. A primeira é comportamental e mede como o cliente escreve: latência de resposta subindo turno a turno, mensagens encurtando, uso de monossílabos onde antes havia frases. A segunda é semântica e mede o conteúdo: repetição da mesma pergunta com outras palavras, marcadores explícitos de frustração, pedido de humano. A terceira é estrutural e mede a conversa como um todo: número de turnos acima do esperado para aquela intenção, ausência de progresso em direção ao desfecho.

A tentação óbvia é jogar tudo isso num modelo e pedir uma probabilidade de abandono. Vale resistir a ela na primeira versão, por dois motivos. O primeiro é que não existe rótulo confiável no começo: o cliente que sumiu não disse por que sumiu, então o alvo de treino precisa ser construído por proxy, e um proxy ruim ensina o modelo a prever a definição em vez do fenômeno. O segundo é operacional: um escore de modelo não é explicável na hora do incidente, e um escore aditivo simples é auditável, ajustável e suficiente para pegar a maior parte do sinal.

// abandonment/risk-score.js
// Escore aditivo de risco de abandono, calculado a cada turno do cliente.
// Deliberadamente sem modelo: cada componente e auditavel e ajustavel
// isoladamente, o que importa quando a operacao contesta um disparo.

const SIGNAL_WEIGHTS = {
  latencyTrend: 25,      // cliente demorando cada vez mais para responder
  messageShrink: 15,     // mensagens encurtando ao longo da conversa
  repetition: 30,        // mesma pergunta reformulada, agente nao resolveu
  frustration: 20,       // marcador lexical explicito de irritacao
  turnOverrun: 10,       // conversa mais longa que o esperado para a intencao
};

// Tendencia de latencia: compara a mediana dos 3 ultimos intervalos com a
// dos 3 primeiros. Mediana, e nao media, porque uma unica pausa longa
// (o cliente atendeu o telefone) nao deve dominar o sinal.
function latencyTrendSignal(gapsMs) {
  if (gapsMs.length < 6) return 0;
  const median = (xs) => {
    const s = [...xs].sort((a, b) => a - b);
    const mid = Math.floor(s.length / 2);
    return s.length % 2 ? s[mid] : (s[mid - 1] + s[mid]) / 2;
  };
  const early = median(gapsMs.slice(0, 3));
  const recent = median(gapsMs.slice(-3));
  if (early === 0) return 0;
  const ratio = recent / early;
  // Abaixo de 2x e variacao normal. Acima de 4x satura: dobrar de novo
  // nao carrega mais informacao, e deixar crescer sem teto faz um unico
  // componente decidir o escore sozinho.
  return Math.max(0, Math.min(1, (ratio - 2) / 2));
}

// Encurtamento: razao entre o tamanho medio das ultimas mensagens e das
// primeiras. "ok" depois de tres paragrafos e desengajamento.
function messageShrinkSignal(lengths) {
  if (lengths.length < 4) return 0;
  const avg = (xs) => xs.reduce((a, b) => a + b, 0) / xs.length;
  const early = avg(lengths.slice(0, 2));
  const recent = avg(lengths.slice(-2));
  if (early === 0) return 0;
  return Math.max(0, Math.min(1, 1 - recent / early));
}

// Repeticao: o cliente reformulou a mesma pergunta. Similaridade por
// trigramas de caractere e barata e resiste a variacao de escrita,
// o que embedding tambem faz, mas custando uma chamada de rede por turno.
function jaccardTrigrams(a, b) {
  const grams = (s) => {
    const t = s.toLowerCase().replace(/\s+/g, ' ').trim();
    const out = new Set();
    for (let i = 0; i + 3 <= t.length; i += 1) out.add(t.slice(i, i + 3));
    return out;
  };
  const ga = grams(a);
  const gb = grams(b);
  if (ga.size === 0 || gb.size === 0) return 0;
  let inter = 0;
  for (const g of ga) if (gb.has(g)) inter += 1;
  return inter / (ga.size + gb.size - inter);
}

function repetitionSignal(customerMessages) {
  if (customerMessages.length < 2) return 0;
  const last = customerMessages[customerMessages.length - 1];
  let best = 0;
  // So compara com os 5 anteriores: repetir algo dito 20 turnos atras
  // e retomada de assunto, nao insistencia.
  for (const prev of customerMessages.slice(-6, -1)) {
    best = Math.max(best, jaccardTrigrams(last, prev));
  }
  // Abaixo de 0.45 e coincidencia de vocabulario do dominio.
  return best < 0.45 ? 0 : Math.min(1, (best - 0.45) / 0.35);
}

export function computeAbandonmentRisk({
  gapsMs,
  messageLengths,
  customerMessages,
  frustrationHits,
  turnCount,
  expectedTurns,
}) {
  const components = {
    latencyTrend: latencyTrendSignal(gapsMs),
    messageShrink: messageShrinkSignal(messageLengths),
    repetition: repetitionSignal(customerMessages),
    frustration: Math.min(1, frustrationHits / 2),
    turnOverrun:
      expectedTurns > 0 ? Math.max(0, Math.min(1, (turnCount - expectedTurns) / expectedTurns)) : 0,
  };

  const score = Object.entries(components).reduce(
    (acc, [key, value]) => acc + value * SIGNAL_WEIGHTS[key],
    0,
  );

  // Retorna os componentes junto com o total: sem isso, ninguem consegue
  // responder "por que essa conversa disparou" durante um incidente.
  return { score: Math.round(score), components };
}

Dois detalhes desse código carregam quase todo o aprendizado de produção. O primeiro é a saturação em cada componente: sem teto, uma única conversa com pausa de duas horas produz um escore astronômico e monopoliza a fila de intervenção. O segundo é o retorno dos componentes junto do total. Escore sem decomposição é impossível de defender quando a operação pergunta por que uma conversa saudável foi marcada, e a resposta "o modelo achou" encerra a credibilidade da feature na primeira semana.

04

Do sinal à ação: intervir sem estragar a conversa

Detectar sem agir gera um painel bonito e nenhum resultado, mas agir errado é pior que não agir. A intervenção mais comum é também a menos eficaz: mandar "ainda está aí?" quando o silêncio passa do limiar. Essa mensagem não adiciona informação nenhuma, transfere ao cliente o custo de responder algo que não interessa a ele e, num canal com notificação, interrompe alguém que talvez fosse voltar sozinho. Ela converte pausa em saída com frequência maior do que se imagina.

A regra que funciona é que toda intervenção precisa carregar valor novo. Se o sistema não tem nada a acrescentar, o certo é não dizer nada e apenas registrar. E o valor novo quase sempre vem de responder à causa do risco, não ao silêncio em si, que é onde a decomposição do escore deixa de ser diagnóstico e vira roteamento.

Componente dominanteInterpretaçãoAção recomendadaO que não fazer
RepetiçãoO agente não resolveu e o cliente insisteOferecer transbordo para humano com o contexto prontoReformular a mesma resposta com outras palavras
FrustraçãoO cliente está irritado com o atendimentoEscalar imediatamente, sem passo intermediárioPedir avaliação ou oferecer autoatendimento
Latência crescenteAtenção dispersa, não necessariamente insatisfaçãoNada no primeiro limiar, resumo do estado no segundoMandar lembrete curto a cada limiar
Encurtamento de mensagemDesengajamento, o cliente está encerrandoOferecer um caminho de saída útil e assíncronoInsistir com nova pergunta aberta
Excesso de turnosA conversa não converge para o desfechoPropor mudança de canal ou agendamentoContinuar o mesmo fluxo por mais turnos

A linha de latência crescente é a que mais economiza dinheiro e a que mais gente implementa errado. Silêncio isolado, sem nenhum outro sinal, quase sempre é pausa e a melhor ação é ausência de ação. Só faz sentido intervir no segundo limiar, e com uma mensagem que devolve o estado da conversa em vez de perguntar se o cliente continua ali, porque o resumo permite retomar sem reler tudo e o "ainda está aí?" só cobra uma resposta.

05

Medir se a intervenção funcionou, não se ela disparou

A métrica que quase todo time coloca no painel primeiro é o número de intervenções disparadas, e ela não significa absolutamente nada sobre valor. O que importa é a diferença de desfecho entre conversas em risco que receberam intervenção e conversas em risco que não receberam. Isso exige manter um grupo de controle permanente: uma fatia do tráfego em que o risco é calculado e registrado, mas nenhuma ação é tomada.

O controle permanente incomoda porque parece deixar dinheiro na mesa de propósito, e é exatamente o que faz. A alternativa é pior: sem ele, a taxa de recuperação observada mistura o efeito da intervenção com o efeito dos clientes que voltariam de qualquer forma, e essa parcela costuma ser grande. Um controle de cinco por cento é suficiente para medir o efeito e barato o bastante para não ser questionado no fim do trimestre.

  1. Defina o que conta como desfecho por tipo de conversa antes de qualquer coisa, porque abandono é a ausência de desfecho e sem essa definição a métrica não existe.
  2. Meça a distribuição real de intervalos entre turnos por canal e por etapa, e derive os limiares dela em vez de escolher um número redondo.
  3. Implemente a verificação agendada com cancelamento no turno seguinte, garantindo idempotência para que reentrega de mensagem não dispare duas vezes.
  4. Comece com escore aditivo e componentes visíveis, deixando modelo para quando houver rótulo confiável acumulado.
  5. Roteie a ação pelo componente dominante do escore, nunca pelo total, porque o total não diz o que fazer.
  6. Mantenha um grupo de controle permanente de cinco por cento, sem o qual a taxa de recuperação é impossível de interpretar.
  7. Acompanhe a taxa de intervenção sobre conversas que terminariam bem, que é o custo real da política e o primeiro número a piorar quando o limiar fica agressivo demais.

O último item merece um alarme próprio. Uma política de abandono agressiva demais não falha de forma visível: ela produz mais mensagens, mais notificações e uma leve queda na satisfação que ninguém atribui à causa certa. O único jeito de enxergar isso é medir quantas conversas que atingiram desfecho positivo receberam intervenção pelo caminho. Se esse número passar de dez por cento, o limiar está errado e o sistema está incomodando gente que estava sendo bem atendida.

Vale fechar reconhecendo o limite da técnica. Detecção de abandono não conserta um agente que responde mal, não substitui um fluxo de transbordo que funcione e não recupera cliente que desistiu por preço. Ela faz uma coisa só, e faz bem: transforma uma perda invisível em uma perda mensurável, com causa atribuída. A decisão sobre o que fazer com essa informação continua sendo de produto, mas pela primeira vez é uma decisão tomada com dado em vez de intuição.

FAQ

Perguntas frequentes

Qual é o tempo certo de silêncio para considerar uma conversa abandonada?

Não existe um número universal, e adotar um é a causa mais comum de a métrica não funcionar. O intervalo esperado entre turnos varia por canal em mais de uma ordem de grandeza: num widget de site, quarenta segundos de silêncio já é anormal porque o cliente está com a aba aberta na frente dele; no WhatsApp, quinze minutos é completamente rotineiro porque o canal é assíncrono e ninguém fica olhando a tela. O limiar precisa ser derivado da distribuição observada no seu tráfego, e um ponto de partida sólido é o percentil noventa dos intervalos em conversas que terminaram com desfecho positivo, com uma folga que evita disparar sobre comportamento normal. Além do canal, a etapa importa: a pausa depois de um pedido de número de documento significa que o cliente foi procurar o documento, e a pausa depois de uma pergunta simples significa outra coisa. E há canais em que o silêncio simplesmente não é sinal útil, como e-mail, onde vale ignorar o tempo e olhar apenas conteúdo.

Vale a pena treinar um modelo para prever abandono em vez de usar regras?

Vale, mas quase nunca como primeira versão, e o motivo é a falta de rótulo confiável. O cliente que sumiu não disse por que sumiu, então qualquer alvo de treino inicial é um proxy construído por você, e um proxy ruim ensina o modelo a prever a sua definição em vez do fenômeno real. Há um segundo motivo, operacional: no dia em que a operação contestar um disparo, um escore de modelo não é explicável e um escore aditivo é. Um escore com cinco componentes visíveis, cada um saturado individualmente, captura a maior parte do sinal disponível e permite ajustar um peso isolado quando um canal se comporta diferente. O modelo passa a valer quando existir volume de rótulo derivado de intervenção real, ou seja, quando você já souber quais conversas em risco voltaram após ação e quais voltariam sozinhas. Esse rótulo só se acumula se houver grupo de controle desde o começo, o que torna o controle um investimento na versão seguinte, e não só uma métrica.

Mandar "ainda está aí?" quando o cliente para de responder ajuda ou atrapalha?

Na maior parte dos casos atrapalha, e é a intervenção mais implementada justamente por ser a mais fácil. Ela não acrescenta informação nenhuma à conversa, transfere ao cliente o custo de responder algo que não interessa a ele e, num canal com notificação, interrompe alguém que possivelmente voltaria sozinho, convertendo pausa em saída. A regra que sustenta uma boa política é que toda intervenção precisa carregar valor novo: se o sistema não tem nada a acrescentar, o correto é não dizer nada e apenas registrar o risco. Quando há valor a entregar, ele deve responder à causa do risco e não ao silêncio. Se o componente dominante é repetição, a ação certa é transbordo para humano com o contexto pronto, porque o agente já demonstrou que não resolve. Se é frustração, é escalada imediata. Se é apenas latência crescente sem nenhum outro sinal, a melhor ação no primeiro limiar é nenhuma, e no segundo limiar um resumo do estado da conversa, que permite retomar sem reler tudo.

A perda que não reclama é a que mais custa

Abandono não é um evento que chega no webhook, é a ausência de um, e por isso exige inverter o fluxo: agendar uma verificação a cada turno e cancelá-la quando o cliente responde. Detectar bem começa por definir o que conta como desfecho, derivar limiares da distribuição real de cada canal e etapa em vez de escolher um número redondo, e usar os sinais que precedem o silêncio, porque quando ele chega o cliente já decidiu. Um escore aditivo com componentes visíveis é suficiente e defensável, e é o componente dominante, não o total, que decide qual ação tomar. Sem grupo de controle permanente, a taxa de recuperação mistura o efeito da intervenção com o dos clientes que voltariam sozinhos e nenhuma conclusão é possível. Posso instrumentar a detecção sobre o seu fluxo atual, calibrar os limiares com o seu histórico e desenhar a política de intervenção por causa em vez de por silêncio.