Pular para o conteúdo principal

Schema do Banco de Dados

O Disparador de Campanhas utiliza um banco de dados MySQL para armazenar informações sobre agentes, conversas, mensagens, webhooks e logs.

Diagrama ER

┌─────────────┐          ┌──────────────────┐
│ agent │────┬────<│ agent_contact │
└─────────────┘ │ └──────────────────┘

│ ┌──────────────────┐
└────<│ conversation │
└────────┬─────────┘

┌────────▼─────────┐
│ message │
└──────────────────┘

┌──────────────────────┐
│ webhook │
└──────────────────────┘

┌──────────────────────┐
│ logs │
└──────────────────────┘

┌──────────────────────┐
│ conversation_insights│
└──────────────────────┘

Tabelas

1. agent

Armazena configurações dos agentes de IA.

CREATE TABLE `agent` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`instructions` longtext, -- Instruções/prompt do agente
`functions` json DEFAULT NULL, -- Funções disponíveis (JSON)
`inbox_id` int DEFAULT NULL, -- ID do inbox no Chatwoot
`status` int DEFAULT NULL, -- 0: inativo, 1: ativo
`team_id` int DEFAULT NULL, -- ID do time responsável
`assigned_contact_id` int DEFAULT NULL, -- Contato atribuído
`testword` text, -- Palavra-chave de teste
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Campos importantes:

  • instructions: Prompt base do agente (ex: "Você é um assistente de vendas...")
  • functions: Lista de funções que o agente pode chamar (formato JSON)
  • inbox_id: Qual inbox do Chatwoot esse agente gerencia
  • status: Se o agente está ativo (1) ou inativo (0)

2. agent_contact

Relacionamento N:N entre agentes e contatos.

