IA que liga para confirmar agendamento no WhatsApp (e entende sim, não e remarcar)
IA que liga pelo WhatsApp para confirmar consultas e serviços: entende sim, não e remarcar, atualiza a agenda e cai para mensagem se ninguém atender.
Uma IA que confirma agendamento por ligação no WhatsApp liga com POST /{key}/call só para clientes que escolheram esse canal, espera o evento call-ready no Socket.IO, diz o compromisso, entende a resposta — confirmar, cancelar ou remarcar — e atualiza a agenda. Se ninguém atender, o evento call-media-failed avisa e a confirmação segue por mensagem de texto. Com a API não oficial da WAME, tudo roda no número que o cliente já conhece.
A confirmação por mensagem já foi coberta em lembrete de agendamento no WhatsApp. A ligação é a camada extra para quem não responde texto — e tem regras próprias.
A camada não oficial da WAME é independente e não é afiliada, endossada ou suportada pelo WhatsApp ou pela Meta. O uso é de responsabilidade de quem envia.
Para quem ligar (e para quem não)
Este é o ponto que decide se a automação ajuda ou derruba o número. A regra:
- Só para quem optou. No agendamento, pergunte: "Como prefere a confirmação: mensagem ou ligação?". Guarde a resposta.
- Só para compromisso real, com data e hora marcadas pelo próprio cliente.
- Uma ligação por compromisso. Não atendeu, vai por texto. Religar três vezes é o comportamento que gera denúncia.
- Em horário razoável. Comercial, nunca cedo demais ou à noite.
Ligar automaticamente para uma lista de contatos que não espera a ligação é robocall. É denunciado rápido, derruba o número e a WAME não apoia esse uso. Feito do jeito certo — cliente que pediu, uma vez, no horário combinado —, é atendimento, e a taxa de bloqueio é muito baixa.
O fluxo completo
- Um job seleciona os agendamentos de amanhã com
canal = "ligacao"e ainda não confirmados. - Para cada um, espaçado no tempo,
POST /{key}/call. A resposta volta na hora com ocallIdestatus: "ringing". - Atendeu: o Socket.IO emite
call-readycom ocallId. A IA fala o compromisso e ouve a resposta pelo eventocall-audio. - Não atendeu ou recusou: o Socket.IO emite
call-media-failed. O sistema manda a confirmação por mensagem. - A resposta vira ação na agenda: confirmado, cancelado ou remarcado.
- A ligação é encerrada com
POST /{key}/call/ende o resultado é registrado.
Iniciar a ligação
const KEY = process.env.WAME_KEY;
const BASE = `https://us.api-wa.me/${KEY}`;
const post = (path, body) =>
fetch(`${BASE}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
}).then((r) => r.json());
const emAndamento = new Map(); // callId -> { agendamento, peerJid, tentativas }
async function ligarPara(agendamento) {
const r = await post('/call', { to: agendamento.telefone });
const { callId, peerJid } = r.response ?? {};
if (!callId) {
await confirmarPorTexto(agendamento); // falhou antes de tocar
return;
}
emAndamento.set(callId, { agendamento, peerJid, tentativas: 0, historico: [] });
}A chamada responde assim que o telefone começa a tocar, com callId e peerJid. O áudio só existe depois que a pessoa atende — por isso o resto do fluxo depende dos eventos do socket.
Ouvir o socket
import { io } from 'socket.io-client';
const socket = io('https://us.api-wa.me', {
auth: { key: KEY },
query: { key: KEY },
transports: ['websocket', 'polling'],
});
socket.on('call-ready', async ({ callId }) => {
const c = emAndamento.get(callId);
if (!c) return;
const { nome, servico, dataHora } = c.agendamento;
await falar(callId,
`Olá, ${nome}! Aqui é a assistente virtual da Clínica Exemplo. ` +
`Estou ligando para confirmar ${servico} ${dataHora}. ` +
`Você confirma, quer cancelar ou prefere remarcar?`);
});
socket.on('call-media-failed', async (evt) => {
const c = evt.callId && emAndamento.get(evt.callId);
if (!c) return;
emAndamento.delete(evt.callId);
await confirmarPorTexto(c.agendamento);
});
socket.on('call-audio', ({ callId, pcm }) => {
const c = emAndamento.get(callId);
if (c) c.detector?.alimentar(Buffer.from(pcm, 'base64'));
});Um cuidado com o call-media-failed: quando a falha acontece antes de a ligação ganhar um identificador, o evento pode vir sem callId. Por isso, tenha também um tempo limite por ligação — se nem call-ready nem call-media-failed chegarem em um minuto ou dois, trate como não atendida e siga por texto.
O falar sintetiza a frase em PCM 16 kHz e envia pelo call-audio-in em pedaços pequenos — o mesmo reprodutor descrito em latência, interrupção e silêncio. A primeira frase também avisa que é uma assistente virtual: transparência reduz desconfiança e reclamação.
Como a saudação é quase igual para todos, dá para pré-gerar o começo ("Olá, aqui é a assistente virtual da Clínica Exemplo") e sintetizar só o trecho variável. Menos latência e menos custo.
Entender sim, não e remarcar
A resposta do cliente é curta e variada: "confirmo", "pode deixar", "não vou conseguir", "tem outro horário?", "quem é?". Depois de transcrever, peça ao modelo uma classificação fechada:
const instrucoes = `
Classifique a resposta do cliente sobre o agendamento.
Responda SOMENTE com JSON: {"intencao": "confirmar|cancelar|remarcar|duvida|nao_entendi", "preferencia": "texto livre ou vazio"}
- "pode ser", "tá certo", "confirmo" => confirmar
- "não vou", "desmarca" => cancelar
- "outro dia", "mais tarde", "tem na sexta?" => remarcar (preencha preferencia)
- perguntas sobre endereço, preparo, valor => duvida
`;
async function tratarResposta(callId, texto) {
const c = emAndamento.get(callId);
const { intencao, preferencia } = await classificar(instrucoes, texto);
if (intencao === 'confirmar') {
await agenda.confirmar(c.agendamento.id);
await falar(callId, 'Perfeito, está confirmado. Até lá!');
return encerrar(callId);
}
if (intencao === 'cancelar') {
await agenda.cancelar(c.agendamento.id);
await falar(callId, 'Tudo bem, cancelei. Se quiser remarcar, é só chamar por aqui.');
return encerrar(callId);
}
if (intencao === 'remarcar') {
const opcoes = await agenda.horariosLivres(c.agendamento, preferencia);
c.opcoes = opcoes.slice(0, 3);
return falar(callId, `Tenho ${falarOpcoes(c.opcoes)}. Qual prefere?`);
}
if (intencao === 'duvida') {
await falar(callId, 'Vou te mandar essas informações por mensagem agora. Você confirma o horário?');
await enviarInformacoes(c.agendamento);
return;
}
// nao_entendi
if (++c.tentativas >= 2) {
await falar(callId, 'Vou te mandar a confirmação por mensagem, tudo bem? Obrigada!');
await confirmarPorTexto(c.agendamento);
return encerrar(callId);
}
await falar(callId, 'Desculpe, não entendi. Você confirma o horário, quer cancelar ou remarcar?');
}A consulta à agenda e a remarcação são ações do seu sistema; com function calling, o próprio modelo pode decidir chamar horariosLivres e remarcar, em vez de você codificar cada ramo. Para uma confirmação simples, o if explícito acima é mais previsível — e previsibilidade vale ouro numa ligação.
Três regras de conversa que evitam frustração:
- No máximo três opções de horário por vez. Por voz, ninguém guarda cinco.
- Repita a decisão antes de encerrar: "Então fica quinta, às 14h. Confirmado."
- Duas incompreensões, sai da voz. Não force; mande por mensagem.
Encerrar e registrar
async function encerrar(callId) {
const c = emAndamento.get(callId);
if (!c) return;
emAndamento.delete(callId);
setTimeout(() => post('/call/end', { callId, peerJid: c.peerJid }), 3000); // deixa a frase final tocar
await agenda.registrarContato(c.agendamento.id, { canal: 'ligacao', resultado: c.resultado });
}Se o cliente desligar antes, o evento de chamada com o novo status chega no webhook; limpe o estado e, se nada foi decidido, siga por texto.
O caminho do texto
A confirmação por texto é o plano B e precisa ser boa. Abra com uma mensagem simples antes de botões — para contatos que nunca conversaram com o número, mensagens interativas podem não aparecer como primeira mensagem:
async function confirmarPorTexto(a) {
await post('/message/text', {
to: a.telefone,
text: `Olá, ${a.nome}! Tentamos te ligar para confirmar ${a.servico} ${a.dataHora}.`,
});
await post('/message/button_reply', {
to: a.telefone,
text: 'Você confirma?',
buttons: [
{ type: 'quick_reply', id: `conf_${a.id}`, text: 'Confirmo' },
{ type: 'quick_reply', id: `canc_${a.id}`, text: 'Cancelar' },
{ type: 'quick_reply', id: `rem_${a.id}`, text: 'Remarcar' },
],
});
}O clique volta no webhook como interactive.button_reply.id, e a mesma lógica de agenda trata a resposta.
Ritmo das ligações
Um job que dispara cem ligações no mesmo minuto não parece atendimento. Espace:
- Uma ligação por vez ou poucas em paralelo, com intervalo entre elas. A plataforma também limita quantas sessões de áudio rodam ao mesmo tempo.
- Distribua ao longo do horário comercial do dia anterior, não tudo às 9h.
- Respeite quem pediu outro horário para contato.
Se a sua API devolver 429 em algum envio de texto do plano B, é sinal para desacelerar a fila, não para tentar de novo na hora. A lógica de fila está em fila, rate limit e retry.
Medir o que importa
- Taxa de atendimento das ligações.
- Taxa de confirmação por canal (voz vs texto).
- Faltas antes e depois de ligar.
- Pedidos de "prefiro mensagem" — sinal para mudar o canal padrão desse cliente.
Se a voz não reduz faltas mais do que o texto para o seu público, fique no texto: é mais barato. A ligação faz mais sentido para agendamentos de alto valor e para quem não responde mensagens.
Conclusão
Uma IA que liga para confirmar agendamento é uma conversa curta e bem delimitada: dizer o compromisso, entender confirmar, cancelar ou remarcar, e agir na agenda. A API não oficial da WAME dá as peças — POST /{key}/call para ligar, call-ready e call-media-failed no Socket.IO para saber o que aconteceu, call-audio e call-audio-in para ouvir e falar. O que faz dar certo é o seu lado: ligar só para quem escolheu esse canal, uma vez, no horário certo, e cair para mensagem sem insistir. O agente de voz completo está em IA para atender ligação no WhatsApp, e o básico de chamadas, em ligação pelo WhatsApp via API.
Pronto para automatizar seu WhatsApp?
Crie sua conta gratuita e comece a enviar mensagens pela API em minutos.
Começar grátisPerguntas frequentes
Posso fazer uma IA ligar para confirmar consultas pelo WhatsApp?+
Sim, para clientes que escolheram receber a confirmação por ligação. Com a API não oficial da WAME você liga com POST /{key}/call, recebe o aviso de atendimento pelo Socket.IO (call-ready), ouve a resposta pelo evento call-audio e fala pelo call-audio-in. A IA entende confirmar, cancelar ou remarcar e atualiza a agenda.
E se o cliente não atender?+
A API avisa pelo Socket.IO com o evento call-media-failed quando a ligação não é atendida ou é recusada. Nesse caso, mande a confirmação por mensagem de texto com botões. Não fique religando: uma tentativa por voz e o resto por texto.
Isso não é robocall?+
Não, se for feito para quem pediu. Robocall é ligar automaticamente para quem não espera a ligação. Aqui a ligação é para um cliente com horário marcado que optou por confirmação por voz, no horário combinado e uma vez. A WAME não apoia ligação automatizada para listas.
Como a IA entende a resposta do cliente?+
A fala é transcrita e um modelo classifica a intenção em confirmar, cancelar, remarcar ou não entendido. Para remarcar, a IA consulta os horários livres por function calling e oferece duas ou três opções. Se não entender duas vezes, encerra e manda por mensagem.
Ligação funciona melhor que mensagem para confirmar?+
Depende do público. Para quem não lê mensagens com frequência, pessoas mais velhas ou agendamentos de alto valor, a voz costuma funcionar melhor. Para o resto, a mensagem com botões é mais barata e suficiente. O ideal é deixar o cliente escolher o canal.
Continue lendo
Agente de voz no WhatsApp: latência, interrupção (barge-in) e silêncio
Como deixar um agente de voz no WhatsApp natural: latência, streaming, detecção de fala, interrupção (barge-in), silêncio e eco, com exemplos em Node.js.
Ligação pelo WhatsApp via API não oficial: fazer, atender e tocar áudio
Como fazer, atender, recusar e encerrar ligações de WhatsApp pela API não oficial, tocar áudio na chamada e gerar link de chamada, com exemplos em cURL.
IA para atender ligação no WhatsApp pela API: como montar um agente de voz
Como montar um agente de voz que atende ligações no WhatsApp pela API: webhook, áudio em tempo real por Socket.IO, transcrição, IA, voz sintética e handoff.