{
  "name": "BIG-AGENT-V2-EXPANDED",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "big-agent-webhook",
        "options": {
          "responseMode": "responseNode"
        }
      },
      "id": "webhook-zapi",
      "name": "Webhook Z-API",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        400
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'received' }) }}",
        "options": {}
      },
      "id": "respond-200",
      "name": "Responder 200",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        220,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "filter-recebida",
              "leftValue": "={{ $json.fromMe }}",
              "rightValue": false,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "filter-recebida",
      "name": "Filtrar Recebidas",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        440,
        400
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "telefone",
              "name": "telefone",
              "value": "={{ $json.phone.replace('@c.us', '').replace('@s.whatsapp.net', '') }}",
              "type": "string"
            },
            {
              "id": "mensagem",
              "name": "mensagem",
              "value": "={{ $json.text?.message || $json.body || '' }}",
              "type": "string"
            },
            {
              "id": "nome_push",
              "name": "nome_push",
              "value": "={{ $json.senderName || $json.pushName || '' }}",
              "type": "string"
            },
            {
              "id": "message_id",
              "name": "message_id",
              "value": "={{ $json.messageId || '' }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "parse-mensagem",
      "name": "Parsear Mensagem",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        660,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://frank-doberman-25459.upstash.io/get/session:{{ $json.telefone }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "redis-get-session",
      "name": "Redis: Buscar Sessao",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        400
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "select",
        "tableId": "ba_leads",
        "filterType": "string",
        "filterString": "=telefone=eq.{{ $('Parsear Mensagem').item.json.telefone }}",
        "options": {
          "limit": 1
        }
      },
      "id": "supabase-get-lead",
      "name": "Supabase: Buscar Lead",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1100,
        400
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "lead-existe",
              "leftValue": "={{ $json.length > 0 }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-lead-existe",
      "name": "Lead Existe?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1320,
        400
      ]
    },
    {
      "parameters": {
        "operation": "insert",
        "tableId": "ba_leads",
        "fieldsToSend": "defineBelow",
        "fieldValues": {
          "values": [
            {
              "fieldName": "telefone",
              "fieldValue": "={{ $('Parsear Mensagem').item.json.telefone }}"
            },
            {
              "fieldName": "nome",
              "fieldValue": "={{ $('Parsear Mensagem').item.json.nome_push }}"
            },
            {
              "fieldName": "estagio_atual",
              "fieldValue": "NOVO"
            }
          ]
        },
        "options": {}
      },
      "id": "supabase-criar-lead",
      "name": "Supabase: Criar Lead",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1540,
        560
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Mesclar dados do lead (existente ou rec\u00e9m-criado)\nconst parsear = $('Parsear Mensagem').item.json;\nconst redisResult = $('Redis: Buscar Sessao').item.json;\nlet leadData = {};\nlet sessao = null;\n\n// Tentar pegar lead existente\ntry {\n  const leadArr = $('Supabase: Buscar Lead').item.json;\n  if (Array.isArray(leadArr) && leadArr.length > 0) {\n    leadData = leadArr[0];\n  }\n} catch (e) {}\n\n// Tentar pegar lead rec\u00e9m-criado\ntry {\n  const novoLead = $('Supabase: Criar Lead').item.json;\n  if (novoLead && novoLead.id) {\n    leadData = novoLead;\n  }\n} catch (e) {}\n\n// Tentar pegar sess\u00e3o do Redis\ntry {\n  if (redisResult && redisResult.result) {\n    sessao = JSON.parse(redisResult.result);\n  }\n} catch (e) {\n  sessao = null;\n}\n\nreturn {\n  json: {\n    telefone: parsear.telefone,\n    mensagem: parsear.mensagem,\n    nome: parsear.nome_push || leadData.nome || 'Desconhecido',\n    message_id: parsear.message_id,\n    lead_id: leadData.id || null,\n    estagio_atual: leadData.estagio_atual || 'NOVO',\n    lead_score: leadData.lead_score || 0,\n    sessao: sessao,\n    historico: sessao?.historico || []\n  }\n};"
      },
      "id": "merge-dados",
      "name": "Mesclar Dados",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        400
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Classifique a intencao da mensagem.\n\nMensagem: {{ $json.mensagem }}\n\nIntencoes possiveis: SAUDACAO, INTERESSE, DUVIDA_PRODUTO, PRECO, OBJECAO_DINHEIRO, OBJECAO_TEMPO, OBJECAO_DUVIDA, OBJECAO_EXTERNA, COMPRAR, SUPORTE, RECLAMACAO, HUMANO, OFFTOPIC, DESPEDIDA\n\nResponda APENAS com JSON: {\"intencao\": \"TIPO\", \"confianca\": 0.95}",
        "options": {
          "systemMessage": "Voce e um classificador de intencoes. Responda APENAS com JSON valido, nada mais."
        }
      },
      "id": "classificar-intencao",
      "name": "Classificar Intencao",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        1980,
        400
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-3-haiku-20240307",
          "cachedResultName": "Claude 3 Haiku"
        },
        "options": {
          "maxTokensToSample": 100,
          "temperature": 0
        }
      },
      "id": "haiku-model",
      "name": "Haiku Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        1980,
        620
      ]
    },
    {
      "parameters": {
        "jsCode": "const input = $input.all()[0].json;\nconst intencaoRaw = input.output || '{}';\n\nlet intencao;\ntry {\n  const match = intencaoRaw.match(/\\{[\\s\\S]*\\}/);\n  intencao = match ? JSON.parse(match[0]) : { intencao: 'SAUDACAO', confianca: 0.5 };\n} catch (e) {\n  intencao = { intencao: 'SAUDACAO', confianca: 0.5 };\n}\n\n// Pegar dados mesclados\nlet dados = {};\ntry {\n  dados = $('Mesclar Dados').item.json;\n} catch (e) {\n  dados = {\n    telefone: 'unknown',\n    mensagem: '',\n    nome: 'Desconhecido',\n    estagio_atual: 'NOVO'\n  };\n}\n\nreturn {\n  json: {\n    ...dados,\n    intencao: intencao.intencao,\n    confianca: intencao.confianca,\n    precisa_escalar: ['HUMANO', 'RECLAMACAO'].includes(intencao.intencao)\n  }\n};"
      },
      "id": "processar-intencao",
      "name": "Processar Intencao",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2200,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "precisa-escalar",
              "leftValue": "={{ $json.precisa_escalar }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "if-escalar",
      "name": "Precisa Escalar?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2420,
        400
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "msg-escalacao",
              "name": "mensagem",
              "value": "Vou te passar pra alguem que pode te ajudar melhor com isso. Um momento! \ud83d\ude4f",
              "type": "string"
            },
            {
              "id": "telefone",
              "name": "telefone",
              "value": "={{ $json.telefone }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "msg-escalacao",
      "name": "Msg Escalacao",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2640,
        240
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.z-api.io/instances/3DEB4A36EC19A04479A132C54B267657/token/9F776951DB6B2E95F3E07510/send-text",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"phone\": \"{{ $json.telefone }}\",\n  \"message\": \"{{ $json.mensagem }}\"\n}",
        "options": {}
      },
      "id": "zapi-enviar-escalacao",
      "name": "Z-API: Enviar Escalacao",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2860,
        240
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=LEAD: {{ $json.nome || 'Desconhecido' }}\nTELEFONE: {{ $json.telefone }}\nESTAGIO: {{ $json.estagio_atual }}\nINTENCAO: {{ $json.intencao }}\n\nHISTORICO RECENTE:\n{{ $json.historico ? $json.historico.slice(-5).map(m => m.role + ': ' + m.content).join('\\n') : '(primeira mensagem)' }}\n\nMENSAGEM DO LEAD:\n{{ $json.mensagem }}\n\nResponda como Marcia. Separe multiplas mensagens com ---",
        "options": {
          "systemMessage": "Voce e Marcia, 52 anos, closer de vendas disfar\u00e7ada de amiga acolhedora.\n\nREGRAS ABSOLUTAS:\n1. NUNCA abrevie: sempre \"voce\" (nunca \"vc\"), \"tambem\" (nunca \"tb\")\n2. RISADA: apenas \"rs\". NUNCA \"kkkk\" ou \"haha\"\n3. EMOJI: maximo 1 por mensagem, apenas: \ud83d\ude0a \ud83d\ude4f \u2764\ufe0f \ud83c\udf89\n4. MENSAGENS CURTAS: max 3-4 linhas cada\n5. Separe mensagens multiplas com --- em linha sozinha\n\nSUA HISTORIA:\n- Ex-gerente Banco do Brasil, 20 anos, saiu no PDV\n- Casada 28 anos com Carlos, mae de Fernanda (27) e Lucas (24)\n- Avo do Theo (4 anos) - quarta e dia sagrado com ele\n\nOS 7 MANDAMENTOS:\n1. Nunca vendo. Ajudo a decidir.\n2. Quem fala mais, perde.\n3. Toda pergunta e uma seta.\n4. Validar antes de redirecionar.\n5. Venda na emocao, justifique na razao.\n6. Paciencia infinita, urgencia invisivel.\n7. Relacionamento primeiro, venda como consequencia.\n\nResponda APENAS com as mensagens da Marcia, separadas por ---"
        }
      },
      "id": "gerar-resposta",
      "name": "Gerar Resposta (Marcia)",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        2640,
        560
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-5-20250929",
          "cachedResultName": "Claude Sonnet 4.5"
        },
        "options": {
          "maxTokensToSample": 500,
          "temperature": 0.7
        }
      },
      "id": "sonnet-model",
      "name": "Sonnet Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        2640,
        780
      ]
    },
    {
      "parameters": {
        "jsCode": "const input = $input.all()[0].json;\nconst respostaRaw = input.output || '';\n\n// Pegar dados anteriores\nlet dados = {};\ntry {\n  dados = $('Processar Intencao').item.json;\n} catch (e) {\n  dados = { telefone: 'unknown' };\n}\n\nconst mensagens = respostaRaw\n  .split(/\\n---\\n|---/)\n  .map(m => m.trim())\n  .filter(m => m.length > 0);\n\nif (mensagens.length === 0) {\n  mensagens.push('Oi! Tudo bem com voce?');\n}\n\nconst output = mensagens.map((msg, idx) => {\n  // Delay baseado no tamanho + varia\u00e7\u00e3o aleat\u00f3ria\n  const baseDelay = msg.length * 50;\n  const randomDelay = Math.random() * 2000;\n  const delayMs = Math.min(Math.max(baseDelay + randomDelay, 1500), 8000);\n  \n  return {\n    json: {\n      mensagem: msg,\n      delay_ms: Math.round(delayMs),\n      indice: idx,\n      total: mensagens.length,\n      telefone: dados.telefone,\n      lead_id: dados.lead_id,\n      intencao: dados.intencao\n    }\n  };\n});\n\nreturn output;"
      },
      "id": "humanizar-resposta",
      "name": "Humanizar Resposta",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2860,
        560
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "id": "loop-mensagens",
      "name": "Loop Mensagens",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        3080,
        560
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.z-api.io/instances/3DEB4A36EC19A04479A132C54B267657/token/9F776951DB6B2E95F3E07510/typing",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"phone\": \"{{ $json.telefone }}\",\n  \"value\": true,\n  \"duration\": {{ Math.min($json.delay_ms, 5000) }}\n}",
        "options": {}
      },
      "id": "zapi-typing",
      "name": "Z-API: Typing",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3300,
        480
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "amount": "={{ $json.delay_ms }}",
        "unit": "milliseconds"
      },
      "id": "delay-humanizado",
      "name": "Delay Humanizado",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        3520,
        480
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.z-api.io/instances/3DEB4A36EC19A04479A132C54B267657/token/9F776951DB6B2E95F3E07510/send-text",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"phone\": \"{{ $json.telefone }}\",\n  \"message\": \"{{ $json.mensagem.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n') }}\"\n}",
        "options": {}
      },
      "id": "zapi-send-text",
      "name": "Z-API: Enviar Msg",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3740,
        480
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "insert",
        "tableId": "ba_mensagens",
        "fieldsToSend": "defineBelow",
        "fieldValues": {
          "values": [
            {
              "fieldName": "lead_id",
              "fieldValue": "={{ $json.lead_id }}"
            },
            {
              "fieldName": "direcao",
              "fieldValue": "out"
            },
            {
              "fieldName": "conteudo",
              "fieldValue": "={{ $json.mensagem }}"
            },
            {
              "fieldName": "intencao",
              "fieldValue": "={{ $json.intencao }}"
            }
          ]
        },
        "options": {}
      },
      "id": "supabase-salvar-msg-out",
      "name": "Supabase: Salvar Msg Enviada",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        3960,
        480
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://frank-doberman-25459.upstash.io/set/session:{{ $('Processar Intencao').item.json.telefone }}/{{ encodeURIComponent(JSON.stringify({ historico: [...($('Processar Intencao').item.json.historico || []), { role: 'user', content: $('Processar Intencao').item.json.mensagem }, { role: 'assistant', content: $json.mensagem }], ultimo_estado: $('Processar Intencao').item.json.estagio_atual, updated_at: Date.now() })) }}?EX=86400",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "redis-salvar-sessao",
      "name": "Redis: Salvar Sessao",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4180,
        560
      ],
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Webhook Z-API": {
      "main": [
        [
          {
            "node": "Responder 200",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Responder 200": {
      "main": [
        [
          {
            "node": "Filtrar Recebidas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtrar Recebidas": {
      "main": [
        [
          {
            "node": "Parsear Mensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Mensagem": {
      "main": [
        [
          {
            "node": "Redis: Buscar Sessao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redis: Buscar Sessao": {
      "main": [
        [
          {
            "node": "Supabase: Buscar Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Supabase: Buscar Lead": {
      "main": [
        [
          {
            "node": "Lead Existe?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Existe?": {
      "main": [
        [
          {
            "node": "Mesclar Dados",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Supabase: Criar Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Supabase: Criar Lead": {
      "main": [
        [
          {
            "node": "Mesclar Dados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mesclar Dados": {
      "main": [
        [
          {
            "node": "Classificar Intencao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Haiku Model": {
      "ai_languageModel": [
        [
          {
            "node": "Classificar Intencao",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Classificar Intencao": {
      "main": [
        [
          {
            "node": "Processar Intencao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Processar Intencao": {
      "main": [
        [
          {
            "node": "Precisa Escalar?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Precisa Escalar?": {
      "main": [
        [
          {
            "node": "Msg Escalacao",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gerar Resposta (Marcia)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Msg Escalacao": {
      "main": [
        [
          {
            "node": "Z-API: Enviar Escalacao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sonnet Model": {
      "ai_languageModel": [
        [
          {
            "node": "Gerar Resposta (Marcia)",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gerar Resposta (Marcia)": {
      "main": [
        [
          {
            "node": "Humanizar Resposta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Humanizar Resposta": {
      "main": [
        [
          {
            "node": "Loop Mensagens",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Mensagens": {
      "main": [
        [
          {
            "node": "Z-API: Typing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Redis: Salvar Sessao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Z-API: Typing": {
      "main": [
        [
          {
            "node": "Delay Humanizado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delay Humanizado": {
      "main": [
        [
          {
            "node": "Z-API: Enviar Msg",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Z-API: Enviar Msg": {
      "main": [
        [
          {
            "node": "Supabase: Salvar Msg Enviada",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Supabase: Salvar Msg Enviada": {
      "main": [
        [
          {
            "node": "Loop Mensagens",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}