{
  "name": "Chatbot SDR WhatsApp v2 - Cloud API oficial (so Postgres, F2A)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "whatsapp-cloud",
        "options": {}
      },
      "id": "2f16e05e-f7eb-4499-8ff9-4c4cab9f1c29",
      "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": "204b38ce-0986-4d6c-af06-b9c2af976ac5",
              "operator": {
                "type": "array",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages }}",
              "rightValue": ""
            }
          ]
        },
        "options": {}
      },
      "id": "c5c01d13-2790-4d31-a94d-7099d18ab9a8",
      "name": "Mensagem recebida (nao status)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        220,
        400
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "aaa6467a-28d2-4209-92cd-ac4288a5c48d",
              "name": "sessionId",
              "type": "string",
              "value": "={{ $json.body.entry[0].changes[0].value.messages[0].from }}"
            },
            {
              "id": "f142419c-0e15-4e76-856e-a2d8348607e8",
              "name": "texto",
              "type": "string",
              "value": "={{ $json.body.entry[0].changes[0].value.messages[0].text.body }}"
            },
            {
              "id": "ee044328-11dd-439f-acd5-4b137ae531b0",
              "name": "msgId",
              "type": "string",
              "value": "={{ $json.body.entry[0].changes[0].value.messages[0].id }}"
            }
          ]
        },
        "options": {}
      },
      "id": "66ab6cc8-0492-4899-8805-209feb3fde50",
      "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": "c98c480f-b663-4752-a814-ce7764611f2f",
      "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": "78bdfc6c-f928-462e-9529-4a9547d96448",
      "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": "bd39b735-7585-416e-a7a9-307d4f0a09df",
      "name": "Espera (debounce)",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1040,
        320
      ],
      "webhookId": "0a90f86b-b10f-474d-b784-6ab539dc615b"
    },
    {
      "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": "f1e272f8-e01e-4e37-83ab-af9d2b0d0195",
      "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": "eb2830f6-29b3-4cf8-abe7-0bde2ee24366",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.msg_id }}",
              "rightValue": "={{ $('Extrai dados').item.json.msgId }}"
            }
          ]
        },
        "options": {}
      },
      "id": "d4609406-7a5b-45bd-a5bd-b5da4f95b0b5",
      "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": "ba3299d4-1e2f-49bc-8dcb-387c713c2a7c",
      "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": "b3d351aa-540e-40e1-8221-782c7ed2d6a2",
      "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": "58d64ebf-52aa-4ec2-bc57-40a163a7fc15",
      "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": "e2014052-edca-49f4-af3a-869d38914e8c",
      "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": "d5d7a244-70d8-4aec-9af4-4c90718d586f",
      "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://graph.facebook.com/v22.0/SEU_PHONE_NUMBER_ID/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer SEU_ACCESS_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ messaging_product: 'whatsapp', to: $('Extrai dados').item.json.sessionId, type: 'text', text: { body: $('AI Agent').item.json.output } }) }}",
        "options": {}
      },
      "id": "5a018c6c-f6d3-443e-ba1a-f87502ecb0b6",
      "name": "Envia (Cloud)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2280,
        240
      ]
    },
    {
      "parameters": {},
      "id": "edea1e84-69ce-47cc-9f48-6aedd394dddd",
      "name": "Ignora (grupo/eco/duplicada)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        840,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f966e92a-cfa4-4c05-924c-76c6389e047b",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.query['hub.challenge'] }}",
              "rightValue": ""
            }
          ]
        },
        "options": {}
      },
      "id": "5a7d8b15-ed3e-4854-9242-6c3f0d91e72a",
      "name": "Verificacao Meta (GET)?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        120,
        600
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query['hub.challenge'] }}",
        "options": {}
      },
      "id": "3a36dce1-3e6f-4bac-99db-d2a1483ffb5e",
      "name": "Responde hub.challenge",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        340,
        600
      ],
      "webhookId": "473f7c3e-77c7-448b-9500-bec541e0b18e"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Verificacao Meta (GET)?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mensagem recebida (nao status)": {
      "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 (Cloud)",
            "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
          }
        ]
      ]
    },
    "Verificacao Meta (GET)?": {
      "main": [
        [
          {
            "node": "Responde hub.challenge",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mensagem recebida (nao status)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}