Serviço enterprise para WhatsApp com Message Aggregator inteligente, Redis isolado, graceful degradation e integração bidirecional com Evolution API.
Usuários enviam pensamentos fragmentados em múltiplas mensagens rápidas. Isso é comportamento normal no WhatsApp.
O Message Aggregator espera 5 segundos após cada mensagem. estende o timeout.
┌─────────────────────────────────────────────────────────────────────────┐
│ Message Aggregator Timeline │
└─────────────────────────────────────────────────────────────────────────┘
Mensagem 1 Mensagem 2 Mensagem 3 Timeout
│ │ │ │
▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ "Oi" │ │"bem?"│ │"10h" │ │ENVIAR│
└──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
│ │ │ │
│ 5s timer │ RESET! │ RESET! │
│────────────────▶│────────────────▶│────────────────▶│
│ │ │ │
│ Timer estendido Timer estendido Timer expirou
│ │ │ │
└─────────────────┴─────────────────┴─────────────────┘
│
┌─────────────────────────────┘
│
▼
┌─────────────────────┐
│ Mensagem Agregada: │
│ "Oi bem? 10h" │
│ │
│ → Backend Orch. │
│ → AI Engine │
└─────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ CONFIG: MESSAGE_DEBOUNCE_SECONDS=5 │
│ AGGREGATOR_MAX_TIMEOUT_SECONDS=30 │
│ AGGREGATOR_MAX_MESSAGES_PER_AGGREGATION=10 │
└─────────────────────────────────────────────────────────────────────────┘O WhatsApp envia eventos de "digitando..." via webhook. O Message Aggregator estender o timeout inteligentemente.
Resultado: O usuário pode digitar no seu ritmo natural. O sistema "espera" inteligentemente até ele terminar o pensamento completo. O usuário pode digitar no seu ritmo natural. O sistema "espera" inteligentemente até ele terminar o pensamento completo.
Esses limites previnem DoS e garantem que mensagens não fiquem "presas" indefinidamente se o usuário ficar digitando sem parar.
WhatsApp gera <strong class="text-green-400">muito tráfego de webhook</strong> - muito tráfego de webhook Misturar isso com o Redis principal é receita para disaster.
┌─────────────────────────────────────────────────────────────────┐
│ REDIS ISOLATED ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 🔴 Redis Principal (Porta 6379/6380) │
│ ├─ AI Engine ✅ Cache de conversas │
│ ├─ Backend Orchestrator ✅ Rate limiting, cache │
│ ├─ Memory Engine ✅ Hot/Warm storage │
│ ├─ Rules Engine ✅ Cache de regras │
│ └─ Celery Workers ✅ Task queues │
│ │
│ 🟢 Redis WhatsApp (Porta 6382) - ISOLADO │
│ └─ WhatsApp Integration ONLY │
│ ├─ Message buffers (agregação) │
│ ├─ Typing state tracking │
│ ├─ Webhook deduplication │
│ ├─ Instance → Tenant mapping │
│ └─ Delivery status cache │
│ │
└─────────────────────────────────────────────────────────────────┘
⚡ Benefícios:
• WhatsApp broadcast não afeta cache de conversas
• Falha no Redis WhatsApp não derruba sistema principal
• Métricas separadas para debugging
• Escala independente se necessárioSe Redis WhatsApp cair ou ficar lento, o sistema principal (AI, Memory, Rules) continua funcionando normalmente.
Monitoring independente: latência do Redis WhatsApp não polui métricas do sistema core. Debug mais fácil.
Alta demanda de WhatsApp? Escala só o Redis WhatsApp. Não precisa mexer na infra principal.
Sob alta carga, o sistema degrada features não-essenciais para manter o core funcionando. Níveis configuráveis de degradação.
DEGRADATION_PENDING_USERS_THRESHOLD_LOW=500
DEGRADATION_PENDING_USERS_THRESHOLD_HIGH=2000
DEGRADATION_REDIS_LATENCY_THRESHOLD_LOW_MS=50
DEGRADATION_REDIS_LATENCY_THRESHOLD_HIGH_MS=150 Degradação baseada em:
No WhatsApp, cada telefone = uma conversa. Não importa qual header chega, sempre calcula o mesmo UUID Isso elimina sessões paralelas e cross-user pollution.
conversation_id = UUID5(
namespace=OPTIMUS_NAMESPACE,
name=f"{tenant_id}:{normalized_phone}"
)
# Exemplo:
# tenant: "clinica_abc"
# phone: "+5511999999999"
# → UUID: "a1b2c3d4-e5f6-5a7b-8c9d-0e1f2a3b4c5d"
# SEMPRE o mesmo UUID para mesmos inputs
# Ignora headers externos completamenteHeaders de X-Conversation-ID são <strong class="text-red-400">ignorados</strong>. ignorados. Previne que um cliente malicioso "pule" para conversa de outro usuário.
// Todos viram o MESMO UUID:
"+5511999999999" → UUID_X
"5511999999999" → UUID_X
"+55 11 999-999-999" → UUID_X
"+55 (11) 99999-9999" → UUID_X
// Phone é normalizado antes do hash:
// 1. Remove espaços, hífens, parênteses
// 2. Remove "+" prefix
// 3. Garante formato numérico puroNão importa como o telefone chega (WhatsApp, Evolution, manual), a normalização garante consistência.
Quando um atendente humano assume a conversa, o comportamento do suportar interação em tempo real.
Cada tenant pode ter múltiplas instâncias WhatsApp. O sistema resolve automaticamente qual tenant "dono" de cada instância via cache O(1).
// Instance → Tenant mapping
{
"clinica_sp": "Local - SP",
"clinica_rj": "Local - RJ",
"clinica_demo": "Local - Dev"
}
// Lookup O(1) via Redis:
// GET instance:tenant:{instance_name}API keys são validadas via HMAC com secret dedicado. Hash do API key (não a key em si) é cacheada para lookups rápidos.
// API Key validation flow:
1. Webhook chega com X-API-Key header
2. HMAC(apikey, EVOLUTION_SECRET) → hash
3. Redis lookup: apikeyhash:tenant:
4. Se match → autorizado
5. Se não → schema scan (fallback)FastAPI + Uvicorn
Redis 8.2 (isolated) + MinIO
WebSocket (25 concurrent)
Evolution API
Audio Processor (STT/TTS)
OpenTelemetry + Prometheus
60 req/min configurable
HTTPX (30s timeout, 3 retries)
Message aggregation, webhooks, multi-tenant instances - tenho experiência prática com os desafios reais.