{
  "name": "Chatbot SDR WhatsApp v2 - Evolution (so Postgres, F2A)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "whatsapp-evolution",
        "options": {}
      },
      "id": "cb775005-6734-449d-a4d8-d9fe80511b9d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "07f70731-b9b1-4a6c-8182-20fa63215a71",
              "operator": {
                "type": "string",
                "operation": "notEndsWith"
              },
              "leftValue": "={{ $json.body.data.key.remoteJid }}",
              "rightValue": "@g.us"
            },
            {
              "id": "94dcddc1-2dcf-4ac3-a1cf-6fcd17831d91",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.data.key.fromMe }}",
              "rightValue": ""
            }
          ]
        },
        "options": {}
      },
      "id": "a71e0637-a07e-418a-9d01-f6a8a3d6de81",
      "name": "So conversa individual (anti-grupo)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        220,
        400
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "b220c22e-e569-4c2f-9048-8fd990b3ba98",
              "name": "sessionId",
              "type": "string",
              "value": "={{ $json.body.data.key.remoteJid.split('@')[0] }}"
            },
            {
              "id": "05e88e49-c7b8-48d8-93ff-d57b5cda735c",
              "name": "texto",
              "type": "string",
              "value": "={{ $json.body.data.message.conversation || $json.body.data.message.extendedTextMessage?.text || '' }}"
            },
            {
              "id": "792ed089-e989-4522-a0e0-6d228cbe09b0",
              "name": "msgId",
              "type": "string",
              "value": "={{ $json.body.data.key.id }}"
            }
          ]
        },
        "options": {}
      },
      "id": "6ebffd77-1c47-40fe-86e0-bc0bc47f45a3",
      "name": "Extrai dados",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        440,
        320
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "CREATE TABLE IF NOT EXISTS msg_buffer (\n  id BIGSERIAL PRIMARY KEY,\n  session_id VARCHAR(30) NOT NULL,\n  texto TEXT NOT NULL,\n  msg_id VARCHAR(255) NOT NULL,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\nCREATE INDEX IF NOT EXISTS idx_msg_buffer_session ON msg_buffer (session_id, created_at DESC);",
        "options": {}
      },
      "id": "cd8b2d52-f9f8-4bdb-80d4-fbfd65af65ba",
      "name": "Cria tabela buffer",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        640,
        320
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "msg_buffer"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "session_id": "={{ $('Extrai dados').item.json.sessionId }}",
            "texto": "={{ $('Extrai dados').item.json.texto }}",
            "msg_id": "={{ $('Extrai dados').item.json.msgId }}"
          },
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true,
          "schema": [
            {
              "id": "id",
              "type": "number",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "id",
              "canBeUsedToMatch": true
            },
            {
              "id": "session_id",
              "type": "string",
              "display": true,
              "required": true,
              "displayName": "session_id",
              "canBeUsedToMatch": true
            },
            {
              "id": "texto",
              "type": "string",
              "display": true,
              "required": true,
              "displayName": "texto",
              "canBeUsedToMatch": true
            },
            {
              "id": "msg_id",
              "type": "string",
              "display": true,
              "required": true,
              "displayName": "msg_id",
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "dateTime",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "created_at",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      },
      "id": "1a2d4329-bf7f-4fad-817b-5c595c82d7ea",
      "name": "Empilha no buffer",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        840,
        320
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "amount": 8,
        "unit": "seconds"
      },
      "id": "ca82271f-6e3a-49aa-adc3-4bc8a858b454",
      "name": "Espera (debounce)",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1040,
        320
      ],
      "webhookId": "7ceb7de9-d154-45f7-b178-3aef0e24dbc0"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT msg_id FROM msg_buffer WHERE session_id = '{{ $('Extrai dados').item.json.sessionId }}' ORDER BY created_at DESC LIMIT 1;",
        "options": {}
      },
      "id": "36f05df3-9c43-423c-96ce-69b8e5e00308",
      "name": "Pega ultima do buffer",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1240,
        320
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9783f504-5262-432e-9800-6d4112060740",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.msg_id }}",
              "rightValue": "={{ $('Extrai dados').item.json.msgId }}"
            }
          ]
        },
        "options": {}
      },
      "id": "71ba2972-c1fd-457c-967b-618bd2461419",
      "name": "Sou a ultima?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1440,
        320
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT string_agg(texto, ' ' ORDER BY created_at) AS mensagem FROM msg_buffer WHERE session_id = '{{ $('Extrai dados').item.json.sessionId }}';",
        "options": {}
      },
      "id": "467d7d84-fe61-4e6e-973c-b33d9b59fbd1",
      "name": "Junta mensagens",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1640,
        240
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM msg_buffer WHERE session_id = '{{ $('Extrai dados').item.json.sessionId }}';",
        "options": {}
      },
      "id": "08d334a3-25e1-4c92-acff-4c4e47e7c997",
      "name": "Limpa buffer",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1840,
        240
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $('Junta mensagens').item.json.mensagem }}",
        "options": {
          "systemMessage": "# IDENTIDADE\n\nVocê é o assistente de pré-vendas (SDR) e recuperação de vendas da **[SUA EMPRESA]** (descreva seu negócio numa linha). Sua função no WhatsApp é:\n\n1. **Atender leads novos** (que vieram de criativos, indicação, formulário)\n2. **Recuperar leads inativos** (que viram a oferta mas não fecharam, ou abriram conversa e sumiram)\n3. **Qualificar e agendar** call com humano quando o lead estiver pronto\n\n# TOM DE VOZ (CRÍTICO)\n\nVocê fala **EXATAMENTE como um SDR humano da [SUA EMPRESA] falaria no WhatsApp**:\n\n- **Português brasileiro coloquial**. Mistura \"tu\" e \"você\" naturalmente.\n- **Frases curtas**. Quebra em várias mensagens quando faz sentido.\n- **Marcadores humanos**: \"pô\", \"tipo\", \"basicamente\", \"enfim\", \"na real\", \"inclusive\", \"sacou?\", \"tá ligado?\"\n- **Áudio do WhatsApp em texto**: leia em voz alta — se soar como apresentação corporativa, está errado.\n- **NUNCA usa**: \"amigão\", \"imagina só\", \"e se eu te dissesse\", \"deixa eu ser honesto\", travessões (—), reticências de IA, \"literalmente\" em excesso, \"incrível\", \"transforme sua vida\".\n- **Reticências** são amigas — uso natural pra dar respiração.\n- **Áudios de áudio**: se o lead manda áudio, responde com paciência tipo \"ó, escutei aqui, então...\"\n- **Vocativos**: \"cara\", \"mano\", \"meu querido\"/\"minha querida\", \"galera\". Adapta pelo gênero/idade aparente do lead.\n\n# FLUXO SDR\n\n## Lead NOVO chegou (primeira msg)\n1. **Cumprimenta** breve + apresenta-se (\"Fala, [nome]! Aqui é o [seu_nome] da [SUA EMPRESA]. Tudo bem?\")\n2. **Identifica origem** sem ser invasivo (\"Vi que tu deixou contato no [criativo/site] — me conta rapidão o que tu tá buscando?\")\n3. **Escuta a dor** sem empurrar venda\n4. **Qualifica** com perguntas BANT light (já tem agência? já roda tráfego pago? qual investimento médio mensal? quando quer começar?)\n5. **Agenda call** se tem fit (oferecer 2-3 horários, não 5+; deixar a decisão fácil)\n\n## Lead INATIVO retornando (já conversou antes)\n1. **Resgata contexto** (\"Oi, [nome]! Lembra que tu tinha conversado comigo sobre [tema]?\")\n2. **Reabre com curiosidade**, não com pressão (\"Apareceu uma coisa que vai te interessar / o que tu achou da proposta?\")\n3. **Identifica objeção residual** (preço? timing? cônjuge? confiança?)\n4. **Trata objeção com case real ou prova** (sem inventar)\n5. **Reencaminha pra call ou material** dependendo do nível\n\n# LIMITES (CRÍTICOS)\n\n- **NÃO inventa números, cases, garantias ou prazos** que não foram informados no contexto.\n- **NÃO promete resultado específico** (\"vai dobrar seu faturamento em 30 dias\").\n- **NÃO desce o preço** sem autorização — quando perguntarem valor, fala que depende do escopo e leva pra call.\n- **NÃO discute concorrente** de forma negativa.\n- Quando o lead estiver pronto pra fechar ou pedir algo fora do teu escopo, **passa pra humano**: \"Show, vou alinhar com [seu nome/closer] aqui e ele te chama em até X horas.\"\n\n# HISTÓRICO\n\nVocê tem memória automática desta conversa (as últimas mensagens deste mesmo número). Use pra dar continuidade, não repetir perguntas e retomar pontos abertos.\n\n# OUTPUT\n\nResponda APENAS o texto que vai pro lead. Sem prefixo, sem aspas, sem markdown — fala como pessoa fala no WhatsApp.",
          "enableStreaming": false,
          "maxIterations": 10
        }
      },
      "id": "eb83950e-d558-4d81-b36b-385c6270ad04",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        2060,
        240
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "mimo-v2.5-pro",
          "cachedResultName": "mimo-v2.5-pro"
        },
        "responsesApiEnabled": false,
        "options": {
          "baseURL": "https://api.xiaomimimo.com/v1",
          "temperature": 0
        }
      },
      "id": "615aed14-a062-40dc-a945-60855ff0a5bc",
      "name": "MiMo v2.5-pro",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        2000,
        460
      ],
      "credentials": {
        "openAiApi": {
          "id": "SUBSTITUIR_LLM",
          "name": "MiMo v2.5-pro (OpenAI-compat)"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Extrai dados').item.json.sessionId }}",
        "tableName": "n8n_chat_histories",
        "contextWindowLength": 15
      },
      "id": "78d5c13a-3182-42aa-9ee8-9f1914071754",
      "name": "Memoria (Postgres)",
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.4,
      "position": [
        2200,
        460
      ],
      "credentials": {
        "postgres": {
          "id": "SUBSTITUIR_POSTGRES",
          "name": "Postgres"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://SEU_EVOLUTION_BASE/message/sendText/SEU_INSTANCE",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "SEU_EVOLUTION_API_KEY"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ number: $('Extrai dados').item.json.sessionId, text: $('AI Agent').item.json.output }) }}",
        "options": {}
      },
      "id": "4ed4132c-4cf6-4a09-8ef7-32a7a0b50690",
      "name": "Envia (Evolution)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2280,
        240
      ]
    },
    {
      "parameters": {},
      "id": "3e1b1929-2b22-4956-af3f-40ddd7e823c6",
      "name": "Ignora (grupo/eco/duplicada)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        840,
        560
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "So conversa individual (anti-grupo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "So conversa individual (anti-grupo)": {
      "main": [
        [
          {
            "node": "Extrai dados",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Ignora (grupo/eco/duplicada)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extrai dados": {
      "main": [
        [
          {
            "node": "Cria tabela buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cria tabela buffer": {
      "main": [
        [
          {
            "node": "Empilha no buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Empilha no buffer": {
      "main": [
        [
          {
            "node": "Espera (debounce)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Espera (debounce)": {
      "main": [
        [
          {
            "node": "Pega ultima do buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pega ultima do buffer": {
      "main": [
        [
          {
            "node": "Sou a ultima?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sou a ultima?": {
      "main": [
        [
          {
            "node": "Junta mensagens",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Ignora (grupo/eco/duplicada)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Junta mensagens": {
      "main": [
        [
          {
            "node": "Limpa buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limpa buffer": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Envia (Evolution)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MiMo v2.5-pro": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Memoria (Postgres)": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}