CREATE TABLE `agent_contact` (
`id` int NOT NULL AUTO_INCREMENT,
`contact_id` int NOT NULL,
`agent_id` int NOT NULL,
PRIMARY KEY (`id`),
KEY `contact_id` (`contact_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Uso: Permite que um contato seja gerenciado por múltiplos agentes ou que um agente gerencie múltiplos contatos.


3. conversation

Armazena conversas ativas e históricas.

CREATE TABLE `conversation` (
`id` int NOT NULL AUTO_INCREMENT,
`external_id` int DEFAULT NULL, -- ID da conversa no Chatwoot
`contact_id` int DEFAULT NULL, -- ID do contato
`inbox_id` int DEFAULT NULL, -- ID do inbox
`status` int DEFAULT NULL, -- Status da conversa
`last_interaction_at` datetime DEFAULT NULL,
`account_id` int DEFAULT NULL, -- ID da conta no Chatwoot
`retry_times` int DEFAULT '0', -- Tentativas de reprocessamento
`is_over` int DEFAULT NULL, -- Conversa finalizada?
`last_source_id` varchar(200) DEFAULT NULL, -- Source ID do último contato
`origin` varchar(50) DEFAULT NULL, -- Origem (whatsapp, instagram, etc)
PRIMARY KEY (`id`),
UNIQUE KEY `uk_external_contact_inbox` (`external_id`,`contact_id`,`inbox_id`),
KEY `account_id` (`account_id`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Campos importantes:

  • external_id: ID da conversa no Chatwoot (para sincronização)
  • status: Status atual (0: aberta, 1: resolvida, 2: pendente)
  • retry_times: Quantas vezes tentou reprocessar (útil para erros)
  • is_over: Flag se conversa foi finalizada
  • origin: Canal de origem (whatsapp, instagram, webchat)

4. message

Armazena todas as mensagens processadas.

CREATE TABLE `message` (
`id` int NOT NULL AUTO_INCREMENT,
`payload` json DEFAULT NULL, -- Payload completo da mensagem
`content` longtext, -- Conteúdo da mensagem
`processed` int DEFAULT NULL, -- Status: 0: não processado, 1: processado
`grouping` varchar(100) DEFAULT NULL, -- Agrupamento (para campanhas)
`created_at` datetime DEFAULT NULL,
`source` varchar(100) DEFAULT NULL, -- Fonte da mensagem
`account_id` int DEFAULT NULL,
`inbox_id` int DEFAULT NULL,
`role` varchar(50) DEFAULT NULL, -- 'user' ou 'assistant'
`external_id` varchar(100) DEFAULT NULL, -- ID externo (Chatwoot)
`sub_external_id` varchar(100) DEFAULT NULL,
`type` varchar(30) DEFAULT NULL, -- Tipo de mensagem
`agent_id` int DEFAULT NULL,
`message_id` int DEFAULT NULL,
`execution_id` varchar(255) DEFAULT NULL, -- ID da execução no N8N
PRIMARY KEY (`id`),
KEY `processed` (`processed`),
KEY `account_id` (`account_id`),
KEY `inbox_id` (`inbox_id`),
KEY `agent_id` (`agent_id`),
KEY `external_id` (`external_id`),
KEY `sub_external_id` (`sub_external_id`),
KEY `grouping` (`grouping`),
KEY `source` (`source`),
KEY `execution_id` (`execution_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Campos importantes:

  • payload: JSON completo da mensagem (útil para debug)
  • content: Texto da mensagem
  • processed: Se foi processada pelo sistema (0: pendente, 1: processado)
  • grouping: Identificador de campanha/lote
  • role: Quem enviou ('user' = cliente, 'assistant' = IA/atendente)
  • execution_id: ID da execução no N8N (rastreabilidade)

5. webhook

Armazena webhooks recebidos (auditoria).

CREATE TABLE `webhook` (
`id` int NOT NULL AUTO_INCREMENT,
`payload` json DEFAULT NULL, -- Payload completo do webhook
`created_at` datetime DEFAULT NULL,
`origin` varchar(100) DEFAULT NULL, -- Origem (chatwoot, meta, brevo)
`type` varchar(50) DEFAULT NULL, -- Tipo do evento
`external_id` varchar(200) DEFAULT NULL, -- ID externo único
PRIMARY KEY (`id`),
UNIQUE KEY `external_id` (`external_id`),
KEY `origin` (`origin`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Uso: Auditoria de todos os webhooks recebidos. Útil para:

  • Debug de problemas
  • Replay de eventos
  • Análise de tráfego

6. logs

Logs gerais do sistema.

CREATE TABLE `logs` (
`id` int NOT NULL AUTO_INCREMENT,
`payload` json NOT NULL, -- Dados do log em JSON
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`status` int NOT NULL DEFAULT '0', -- Status do processamento
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Uso: Logs genéricos que não se encaixam em outras tabelas.


7. conversation_insights

Insights e métricas de conversas (campanhas).

CREATE TABLE `conversation_insights` (
`id` int NOT NULL AUTO_INCREMENT,
`conversation_id` int NOT NULL,
`name` varchar(200) NOT NULL, -- Nome do contato
`phone_number` varchar(50) NOT NULL,
`contact_id` int NOT NULL,
`has_reply` int NOT NULL, -- 0: não respondeu, 1: respondeu
PRIMARY KEY (`id`),
UNIQUE KEY `conversation_id` (`conversation_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Uso: Análise de campanhas

  • Quantos responderam?
  • Taxa de resposta por campanha
  • Identificar contatos engajados

Queries Úteis

Contadores de Conversas por Status

SELECT
status,
COUNT(*) as total,
origin
FROM conversation
WHERE account_id = 1
GROUP BY status, origin;

Mensagens Não Processadas

SELECT
id,
content,
created_at,
inbox_id
FROM message
WHERE processed = 0
ORDER BY created_at DESC
LIMIT 50;

Taxa de Resposta de Campanha

SELECT
COUNT(*) as total_sent,
SUM(has_reply) as replied,
ROUND(SUM(has_reply) / COUNT(*) * 100, 2) as reply_rate_percent
FROM conversation_insights;

Últimos Webhooks Recebidos

SELECT
id,
origin,
type,
created_at
FROM webhook
ORDER BY created_at DESC
LIMIT 20;

Mensagens por Agente

SELECT
a.name as agent_name,
COUNT(m.id) as total_messages,
SUM(CASE WHEN m.role = 'assistant' THEN 1 ELSE 0 END) as sent_by_agent,
SUM(CASE WHEN m.role = 'user' THEN 1 ELSE 0 END) as received_from_user
FROM agent a
LEFT JOIN message m ON m.agent_id = a.id
GROUP BY a.id, a.name;

Índices Importantes

Os índices existentes garantem performance para:

  1. Busca por conversa: external_id, contact_id, inbox_id
  2. Filtragem de mensagens: processed, account_id, inbox_id, grouping
  3. Rastreabilidade: execution_id, external_id
  4. Auditoria: origin (webhook), status (conversation)

Manutenção

Limpeza de Logs Antigos

-- Remover logs com mais de 30 dias
DELETE FROM logs
WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);

-- Remover webhooks antigos (mais de 90 dias)
DELETE FROM webhook
WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY);

Backup Recomendado

# Dump diário
mysqldump -u user -p whatsapp > backup_$(date +%Y%m%d).sql

# Apenas estrutura (sem dados)
mysqldump -u user -p --no-data whatsapp > schema.sql

Próximos Passos