Appearance
WhatsApp & IA Conversacional
Visão Geral
O módulo WhatsApp (Domain/WhatsApp) integra o Decaelo com a Meta Cloud API (WhatsApp Business Platform) e o Laravel AI SDK para oferecer comunicação bidirecional inteligente entre igrejas e seus membros.
Funcionalidades principais:
- Notificações outbound via templates aprovados pelo Meta
- Chatbot conversacional com IA que responde de forma natural
- Escalação automática para atendente humano
- 3 níveis de acesso gateados por plano
- Personalidade da IA customizável por igreja
Arquitetura
Fluxo Geral
Meta Cloud API ←→ Webhook Controller (central) ←→ Jobs (tenant-aware) ←→ WhatsAppAgent (Laravel AI SDK)- Webhook centralizado — rota pública fora do tenant middleware. Resolve o tenant pelo
phone_number_idcadastrado emwhatsapp_accounts - Filas dedicadas —
whatsapp-inbound(processamento IA) ewhatsapp-outbound(envio), workers Horizon separados - Agent do Laravel AI SDK —
WhatsAppAgentcom Tools, Middleware e Failover entre provedores
Número por Igreja
Cada igreja (tenant) possui seu próprio número de WhatsApp registrado na Meta Cloud API. O número pode ser o que a igreja já utiliza. Isso garante:
- Identidade própria — mensagens saem do número da igreja
- Roteamento trivial —
phone_number_idmapeia diretamente para o tenant - Sem conflito de rate limits entre igrejas
Modelo de Dados
Banco Central:
| Tabela | Descrição |
|---|---|
whatsapp_accounts | Credenciais Meta por tenant (phone_number_id, access_token criptografado) |
Banco Tenant (isolado por igreja):
| Tabela | Descrição |
|---|---|
whatsapp_conversations | Conversas com status (active, escalated, closed, expired) |
whatsapp_messages | Mensagens com direção, tipo, sender_id, status de entrega, tokens IA usados |
whatsapp_templates | Templates aprovados pelo Meta para mensagens outbound |
ai_prompt_configurations | Personalidade da IA, system prompt, saudação, fallback |
whatsapp_credit_usage | Controle mensal de cota e créditos extras |
Integração com Módulos Existentes
- Communication —
NotificationChannel::WhatsAppadicionado ao enum existente.SendNotificationActionestendido para despachar via WhatsApp respeitando preferências do membro - Feature Flags —
whatsapp_basic,whatsapp_intermediate,whatsapp_complete,whatsapp_custom_prompt - Horizon — supervisor dedicado
whatsappcom filaswhatsapp-inboundewhatsapp-outbound - Reverb — broadcasting de conversas escaladas e status de mensagens para o painel admin
- Auditing — todos os models do módulo são auditados automaticamente
Fluxo Inbound (Membro → Igreja)
1. Membro envia mensagem no WhatsApp
2. Meta POST /webhooks/whatsapp
3. WhatsAppWebhookController valida signature
4. Resolve tenant pelo phone_number_id
5. Dispatch ProcessInboundMessageJob (fila: whatsapp-inbound)
6. Job no contexto do tenant:
a. Busca/cria conversa pelo telefone do remetente
b. Vincula ao member (se encontrar pelo telefone)
c. Salva mensagem
d. Se conversa escalada → broadcast para painel do atendente
e. Se conversa ativa → WhatsAppAgent processa com IA
7. Agent responde → dispatch SendOutboundMessageJob
8. Mensagem enviada via MetaCloudApiServiceÁudio
Mensagens de áudio são baixadas via Meta API e transcritas usando o Laravel AI SDK (Transcription STT). O texto transcrito é processado como mensagem de texto normal.
Fluxo Outbound (Igreja → Membros)
Notificações via Template
Mensagens iniciadas pela igreja (fora da janela de 24h) exigem templates pré-aprovados pelo Meta.
1. Admin cria notificação no painel
2. SendNotificationAction verifica preferências do membro
3. Canal WhatsApp habilitado → dispatch SendWhatsAppTemplateJob
4. Job preenche placeholders do template com dados do membro/evento
5. MetaCloudApiService envia templateJanela de 24h
- Membro envia mensagem → abre janela de 24h para respostas livres
- Dentro da janela: IA e atendentes respondem livremente (free-form)
- Fora da janela: apenas templates aprovados
IA Conversacional
Laravel AI SDK
O chatbot usa o WhatsAppAgent construído com o Laravel AI SDK:
php
class WhatsAppAgent implements Agent, Conversational, HasMiddleware
{
use Promptable, RemembersConversations;
public function tools(): iterable
{
return match ($this->accessLevel) {
AiAccessLevel::Basic => $this->basicTools(),
AiAccessLevel::Intermediate => $this->intermediateTools(),
AiAccessLevel::Complete => $this->completeTools(),
};
}
}Níveis de Acesso
Básico — informações públicas da igreja:
| Tool | Descrição |
|---|---|
ConsultarHorariosCulto | Horários de cultos e missas |
ConsultarEventosProximos | Próximos eventos públicos |
ConsultarInfoIgreja | Endereço, telefone, redes sociais |
ConsultarAvisosGerais | Avisos da liderança |
Intermediário — dados do próprio membro:
| Tool | Descrição |
|---|---|
ConsultarMeusDados | Dados cadastrais do membro |
ConsultarMeusCelulas | Células/grupos que participa |
ConsultarMinhasContribuicoes | Resumo de dízimos/ofertas |
ConsultarMeusEventos | Eventos inscritos |
Completo — ações executáveis:
| Tool | Descrição |
|---|---|
RegistrarPedidoOracao | Cria pedido no mural de oração |
InscreverEmEvento | Inscreve em evento |
ConfirmarPresenca | Confirma presença |
SolicitarAtestado | Solicita declaração de membro |
EscalarParaHumano | Transfere para atendente |
Middleware do Agent
| Middleware | Função |
|---|---|
InjectChurchPersonality | Carrega system prompt da igreja (template ou customizado) |
CheckCreditQuota | Verifica e decrementa cota mensal |
FilterByAccessLevel | Remove tools fora do nível do plano |
LogAiUsage | Registra tokens, provider, tempo de resposta |
Personalidade da IA
- Templates (plano menor): perfis prontos — Formal, Acolhedor, Jovem
- System prompt customizável (plano premium): admin configura tom, saudação, nome do bot, informações da denominação
Failover
php
$response = $agent->prompt($message, provider: [Lab::OpenAI, Lab::Anthropic]);Se o provider principal falhar (rate limit, timeout), o SDK automaticamente tenta o próximo.
Providers por Ambiente
| Ambiente | Provider | Modelo |
|---|---|---|
| Dev/Test | OpenAI | gpt-4o-mini |
| Produção | OpenAI (fallback: Anthropic) | gpt-4o-mini (fallback: claude-haiku) |
Escalação para Humano
1. IA não consegue resolver → chama tool EscalarParaHumano
2. Conversa marcada como 'escalated'
3. Notificação via Reverb → sino no painel admin
4. Atendente vê conversa com histórico completo
5. Atendente responde pelo painel → mensagem enviada via WhatsApp
6. Timeout (configurável, default 15min):
→ Ninguém respondeu → mensagem ao membro informando retorno
→ Cria tarefa interna de follow-up
7. Atendente pode "Devolver para IA" → conversa volta para status 'active'Segurança
Webhook
- Validação
X-Hub-Signature-256com HMAC SHA-256 - Rate limiting no endpoint
verify_tokenpara handshake inicial do Meta
Dados
access_tokencriptografado no banco (encryptedcast)- Mensagens isoladas por tenant (banco separado)
- Áudio descartado após transcrição
Proteção contra Prompt Injection
- Tools acessam dados APENAS do membro identificado pelo telefone
FilterByAccessLevelremove tools antes do provider — restrição estrutural, não por prompt- Tools de ação retornam intent → Action valida e executa
Identificação do Membro
- Vinculação automática por telefone
- Primeiro acesso a dados pessoais exige confirmação (últimos 4 dígitos do CPF ou data de nascimento)
- Confirmação válida por 30 dias
Configuracao na Meta (Passo a Passo)
IMPORTANTE: Use um app Meta separado do Facebook Login. A Meta restringe apps que misturam autenticacao com mensageria.
1. Criar o App na Meta
- Acesse https://developers.facebook.com/
- My Apps > Create App
- Tipo: Business
- Nome:
Decaelo WhatsApp(ou similar) - Selecione ou crie um Business Portfolio
2. Adicionar WhatsApp Product
- No dashboard do app, clique Add Product > WhatsApp > Set Up
- Selecione o Business Portfolio
- A Meta criara automaticamente um WhatsApp Business Account (WABA) de teste
3. Configurar Webhook
- Va em WhatsApp > Configuration (menu lateral)
- Em Webhook:
- Callback URL:
https://decaelo.com.br/webhooks/whatsapp - Verify Token: gere um token aleatorio (ex:
decaelo-whatsapp-verify-2026) e anote-o — sera usado ao cadastrar a conta no painel admin
- Callback URL:
- Clique Verify and Save
- Em Webhook Fields, marque:
messages— receber mensagens inboundmessage_deliveries— status de entrega (optional)
4. Obter Credenciais
- Va em WhatsApp > API Setup
- Anote:
- Phone Number ID — identificador do numero de teste
- WhatsApp Business Account ID — WABA ID
- Temporary Access Token — token de 24h para testes
- Para token permanente:
- Va em Settings > Basic > anote o App Secret
- Va em Business Settings > System Users > crie um system user
- Gere um token permanente com permissao
whatsapp_business_messaging
5. Configurar .env no Servidor
env
META_WHATSAPP_APP_SECRET=abc123def456 # App Secret do app WhatsApp (para validar webhook signature)6. Rodar Migration do Banco Central
A tabela audits precisa existir no banco central para que o model WhatsAppAccount funcione (ele usa o trait Auditable). Essa migration ja esta inclusa e roda automaticamente com app:setup ou php artisan migrate.
Se o banco central ja existe e voce esta adicionando o WhatsApp pela primeira vez:
bash
docker compose exec app php artisan migrate7. Cadastrar Conta no Painel Admin
- Acesse
/admin/whatsapp-accounts - Clique Nova Conta
- Preencha:
- Tenant: selecione a igreja
- Phone Number ID: do passo 4
- WABA ID: do passo 4
- Numero: numero de WhatsApp (ex: +5511999999999)
- Access Token: token permanente do passo 4
- Verify Token: o mesmo usado no webhook (passo 3)
- Webhook Secret: App Secret (para validacao HMAC)
- Salve e ative
8. Testar
- No API Setup da Meta, envie uma mensagem de teste para seu numero
- Verifique nos logs:
docker compose logs horizon --tail=20 - A mensagem deve aparecer no painel de conversas da igreja
9. Producao — Numero Real da Igreja
- WhatsApp > API Setup > Add Phone Number
- Registre o numero da igreja (sera verificado via SMS/ligacao)
- Atualize o Phone Number ID no painel admin
- Envie templates para aprovacao em WhatsApp > Message Templates
Resumo de URLs e Tokens
| Item | Valor |
|---|---|
| Webhook URL | https://decaelo.com.br/webhooks/whatsapp |
| Webhook Verify Token | Definido por voce ao cadastrar a conta |
| Webhook Secret (HMAC) | App Secret do app WhatsApp na Meta |
| Access Token | Token permanente do System User |
| Callback do Social Login | https://decaelo.com.br/auth/facebook/callback (app separado!) |
Troubleshooting
| Problema | Causa | Solucao |
|---|---|---|
| 419 Page Expired no webhook | CSRF bloqueando POST | Adicionar webhooks/* em validateCsrfTokens(except:) no bootstrap/app.php |
| 403 no webhook POST | HMAC signature nao confere | Verificar que webhook_secret da conta = App Secret do app WhatsApp na Meta |
| 403 no webhook GET (verificacao) | verify_token nao encontrado no banco | Cadastrar a conta no painel admin ANTES de configurar webhook na Meta |
Table 'tenantalfa.whatsapp_accounts' doesn't exist | Model sem getConnectionName() | WhatsAppAccount deve retornar config('tenancy.database.central_connection') |
Database connection [central] not configured | Codigo usa ::on('central') hardcoded | Usar WhatsAppAccount::where(...) (model resolve a connection sozinho) |
Table 'decaelo.audits' doesn't exist | Migration de audits so existe em tenant/ | Rodar php artisan migrate (migration central de audits adicionada) |
| Jobs nao processam (Horizon silencioso) | APP_ENV nao configurado no horizon.php | Adicionar environment em config/horizon.php com as queues whatsapp-* |
Recipient phone number not in allowed list | Modo dev da Meta, numero nao na allowlist | Adicionar numero em API Setup > "Ate" na Meta. Nao ocorre em producao |
Numero truncado no from | Bug da Meta com numero de teste americano | Usar numero real da igreja em producao resolve |
Feature Flags
| Flag | Descrição |
|---|---|
whatsapp_basic | Notificações + IA nível básico |
whatsapp_intermediate | IA com acesso a dados do membro |
whatsapp_complete | IA com ações executáveis |
whatsapp_custom_prompt | System prompt customizável |
Páginas do Painel Admin
| Página | Rota | Descrição |
|---|---|---|
| Conversas | /whatsapp/conversations | Lista de conversas com filtro por status |
| Chat | /whatsapp/conversations/{ulid} | Chat em tempo real (atendente) |
| Templates | /whatsapp/templates | Gestão de templates Meta |
| Configuração IA | /whatsapp/configuration | Personalidade, prompts, saudação |
| Créditos | /whatsapp/credits | Uso mensal e compra de créditos extras |
Permissões
| Permissão | Descrição |
|---|---|
whatsapp.view | Visualizar conversas |
whatsapp.reply | Responder como atendente |
whatsapp.manage | Gerenciar templates e configuração IA |
whatsapp.credits | Visualizar e comprar créditos |