Pular para o conteúdo

01 — Visão Geral da Arquitetura

O que estamos construindo

Plataforma de agentes conversacionais WhatsApp multi-tenant. Cada agente é um produto independente que serve múltiplos clientes simultaneamente, com configuração isolada por cliente.

Diagrama de alto nível

┌──────────────────────────────────────────────────────────────────┐
│ CAMADA DE ENTRADA │
│ │
│ Evolution API Stevo │
│ (clientes Kommo) (clientes GHL) │
│ │ │ │
│ └──────┬───────────────┘ │
│ ↓ │
│ Webhook Triadeflow │
│ (api.triadeflow.com.br/webhooks/{provider}/{tenant}) │
│ ↓ │
│ Fila BullMQ (Redis) │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ CAMADA DE PROCESSAMENTO │
│ │
│ Worker Python (LangChain + LangGraph) │
│ ├── Identifica tenant pela instance │
│ ├── Carrega config.yaml do tenant │
│ ├── Carrega histórico (Redis) │
│ ├── Busca contexto (Qdrant via RAG) │
│ ├── Executa LangGraph com Claude │
│ ├── Chama tools necessárias │
│ └── Envia resposta via provider │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ CAMADA DE INTEGRAÇÃO │
│ │
│ CRM Tools Calendar Pagamento Helpdesk │
│ Kommo / GHL Google Stripe/Asaas Asana │
│ │
│ Catálogo Sistemas LGPD Notificação │
│ Qdrant Verticais Compliance Telegram │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ CAMADA DE OBSERVABILIDADE │
│ │
│ Langfuse self-hosted (Hetzner) │
│ ├── Traces (todo I/O do agente) │
│ ├── Datasets (casos de eval) │
│ ├── Annotations (revisão humana) │
│ ├── Prompts versionados │
│ └── Scores (LLM-as-judge + métricas) │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ CAMADA DE VISUALIZAÇÃO │
│ │
│ Langfuse UI (técnico) Power BI (executivo/cliente) │
│ ├── Trace explorer ├── Dashboard por cliente │
│ ├── Sessions ├── KPIs de negócio │
│ ├── Comparação de runs ├── ROI │
│ └── Custo por modelo └── Relatórios mensais │
└──────────────────────────────────────────────────────────────────┘

Fluxo de uma mensagem real

Exemplo: cliente USA Salus tem agent-sdr ativo. Lead chega via WhatsApp.

1. Lead manda "Oi, vi anúncio sobre emagrecimento"
2. Stevo (porque USA Salus é GHL) recebe
3. Stevo dispara webhook para api.triadeflow.com.br/webhooks/stevo/usa_salus
4. Webhook handler valida e empurra pra fila BullMQ
5. Worker do agent-sdr pega da fila
6. Worker identifica:
- tenant_id: usa_salus
- agent_type: sdr
- provider: stevo
7. Carrega tenants/usa_salus/config.yaml
8. Carrega histórico do Redis (key: conv:usa_salus:5585999...)
9. Inicia trace no Langfuse com metadata
10. Executa LangGraph:
- Nó 1: classifica intenção
- Nó 2: busca contexto no Qdrant (collection: usa_salus_kb)
- Nó 3: chama Claude Sonnet com prompt + contexto + tools
11. Claude decide: responder + iniciar qualificação
12. Worker formata resposta e envia via Stevo API
13. Stevo entrega no WhatsApp do lead
14. Worker salva no Redis (histórico atualizado)
15. Worker chama tool: atualiza GHL com etapa "primeiro contato"
16. Trace fechado no Langfuse:
- input/output completo
- tools chamadas
- latência: 1.8s
- tokens: 1200/80
- custo: $0.012
17. Em background, LLM-as-judge avalia o trace e gera score

Repositórios envolvidos

triadeflow-org/ GitHub Organization
├── triadeflow-core/ Biblioteca compartilhada
├── agent-template/ Template para novos agentes
├── agent-sdr/ Produto: SDR
├── agent-vendas/ Produto: Vendas
├── agent-suporte/ Produto: Suporte
├── agent-agendamento/ Produto: Agendamento
├── agent-recuperacao/ Produto: Recuperação
├── agent-cobranca/ Produto: Cobrança
├── agent-pos-venda/ Produto: Pós-venda
├── agent-prospeccao-ativa/ Produto: Prospecção
├── agent-pesquisa-nps/ Produto: NPS
├── triadeflow-admin/ Painel multi-tenant
└── triadeflow-docs/ Esta documentação

Infraestrutura de produção

ComponenteOnde rodaPortaDomínio
Workers (todos os agentes)Hetzner Cloud (CPX21)--
Webhook APIHetzner + Caddy443api.triadeflow.com.br
LangfuseHetzner + Docker3000langfuse.triadeflow.com.br
QdrantHetzner + Docker6333qdrant.triadeflow.com.br
Redis (BullMQ + memória)Hetzner + Docker6379(interno)
Postgres (Langfuse + tenants)Hetzner + Docker5432(interno)
Power BIMicrosoft Cloud--

Decisões arquiteturais críticas

1. Por que separar agentes em produtos independentes?

Decisão: cada tipo de agente (SDR, vendas, suporte, etc) é repositório, deploy e produto separado.

Motivo:

  • Manutenção isolada (bug em vendas não afeta SDR)
  • Pricing modular
  • Métricas claras por produto
  • Times podem ser donos de produtos diferentes
  • Novo tipo de agente = clonar template, sem refatoração

Trade-off aceito:

  • Mais repositórios para manter
  • Algum código duplicado (mitigado pelo triadeflow-core)

2. Por que multi-tenant na mesma instância e não 1 deploy por cliente?

Decisão: uma instância de cada agente serve N clientes simultaneamente.

Motivo:

  • Custo de infraestrutura escala bem (1 worker, N clientes)
  • Atualização do código atinge todos de uma vez
  • Onboarding de novo cliente = só criar pasta tenants/{tenant_id}/
  • Compartilhamento de modelos e custos da Anthropic API

Trade-off aceito:

  • Bug afeta todos os clientes ao mesmo tempo (mitigado por testes e canary deploy)
  • Limites de rate da Anthropic API são compartilhados

3. Por que Langfuse self-hosted?

Decisão: Langfuse rodando no Hetzner em Docker, não SaaS.

Motivo:

  • Compliance LGPD (dados dos clientes não saem da infra Triadeflow)
  • Custo previsível (volume alto fica caro no SaaS)
  • Sem limite de retenção
  • Possibilidade de customização

Trade-off aceito:

  • Manutenção da infraestrutura é responsabilidade da Triadeflow
  • Updates manuais

4. Por que sem orquestrador entre agentes?

Decisão: múltiplos agentes do mesmo cliente = múltiplos números WhatsApp distintos. Não há um “agente mestre” roteando entre eles.

Motivo:

  • Clareza para o cliente final (cada número, uma função)
  • Times humanos podem ser diferentes (vendas vs CS)
  • Métricas separadas por canal
  • Implementação mais simples
  • Deploy independente

Trade-off aceito:

  • Cliente precisa direcionar público para o número certo (resolvido com material de marketing)

Próximos documentos