Chatwoot Messages
Este workflow processa mensagens do evento message_created do Chatwoot, filtrando apenas mensagens válidas de contatos (não de bots), e encaminha para processamento com IA. Resolve:
- Evitar loops de bot respondendo bot
- Processar apenas mensagens de texto ou com anexos
- Garantir que apenas conversas sem atendente humano sejam processadas automaticamente
- Armazenar histórico completo para análise
O Que Este Fluxo Faz
Fluxo Principal
- Recebe webhook
message_createddo Chatwoot - Valida condições para processar a mensagem:
- ✅ Sender é do tipo
contact(não é bot) - ✅ Mensagem não está
private(visível para o contato) - ✅ Conversa não está atribuída a um atendente humano
- ✅ Conversa não está em um time específico
- ✅ Sender é do tipo
- Separa em dois fluxos baseado no tipo:
Fluxo A: Mensagens com Anexo
- Condição: Possui
attachmentsnão vazio - Ações:
- Salva conversa no banco (tabela
conversation) - Executa Type Message Router (subflow):
- Processa imagens → Extrai base64
- Processa áudios → Transcreve com OpenAI
- Processa arquivos, contatos, localizações → Extrai metadados
- Salva mensagem processada no banco (tabela
message) - Executa Process Messages para gerar resposta com IA
- Salva conversa no banco (tabela
Fluxo B: Mensagens de Texto
- Condição: Não possui anexos
- Ações:
- Salva conversa no banco (tabela
conversation) - Salva mensagem no banco (tabela
message) - Executa Process Messages para gerar resposta com IA
- Salva conversa no banco (tabela
Como a IA Processa as Mensagens
Após salvar a mensagem no banco, o workflow executa um fluxo complexo de processamento com IA usando OpenAI (ou LLM configurado). Veja o diagrama completo:
Detalhamento do Processamento
1. Busca do Agent (Get Agents)
O workflow busca o agent (configuração de IA) mais adequado baseado em prioridade:
SELECT a.* FROM agent a
LEFT JOIN agent_contact ac ON ac.agent_id = a.id
WHERE a.status = '1' AND a.inbox_id = '{inbox_id}'
AND (
a.assigned_contact_id = '{contact_id}' -- Prioridade 1
OR ac.contact_id IS NOT NULL -- Prioridade 2
OR a.assigned_contact_id IS NULL -- Prioridade 3 (genérico)
)
ORDER BY [prioridade] LIMIT 1
Tabela agent:
id: ID do agentinstructions: Prompt base (system prompt)functions: JSON com lista de functions disponíveisinbox_id: Inbox associadaassigned_contact_id: Se específico para um contatoteam_id: Se vinculado a um timetestword: Palavra-chave para ativação (opcional)
2. Montagem do Contexto (Agent Settings)
O nó Agent Settings monta o payload completo para a OpenAI:
{
"input": [
{
"role": "system",
"content": [{
"type": "input_text",
"text": `${instructions}
## Dados da conversa
Data e Hora Atual: ${now}
Nome do usuário: ${nome}
Telefone: ${telefone}
E-mail: ${email}
User ID: ${platform_id || 'Não informado'}
Chat ID: ${conversation_id}
Account ID: ${account_id}
Inbox ID: ${inbox_id}
`
}]
},
// Histórico de mensagens (user, assistant, function_call, function_call_output)
],
"tools": [...], // Functions disponíveis
"model": "gpt-4.1-mini",
"temperature": 0.4,
"max_output_tokens": 2048
}
Tipos de mensagens no histórico:
user(text): Mensagem de texto do usuáriouser(image): Imagem em base64assistant: Resposta da IAfunction_call: IA solicitou executar uma functionfunction_call_output: Resultado da execução da function
3. Resposta da OpenAI
A API retorna um dos dois tipos:
Tipo 1: Texto (output_text)
{
"id": "msg_abc123",
"output": [{
"content": [{
"type": "output_text",
"text": "Olá! Como posso ajudar?"
}]
}]
}
→ Salvo como role=assistant → Quebrado em blocos de 140 chars → Enviado ao Chatwoot
Tipo 2: Function Call
{
"id": "msg_abc123",
"type": "function_call",
"call_id": "call_xyz789",
"name": "search_knowledge_base",
"arguments": "{\"query\": \"como emitir certificado\"}"
}
→ Salvo como role=function_call → Executa workflow correspondente → Salva output como role=function_call_output → Reinicia fluxo IA
4. Tree Tools (Mapeamento de Functions)
O nó Tree Tools mapeia cada function_name para seu workflow_id:
| Function Name | Workflow ID | Descrição |
|---|---|---|
transfer_to_human | 0V2b41jDw9rbfIWd | Transfere para atendente humano |
search_knowledge_base | AAtFzeQnDevWVuJ4 | Busca na base de conhecimento (Dify) |
end_conversation | JZ5i8erPnHoViFNw | Finaliza conversa |
formulario_login | SGv14qbAvQCMNTGK | Coleta dados de login |
get_matriculas | YYZLerBm3hqdU4Dq | Busca matrículas do aluno |
get_certificate | uTYdQjEsQMbecm2z | Gera certificado |
create_transaction | cYI8xPDhp1VI4a8W | Cria transação de pagamento |
| ...e mais 11 functions | - | Diversas integrações |
5. Loop de Function Calling
Quando a IA retorna uma function_call:
- Salva a function call no banco (
role=function_call) - Executa o workflow correspondente
- Salva o resultado (
role=function_call_output) - Busca novamente todas as mensagens (incluindo a nova output)
- Reenvia para a OpenAI com contexto atualizado
- Repete até a IA retornar texto (não function_call)
Este loop permite que a IA:
- Busque informações antes de responder
- Execute múltiplas ações em sequência
- Tome decisões baseadas nos resultados das functions
Estrutura do Banco de Dados
Tabela agent
- id: ID do agent (auto increment)
- instructions: Prompt base (system prompt) da IA
- functions: JSON com lista de functions disponíveis
- inbox_id: ID da inbox associada
- assigned_contact_id: Contact ID específico (NULL = genérico)
- team_id: Team ID vinculado (opcional)
- testword: Palavra-chave de ativação (opcional)
- status: 1 (ativo) ou 0 (inativo)
- created_at: Timestamp de criação
Tabela agent_contact
- id: ID do registro (auto increment)
- agent_id: Referência ao agent
- contact_id: Referência ao contato do Chatwoot
- created_at: Timestamp de associação
Tabela conversation
- external_id: ID da conversa no Chatwoot
- contact_id: ID do contato
- inbox_id: ID da inbox
- account_id: ID da conta Chatwoot
- status: 0 (pendente) ou 1 (processando)
- last_source_id: ID da última mensagem
- origin: Número de telefone do contato
- last_interaction_at: Última interação
Tabela message
- payload: JSON completo da mensagem
- content: Conteúdo (texto, base64, metadados ou JSON)
- source: "{conversation_id}_{contact_id}"
- processed: 0 (não processada) ou 1 (processada)
- account_id: ID da conta
- inbox_id: ID da inbox
- role: "user", "assistant", "function_call", "function_call_output"
- type: "text", "image", etc
- message_id: ID da mensagem no Chatwoot
- external_id: ID externo (da OpenAI)
- sub_external_id: call_id (para function calls)
- execution_id: ID da execução no N8N
- grouping: Agrupamento (opcional)
- created_at: Timestamp
Setup
1. Configurar Webhook no Chatwoot
- Acesse Chatwoot > Settings > Integrations > Webhooks
- Adicione um novo webhook:
- URL:
https://n8n-queue.incibrasil.com.br/webhook/incoming - Eventos: Marcar apenas
message_created
- URL:
- Salve e teste o webhook
2. Configurar Agent (IA)
Para criar um novo agent com IA personalizada:
- Insira um registro na tabela
agent:
INSERT INTO agent (instructions, functions, inbox_id, status) VALUES (
'Você é um assistente virtual prestativo. Seu objetivo é...',
'[{"type": "function", "function": {"name": "search_knowledge_base", "description": "..."}}, ...]',
8, -- ID da inbox
1 -- Ativo
);
- (Opcional) Associe o agent a contatos específicos:
INSERT INTO agent_contact (agent_id, contact_id) VALUES (1, 12345);
3. Configurar Workflows Relacionados
Este workflow depende de outros workflows que devem estar ativos:
- Type Message Router (ID:
9h1KXLbdEtAmp11C): Processa anexos - Chatwoot Messages - Sender: Envia respostas ao Chatwoot
- Function workflows: Cada function mapeada em Tree Tools deve ter seu workflow
4. Adicionar Nova Conta Chatwoot
Este workflow está preparado para múltiplas contas. Se você precisar adicionar suporte para uma nova conta:
- Não é necessário alterar este workflow
- Configure apenas:
- Webhook no Chatwoot da nova conta
- Credenciais de bot no workflow Chatwoot Messages - Sender
Observações Importantes
- ✅ Este workflow processa apenas mensagens de contatos, não de bots
- ✅ Ignora mensagens de conversas já atribuídas a atendentes humanos
- ✅ Ignora mensagens privadas (anotações internas)
- ⚠️ Mensagens com anexos passam por processamento extra (Type Message Router)
- ⚠️ Se o banco estiver indisponível, mensagens são perdidas (sem retry)
- ⚠️ Todas as mensagens são salvas com
processed: 0aguardando processamento posterior
Workflows Relacionados
- WhatsApp Webhook: Recebe mensagens do WhatsApp → Chatwoot
- Type Message Router: Processa anexos (áudio, imagem, arquivo, etc.)
- Chatwoot Messages - Sender: Envia respostas da IA de volta ao Chatwoot