Skip to content

Automação de WhatsApp ​

A automação de comunicações via WhatsApp é um dos pilares de eficiência do CRMed, reduzindo o no-show e automatizando o acompanhamento pós-operatório. A infraestrutura utiliza exclusivamente a Evolution Go API (versão Golang do Evolution API).

Régua de Notificações (RN05) ​

EventoGatilhoObjetivo
Lembrete 30d30 dias antes do agendamentoManter o agendamento no radar do paciente.
Lembrete 7d7 dias antes do agendamentoIniciar preparativos para o procedimento.
Confirmação 48h48 horas antes do agendamentoConfirmar presença ou solicitar remarcação.
ReagendamentoAlteração de data/hora no CRMInformar ativamente o paciente sobre o novo horário.
Pós-OpData definida no registro de Post-OpAcompanhamento de recuperação do paciente.

Os envios são avaliados pelo Cronjob Diário (que roda às 08:00 AM - America/Sao_Paulo). O cronjob identifica os agendamentos elegíveis e enfileira as mensagens no BullMQ (Redis).

Testando a Régua de Notificações Manualmente ​

Para facilitar a validação em ambiente de desenvolvimento, o sistema possui scripts oficiais para gerar dados de teste e forçar a execução do cronjob:

bash
# 1. Popula o banco com 3 agendamentos fictícios (30d, 7d, 2d) vinculados ao número do DEV_ALLOWED_PHONE
pnpm -F @crmed/workers seed:cron-test

# 2. Executa a varredura do Cronjob manualmente
pnpm -F @crmed/workers test:cron

O Cronjob possui observabilidade detalhada e logará no terminal exatamente quantos agendamentos foram avaliados, quantos foram enfileirados para envio e quantos foram ignorados (por já possuírem a notificação no banco de dados, evitando duplicidade).


Máquina de Estados do Chatbot ​

Estados do Chatbot ​

EstadoDescrição
STARTEstado inicial: identifica se o contato é novo ou existente no banco.
NEW_ASK_NAMECaptação de leads: solicita nome ao contato desconhecido.
NEW_CONFIRM_NAMEConfirmação do nome informado antes de prosseguir.
NEW_ASK_EMAILCaptação de leads: solicita email (opcional, pode pular).
NEW_ASK_INTERESTTriagem: lista áreas de interesse para direcionar o lead.
EXISTING_MENUMenu principal para pacientes/leads já cadastrados.
EXISTING_FAQExibe FAQ do Hospital (aguardando 0 para voltar ao menu).
EXISTING_PROCEDUREInformações sobre procedimentos (aguardando 0).
EXISTING_SCHEDULEHandover para equipe humana (reagendamento/agendamento).
VERIFY_DOB_CHALLENGEDesafio LGPD: valida data de nascimento antes de exibir dados clínicos.
VERIFY_DOB_ENRICHProgressive Profiling: captura DOB ausente no perfil do paciente.
CONFIRM_APPOINTMENTAguardando resposta à confirmação de 48h (disparado pelo NotificationService).
APPOINTMENT_LISTAutoatendimento: lista agendamentos futuros do paciente.
APPOINTMENT_CANCEL_CONFIRMGestão de agendamento selecionado (confirmar/reagendar/cancelar).

Sistema de Templates ​

O conteúdo das mensagens é gerenciado exclusivamente pelo banco de dados — nunca hardcoded no backend. Isso permite que a equipe clínica edite mensagens sem deploys.

TemplateParser ​

O TemplateParser do pacote @crmed/database realiza a interpolação de variáveis:

typescript
// Exemplo de template no banco:
"Olá *{{paciente}}*! Seu procedimento *{{procedimento}}* com o Dr. {{medico}} está agendado para {{data}}."

// Resultado após parse:
"Olá *João Silva*! Seu procedimento *Rinoplastia* com o Dr. Carlos está agendado para 20/06/2026."

Visão do Paciente:

  • Suporta sintaxe {{ }} (duplas chaves).
  • Suporta formatação nativa do WhatsApp: *negrito*, _itálico_.
  • Graceful Degradation: Tags não encontradas são substituídas por termos genéricos (ex: "nosso especialista"), evitando mensagens quebradas.

Integração Técnica ​

Arquitetura do Fluxo de Mensagem ​

Deduplicação de Mensagens (Fingerprint) ​

O webhook processa eventos com uma verificação de fingerprint em memória (Set<string>) com lock natural de 10 segundos, prevenindo que a mesma mensagem seja processada duas vezes em caso de retentativas da Evolution Go.

Autenticação com Evolution Go ​

  • Global Key: Header apikey com a chave global da instância.
  • Instance Token: Header Authorization: Bearer <instanceToken> para operações instance-scoped.
  • Respostas são envelopadas no formato { data: T, message: string } e desembrulhadas via EvoGoClient.unwrap().

Sandbox Mode (Desenvolvimento) ​

Em ambiente de desenvolvimento e staging, as mensagens são bloqueadas para evitar spam em números reais.

  • Variável: DEV_ALLOWED_PHONE (definida no .env raiz).
  • Comportamento: O WhatsappSender verifica se o número de destino é igual ao DEV_ALLOWED_PHONE. Caso contrário, a mensagem é logada como blocked_by_dev_sandbox e não enviada.
  • Garantia: Em produção, esta variável deve estar vazia ou não definida.

Segurança do Webhook ​

A rota POST /webhook/evolution nos Workers é protegida por:

CamadaMecanismo
AssinaturaHMAC-SHA256 validado em cada request para garantir origem confiável
IP AllowlistRequisições fora do range da infraestrutura são bloqueadas
IdempotênciaFingerprint em memória previne reprocessamento de eventos duplicados