{
  "name": "Brokeria-v15",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "waha",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -128,
        4832
      ],
      "id": "e13785cc-46d8-49db-ac71-e33de0b3441d",
      "name": "Webhook"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "78415b90-064b-46f3-8a36-8489bd14f43a",
              "name": "event",
              "value": "={{ $json.body.event }}",
              "type": "string"
            },
            {
              "id": "6d70d6a1-58d7-416a-a388-7b2aeabd4b85",
              "name": "session",
              "value": "={{ $json.body.session }}",
              "type": "string"
            },
            {
              "id": "ff0bd58d-efa1-4e49-9c9c-602aed25a290",
              "name": "payload_id",
              "value": "={{ $json.body.payload.id }}",
              "type": "string"
            },
            {
              "id": "0c990094-4206-417a-be86-008c8156acf8",
              "name": "from",
              "value": "={{ $json.body.payload.from }}",
              "type": "string"
            },
            {
              "id": "d33eb4cc-078e-40b7-9c9c-8fbba1e2aa76",
              "name": "to",
              "value": "={{ $json.body.payload.to }}",
              "type": "string"
            },
            {
              "id": "457f7c13-bf6f-4171-80bc-75620cfda604",
              "name": "source",
              "value": "={{ $json.body.payload.source }}",
              "type": "string"
            },
            {
              "id": "8ce79aa1-5408-48c9-8226-9ac6f875df12",
              "name": "body",
              "value": "={{ $json.body.payload.body }}",
              "type": "string"
            },
            {
              "id": "3fc1bd24-4960-40a3-9a52-5e1fa4365813",
              "name": "hasMedia",
              "value": "={{ $json.body.payload.hasMedia }}",
              "type": "boolean"
            },
            {
              "id": "7437da46-cfce-4e5b-909a-5daf06dfd2ad",
              "name": "type",
              "value": "={{ $json.body.payload._data.type }}",
              "type": "string"
            },
            {
              "id": "f8f215f3-ba00-485e-be98-354baa181f28",
              "name": "name",
              "value": "={{ $json.body.payload._data.notifyName }}",
              "type": "string"
            },
            {
              "id": "6508b08d-4b94-4352-8a94-c55ffd11cc91",
              "name": "fromMe",
              "value": "={{ $json.body.payload.fromMe }}",
              "type": "boolean"
            },
            {
              "id": "3ada40ac-45a0-440a-9e4b-44417caadf9c",
              "name": "to",
              "value": "={{ $json.body.payload.to }}",
              "type": "string"
            },
            {
              "id": "0096fa37-d92b-43ca-8c98-269cc5e1899f",
              "name": "id",
              "value": "={{ $json.body.id }}",
              "type": "string"
            },
            {
              "id": "30a509ba-e3aa-4e6a-b3ce-4f7d1fcbf46f",
              "name": "session_id",
              "value": "={{ $json.body.session + ' ' + $json.body.payload.from + ' chats' }}",
              "type": "string"
            },
            {
              "id": "72d18f99-83a5-4bfb-8621-6af03d231409",
              "name": "user_text",
              "value": "={{ $json.body.payload.body }}",
              "type": "string"
            },
            {
              "id": "d1a86623-555b-4571-b71d-b7dc69e0b763",
              "name": "media_url",
              "value": "={{ $json.body.payload.media.url || $json.body.payload.url || \"\" }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        48,
        4832
      ],
      "id": "198ce6ce-92d4-4de0-9572-a8ffe503279f",
      "name": "Dados"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Seen",
        "session": "default",
        "chatId": "={{ $('DefinirContextoAI').first().json.contexto.telefone + '@c.us' }}",
        "messageId": "",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2512,
        5872
      ],
      "id": "14425c66-4428-4564-8869-9ae910b16e66",
      "name": "Send Seen",
      "alwaysOutputData": true,
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Start Typing",
        "session": "={{ $('Padronizar Output').first().json.target_session || 'default' }}",
        "chatId": "={{ $('Padronizar Output').first().json.target_chat_id }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2656,
        5872
      ],
      "id": "69f232d6-706d-43d7-bf74-12befe7811c8",
      "name": "Start Typing",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        2800,
        5872
      ],
      "id": "993fa305-86a0-42d3-a595-e5847d31e844",
      "name": "Wait"
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Text",
        "session": "={{ $('Padronizar Output').first().json.target_session || 'default' }}",
        "chatId": "={{ $('Padronizar Output').first().json.target_chat_id }}",
        "reply_to": "=",
        "text": "={{ $json.text }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        3104,
        5872
      ],
      "id": "46bca101-83f0-4595-bb2c-d35a0047c3fa",
      "name": "Send a text message",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ ('http://waha:3000/api/' + $json.session + '/lids/' + encodeURIComponent(($json.from || '').trim())).trim() }}\n\n",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            },
            {
              "name": "X-Api-Key",
              "value": "GR15VC0m5ueLygSMQPM6In4A8qfnrLT31ECnIEmZvnfyovsGxjUSfaFcMi1YQ3E1VvR9WjdJijFKGllhKAhkQ6yNYzYstzwtlQODhb06lknx3j8JlfxA7UCbzKCe61nbb"
            }
          ]
        },
        "options": {}
      },
      "id": "70585f50-5dcd-4584-bd1e-6bbf615f50e3",
      "name": "Consultar WAHA Direto",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        208,
        4832
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "custom-field",
              "name": "PhoneNumber",
              "value": "={{ $json.pn ? $json.pn.split('@')[0] : undefined }}",
              "type": "string"
            },
            {
              "id": "835b86bc-37d1-4742-a421-3247982275a9",
              "name": "LidNumber",
              "value": "={{ $json.lid ? $json.lid.split('@')[0] : undefined }}",
              "type": "string"
            },
            {
              "id": "92fd4ba6-2d13-4ff9-b215-8895fd828fa2",
              "name": "isGroup",
              "value": "={{ ($json.pn || '').endsWith('@g.us') }}",
              "type": "boolean"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "ff32b552-e64c-444b-87a1-830c8323327a",
      "name": "Limpar Telefone",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        368,
        4832
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "/* BANCO: brokeria_db | SCHEMA: public */\nSELECT \n  c.id_cliente, \n  c.nome_completo, \n  c.cpf, \n  c.email, \n  c.celular,\n  c.telefone,\n  (\n    SELECT json_agg(a)\n    FROM public.apolices_brokeria a\n    WHERE a.id_cliente::text = c.id_cliente::text  -- \u00f0\u0178\u2019\u00a1 Blindagem: for\u00c3\u00a7a compara\u00c3\u00a7\u00c3\u00a3o entre textos\n  ) as apolices_detalhadas\nFROM public.clientes_brokeria c\nWHERE c.celular = '{{ $node[\"Limpar Telefone\"].json.PhoneNumber }}'\n   OR c.telefone = '{{ $node[\"Limpar Telefone\"].json.PhoneNumber }}'\nLIMIT 1;",
        "options": {
          "queryReplacement": "={{ $('Limpar Telefone').item.json.PhoneNumber }}"
        }
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1200,
        5392
      ],
      "id": "5ebda921-841a-4a67-a6a3-88e275fb4c29",
      "name": "Busca_Cliente",
      "alwaysOutputData": true,
      "executeOnce": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));\nawait wait(Math.floor(Math.random() * 400)); \n\nlet mensagens = [];\nconst dadosEntrada = $input.first().json; \nconst msgId = dadosEntrada.payload_id; \nconst execId = $execution.id; // \u00e2\u0153\u2026 Captura ID exclusivo da execu\u00c3\u00a7\u00c3\u00a3o\n\ntry {\n  const redisItem = $(\"Recuperar_Buffer\").first();\n  if (redisItem && redisItem.json) {\n    const conteudoRedis = redisItem.json.Redis_Check_Buffer || redisItem.json.value;\n    if (conteudoRedis && typeof conteudoRedis === 'string') {\n      mensagens = JSON.parse(conteudoRedis);\n    }\n  }\n} catch (e) {\n  mensagens = [];\n}\n\nif (!mensagens.some(m => m.id === msgId)) {\n    mensagens.push({\n        id: msgId,\n        exec_id: execId, // \u00e2\u0153\u2026 Salva quem foi o \u00c3\u00baltimo a escrever\n        texto: dadosEntrada.user_text || \"MIDIA_INPUT\", \n        tipo: dadosEntrada.mediaType || \"chat\"\n    });\n}\n\nreturn {\n    ...dadosEntrada, \n    texto_combinado: mensagens.map(m => m.texto).join(' \\n '),\n    lista_raw: JSON.stringify(mensagens),\n    quantidade: mensagens.length\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        16,
        5408
      ],
      "id": "473036e0-8c18-4343-a118-7994c613a59b",
      "name": "Agrupar_Texto"
    },
    {
      "parameters": {
        "operation": "set",
        "key": "=buffer:{{ $node[\"CheckOrigem\"].json.tecnico.session_id }}",
        "value": "={{ $json.lista_raw }}",
        "expire": true,
        "ttl": 10
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        160,
        5408
      ],
      "id": "a1a81ba9-fc73-4e3f-9483-1532cd0ee6fa",
      "name": "Atualizar_Buffer",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "amount": 3
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        320,
        5408
      ],
      "id": "535cad36-ad8e-4591-8a93-dafb7464386f",
      "name": "Espera_3_Segundos"
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "Redis_Check_Final",
        "key": "=buffer:{{ $node[\"CheckOrigem\"].json.tecnico.session_id }}",
        "options": {}
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        480,
        5408
      ],
      "id": "8eda9515-bc0b-4bc3-9e87-d0b5020efe9c",
      "name": "Check_Pos_Espera",
      "alwaysOutputData": true,
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 3
          },
          "conditions": [
            {
              "id": "768c0bd8-dd6a-4825-94af-95a9c9d03ad5",
              "leftValue": "={{ $node[\"Agrupar_Texto\"].json.payload_id + '_' + $execution.id }}",
              "rightValue": "={{ JSON.parse($json.Redis_Check_Final || \"[]\").slice(-1)[0].id + '_' + JSON.parse($json.Redis_Check_Final || \"[]\").slice(-1)[0].exec_id }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        656,
        5408
      ],
      "id": "cccb5f15-a217-43bc-81dc-c4969ce41dea",
      "name": "Filtro_Ultima_Execucao"
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "Redis_Check_Buffer",
        "key": "=buffer:{{ $('CheckOrigem').first().json.tecnico.session_id }}",
        "options": {}
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        -144,
        5408
      ],
      "id": "8162f2eb-9da6-48df-85f2-eac5bdd87af1",
      "name": "Recuperar_Buffer",
      "alwaysOutputData": true,
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "{{ $json.tecnico.isGroup }}",
                    "rightValue": "false",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "9d8b45b5-c151-4e99-bdaf-6306764ea594"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "27953cd9-b238-4be3-9db8-7f15b5635ba4",
                    "leftValue": "{{ $json.tecnico.source }}",
                    "rightValue": "api",
                    "operator": {
                      "type": "string",
                      "operation": "notContains"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "ffff129c-9a55-4c12-a18f-e84e087b7a88",
                    "leftValue": "{{ $json.tecnico.fromMe }}",
                    "rightValue": "false",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        1024,
        5376
      ],
      "id": "3abe8575-280d-44f8-81d7-7043ce1bbf19",
      "name": "SwitchOrigem"
    },
    {
      "parameters": {
        "jsCode": "// ==========================================================\n// 1. RECUPERA\u00c3\u2021\u00c3\u0192O DO N\u00c3\u0161MERO REAL (Do n\u00c3\u00b3 Consultar WAHA Direto)\n// ==========================================================\nlet phoneReal = \"\";\nlet nomeReal = \"Cliente\";\n\ntry {\n    // Pega o output da consulta que voc\u00c3\u00aa fez na API\n    const dadosAPI = $('Consultar WAHA Direto').first().json;\n    \n    // O WAHA retorna o n\u00c3\u00bamero real em 'pn', 'id.user' ou 'id' dependendo da vers\u00c3\u00a3o\n    const rawPhone = dadosAPI.pn || dadosAPI.id || \"\";\n    phoneReal = typeof rawPhone === 'string' ? rawPhone.split('@')[0].replace(/\\D/g, '') : \"\";\n    \n    // PRIORIDADE DE CAPTURA DO NOME (ordem de prefer\u00c3\u00aancia)\n    nomeReal = dadosAPI.pushname || dadosAPI.name || dadosAPI.notifyName || dadosAPI.verifiedName || \"Cliente\";\n} catch (error) {\n    phoneReal = $json.body.payload.from.split('@')[0];\n}\n\n// FALLBACK: Se ainda n\u00c3\u00a3o pegou o nome, tenta do payload direto\nif (nomeReal === \"Cliente\") {\n    try {\n        const payload = $json.body.payload || {};\n        const payloadData = payload._data || {};\n        nomeReal = payloadData.notifyName || payload.notifyName || payload.pushname || \"Cliente\";\n    } catch(e) {}\n}\n\n// ==========================================================\n// 2. RECUPERA\u00c3\u2021\u00c3\u0192O DOS DADOS BRUTOS (Do Webhook/Input)\n// ==========================================================\nconst inputData = $json; \nconst body = inputData.body || inputData;\nconst payload = body.payload || body || {};\n\nconst chatIdTecnico = payload.from || body.from;\nconst isGroup = String(chatIdTecnico).includes('@g.us');\n\nlet sessionId = body.session || 'default';\nif (!sessionId || sessionId === phoneReal) sessionId = 'default';\n\nlet userText = payload.body || \"\";\ntry {\n    const buffer = $('Agrupar_Texto').first().json;\n    if (buffer && buffer.texto_combinado) {\n        userText = buffer.texto_combinado;\n    }\n} catch(e) {}\n\n// ==========================================================\n// 3. MONTAGEM DO JSON FINAL\n// ==========================================================\nreturn {\n  json: {\n    \"tecnico\": {\n      \"session_id\": sessionId,\n      \"chat_id\": chatIdTecnico,\n      \"isGroup\": isGroup,\n      \"source\": body.source || \"api\",\n      \"fromMe\": payload.fromMe || false\n    },\n    \"cliente\": {\n      \"phoneNumber\": phoneReal,\n      \"nome_whatsapp\": nomeReal  // \u00e2\u0153\u2026 AGORA COM CAPTURA ROBUSTA\n    },\n    \"input_bruto\": {\n      \"user_text\": userText,\n      \"mediaType\": payload.type || \"chat\",\n      \"payload_id\": payload.id\n    }\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -320,
        5408
      ],
      "id": "e0d7b1ff-6001-4844-b8a5-324e757cbc05",
      "name": "CheckOrigem"
    },
    {
      "parameters": {
        "operation": "get",
        "propertyName": "sessaoExistente",
        "key": "=status_2fa:{{ $('Limpar Telefone').first().json.PhoneNumber }}",
        "options": {
          "dotNotation": true
        }
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        1376,
        5392
      ],
      "id": "49aa9477-d4ed-460d-8576-594140d1f4ba",
      "name": "Buscar_Sessao_Existente",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "// =========================================================\n// 1. RECUPERA\u00c3\u2021\u00c3\u0192O DE DADOS (BANCO + WHATSAPP)\n// =========================================================\nlet cliente = {};\ntry { \n    const busca = $(\"Busca_Cliente\").first();\n    if (busca && busca.json && busca.json.id_cliente) {\n        cliente = busca.json;\n    }\n} catch(e) {}\n\nlet dadosWhatsApp = {};\ntry {\n    dadosWhatsApp = $(\"CheckOrigem\").first().json.cliente || {};\n} catch(e) {}\n\nconst phoneNumber = dadosWhatsApp.phoneNumber || \"\";\nconst nomeWhatsApp = dadosWhatsApp.nome_whatsapp || \"Cliente\";\nconst isClienteCadastrado = !!(cliente && cliente.id_cliente);\n\nlet consolidado = {};\ntry { consolidado = $(\"ConsolidarMensagem\").first().json || {}; } catch(e) {}\n\nlet perguntaAgente = consolidado.mensagem_final;\n\n// BLINDAGEM MASTER\nif (consolidado.teve_erro_ia) {\n    const msgRecomendada = (consolidado.tipo_entrada === \"image\") \n        ? \"Houve um erro t\u00c3\u00a9cnico ao processar a imagem do cliente. Pe\u00c3\u00a7a educadamente para ele descrever o que deseja ou reenviar.\"\n        : \"Houve um erro t\u00c3\u00a9cnico ao transcrever o \u00c3\u00a1udio do cliente. Pe\u00c3\u00a7a para ele digitar ou enviar o \u00c3\u00a1udio novamente.\";\n    perguntaAgente = `[SISTEMA]: ${msgRecomendada}`;\n} \nelse if (!perguntaAgente) {\n    perguntaAgente = (consolidado.tipo_entrada === \"chat\") ? \"Ol\u00c3\u00a1\" : \"...\";\n}\n\nlet isValid = false;\ntry {\n    const nodeRedis = $(\"Buscar_Sessao_Existente\").first();\n    if (nodeRedis && nodeRedis.json && nodeRedis.json.sessaoExistente === \"VALIDADO\") {\n        isValid = true;\n    }\n} catch (e) { isValid = false; }\n\n// =========================================================\n// 2. PROCESSAMENTO DE AP\u00c3\u201cLICES (V13 INTEGRAL)\n// =========================================================\nlet apolicesRaw = (cliente.apolices_detalhadas || []).filter(ap => \n    ap && ap.status_apolice && String(ap.status_apolice).toUpperCase() === 'ATIVA'\n);\n\nconst apolicesContexto = apolicesRaw.map(ap => ({\n    seguradora: ap.seguradora,\n    tipo: ap.ramo,\n    status: ap.status_apolice,\n    apolice: isValid ? ap.numero_apolice : \"(Bloqueado)\",\n    vencimento: isValid ? ap.vigencia_fim : \"(Bloqueado)\",\n    placa: (ap.placa && isValid) ? ap.placa : (ap.placa ? \"***-****\" : \"N/A\"),\n    endereco: isValid ? (ap.endereco_apolice || \"N\u00c3\u00a3o informado\") : \"Endere\u00c3\u00a7o Oculto\",\n    cidade: isValid ? (ap.cidade_apolice || \"N\u00c3\u00a3o informado\") : \"Mascarado\",\n    uf: isValid ? (ap.uf_apolice || \"\") : \"\"\n}));\n\n// =========================================================\n// 3. CLASSIFICA\u00c3\u2021\u00c3\u0192O DE ROTA\n// =========================================================\nconst securityKeywords = /^(3|5|6|seguro|contratado|boleto|financeiro|sinistro|segunda|2a)|apolice|ap[o\u00c3\u00b3]lice|meus dados|minha ap/i;\nconst rota_num = securityKeywords.test(perguntaAgente || \"\") ? 1 : 0;\n\n// =========================================================\n// 4. RETORNO\n// =========================================================\nreturn [{\n    json: {\n        pergunta_cliente: perguntaAgente,\n        rota_num: rota_num,\n        contexto: {\n            nome: cliente.nome_completo || nomeWhatsApp,\n            cpf_real: cliente.cpf || \"\",\n            cpf_exibicao: (cliente.cpf) ? `***.***.***-${cliente.cpf.replace(/\\D/g, \"\").slice(-2)}` : \"N\u00c3\u00a3o informado\",\n            telefone: cliente.celular || phoneNumber,\n            email_cadastrado: cliente.email || \"\",\n            token_validado: isValid ? \"SIM\" : \"N\u00c3\u0192O\",\n            cadastrado: isClienteCadastrado,\n            id_cliente: cliente.id_cliente || null,\n            input_user: perguntaAgente,\n            resumo_apolices: apolicesContexto,\n            tipo_cliente: isClienteCadastrado ? \"CADASTRADO\" : \"NOVO\",\n            mensagem_sistema: isClienteCadastrado \n                ? \"Cliente encontrado no sistema.\" \n                : \"Cliente novo - n\u00c3\u00a3o encontrado no cadastro.\"\n        }\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2576,
        5440
      ],
      "id": "58a88635-946b-49f8-bf5a-9b55c4856b1f",
      "name": "DefinirContextoAI",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $('Dados').first().json.type || 'chat' }}",
                    "rightValue": "audio|ptt",
                    "operator": {
                      "type": "string",
                      "operation": "regex"
                    },
                    "id": "0dc49c03-4595-4987-ac0a-3fc9d3a6155c"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "6b2eacf3-4648-4f87-855c-274503889af2",
                    "leftValue": "={{ $('Dados').first().json.type || 'chat' }}",
                    "rightValue": "image",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "7102c9ec-2c9e-4121-856c-7e44d524cbb7",
                    "leftValue": "={{ $('Dados').first().json.type || 'chat' }}",
                    "rightValue": "chat",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        1536,
        5376
      ],
      "id": "85c9cec0-8417-42f6-ba1d-1efaae532c89",
      "name": "SwitchMidia"
    },
    {
      "parameters": {
        "url": "={{ ($node[\"Dados\"].json.media_url || $node[\"Webhook\"].json.body.payload.url || \"\").replace(/https?:\\/\\/[^\\/]+/, 'http://waha:3000') }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wahaApi",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1808,
        5024
      ],
      "id": "2ca4918e-b8d8-4a6d-babc-e814bf531394",
      "name": "DownloadMidia",
      "alwaysOutputData": false,
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "audio",
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.0-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.0-flash"
        },
        "inputType": "binary",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        1984,
        5024
      ],
      "id": "48ccbcde-0249-4506-8f6f-ac5b495fbbf5",
      "name": "IA_Processar_Audio",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput",
      "notes": "Em caso de erro, prossiga o chat."
    },
    {
      "parameters": {
        "url": "={{ ($node[\"Dados\"].json.media_url || $node[\"Webhook\"].json.body.payload.url || \"\").replace(/https?:\\/\\/[^\\/]+/, 'http://waha:3000') }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wahaApi",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        1808,
        5184
      ],
      "id": "0c0a5083-c7a7-4e21-aa7c-f3ecc5c7198c",
      "name": "ImageDownload",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "image",
        "operation": "analyze",
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.0-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.0-flash"
        },
        "text": "=Analise a imagem e d\u00c3\u00aa detalhes do que tem nela:\n  - Se for a imagem de um documento, procure fazer o reconhecimento atrav\u00c3\u00a9s do t\u00c3\u00adtulo ou qualquer coisa permita a correta identifica\u00c3\u00a7\u00c3\u00a3o\n  - Se for a imagem de um veiculo, procure identifica-lo (moto, carro ou caminh\u00c3\u00a3o), al\u00c3\u00a9m de modelo, cor e principalmente se identificado alguma batida etc. \n  - Se for qualquer outro tipo de imagem, analise de forma geral\n\nA pessoa que enviou essa imagem mencionou: {{ $node[\"CheckOrigem\"].json.input_bruto.user_text || \"N\u00c3\u00a3o mencionou nada\" }}",
        "inputType": "binary",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        1984,
        5184
      ],
      "id": "870d662c-796e-405f-bf9b-227885792ab6",
      "name": "IA_Processar_Imagem",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput",
      "notes": "Em caso de erro, prossiga o chat."
    },
    {
      "parameters": {
        "jsCode": "// 1. Pega dados de origem para saber o tipo real (chat ou m\u00c3\u00addia)\nlet origem = {};\ntry { origem = $(\"CheckOrigem\").first().json; } catch(e) {}\nconst tipoReal = origem.input_bruto?.mediaType || \"chat\";\nconst textoOriginal = origem.input_bruto?.user_text || \"\";\n\nlet transcricao = \"\";\nlet erroIA = false;\n\n// 2. S\u00c3\u201c BUSCA ERRO DE IA SE REALMENTE FOR M\u00c3\u008dDIA\nif (tipoReal === \"audio\" || tipoReal === \"ptt\") {\n    try {\n        const nodeAudio = $(\"IA_Processar_Audio\").first();\n        if (nodeAudio.json.error || !nodeAudio.json.text || nodeAudio.json.text.includes(\"Erro\")) erroIA = true;\n        else transcricao = nodeAudio.json.text;\n    } catch(e) { erroIA = true; }\n} \nelse if (tipoReal === \"image\") {\n    try {\n        const nodeImagem = $(\"IA_Processar_Imagem\").first();\n        if (nodeImagem.json.error || !nodeImagem.json.text) erroIA = true;\n        else transcricao = nodeImagem.json.text;\n    } catch(e) { erroIA = true; }\n}\n\n// 3. Resultado Final\nlet mensagemFinal = (tipoReal === \"chat\") ? textoOriginal : transcricao;\n\n// Limpeza de placeholders residuais\nif (mensagemFinal === \"MIDIA_INPUT\") mensagemFinal = \"\";\n\nreturn [{\n    json: {\n        mensagem_final: mensagemFinal.trim(),\n        tipo_entrada: tipoReal,\n        teve_erro_ia: erroIA && (tipoReal !== \"chat\"),\n        houve_erro_midia: false \n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2240,
        5424
      ],
      "id": "1a6c5c5c-39fe-41df-896f-99da0c8a6fb8",
      "name": "ConsolidarMensagem",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.houve_erro_midia }}",
                    "rightValue": "",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "id": "5280c04a-9876-4f53-a252-2e8fff6d4d73"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "63991c1f-d6e5-45f5-a188-beca30f15b0c",
                    "leftValue": "={{ $json.houve_erro_midia }}",
                    "rightValue": "If Boolean is False: Conecte ao n\u00c3\u00b3 DefinirContextoAI.",
                    "operator": {
                      "type": "boolean",
                      "operation": "false",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        2384,
        5424
      ],
      "id": "ff50d6d9-f861-4062-a737-6e0e1435ccd0",
      "name": "TratamentoErroMidia"
    },
    {
      "parameters": {
        "model": "google/gemini-2.0-flash",
        "options": {
          "maxTokens": 2048
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "typeVersion": 1,
      "position": [
        1216,
        6400
      ],
      "id": "601e9013-1ee8-4a16-99ec-58de67cc33dd",
      "name": "OpenRouter Chat Model1",
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ (() => { try { const tel = $('DefinirContextoAI').first().json.contexto.telefone; if (tel) return tel + '_v2'; } catch(e) {} try { return $('MontarContextoPortal').first().json.session_key; } catch(e) {} return 'FALLBACK_' + Date.now(); })() }}",
        "contextWindowLength": 6
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        1408,
        6400
      ],
      "id": "9b34d508-4c86-4809-a642-9053d09114de",
      "name": "PostgresChatMemory",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "NOME: Validador_Cliente_Brokeria\n\nQUANDO USAR:\n1. Quando um usu\u00c3\u00a1rio desconhecido (telefone n\u00c3\u00a3o cadastrado) afirma ser cliente e fornece o documento ou e-mail.\n2. Quando um usu\u00c3\u00a1rio j\u00c3\u00a1 identificado solicita acesso a dados sens\u00c3\u00adveis (ap\u00c3\u00b3lices, altera\u00c3\u00a7\u00c3\u00b5es cadastrais) e precisa revalidar a identidade.\n\nINPUT:\nO cliente deve fornecer o CPF (11 d\u00c3\u00adgitos), CNPJ (14 d\u00c3\u00adgitos) OU o E-mail cadastrado.\nExemplo JSON: { \"documento\": \"12345678900\" } ou { \"documento\": \"teste@email.com\" }\n\nRETORNO:\nRetorna os dados cadastrais completos do cliente. Retorna vazio se n\u00c3\u00a3o encontrar.",
        "operation": "executeQuery",
        "query": "SELECT * FROM public.clientes_brokeria\nWHERE cpf = '{{\n  (() => {\n    const val = $json.documento ? $json.documento.toString() : \"\";\n    if (val.includes(\"@\")) return \"EMAIL_QUERY_BYPASS\";\n    const doc = val.replace(/\\D/g, \"\");\n    if (doc.length !== 11 && doc.length !== 14) return \"000\";\n    return doc;\n  })()\n}}' OR email = '{{ $json.documento }}';",
        "options": {}
      },
      "type": "n8n-nodes-base.postgresTool",
      "typeVersion": 2.6,
      "position": [
        1600,
        6400
      ],
      "id": "5cb24bdd-0c72-4faa-b26e-68e08b6025f2",
      "name": "QueryPostgresClientes",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        624,
        4848
      ],
      "id": "a930ebb6-c18a-44c2-ad00-41a0ae411e6b",
      "name": "MergeDados"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "f8eff236-eaf4-4910-8750-745c585893f0",
              "name": "wa.provider",
              "value": "waha",
              "type": "string"
            },
            {
              "id": "952635f9-b937-4076-8b4c-87e5b4dfaf5e",
              "name": "wa.session",
              "value": "={{$json.body.session}}",
              "type": "string"
            },
            {
              "id": "01f5d87e-4994-4995-a882-477a14b85ab6",
              "name": "wa.messageId",
              "value": "={{$json.body.payload.id}}",
              "type": "string"
            },
            {
              "id": "d875c982-ad5d-4098-b28f-ea116c24b210",
              "name": "wa.chatId",
              "value": "={{ $json.body.payload.from }}",
              "type": "string"
            },
            {
              "id": "16637790-2905-445d-a3f5-a280a1d7726c",
              "name": "wa.text",
              "value": "={{$json.body.payload.body}}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        208,
        5024
      ],
      "id": "b344e8bf-7fbe-4e3c-92ad-3b375a2402fd",
      "name": "NormalizeInbound"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "f13f09b9-af26-4aa3-9761-edc7d76ff32e",
              "name": "wa.chatId",
              "value": "={{ $json.pn || $json.wa.chatId }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        800,
        4832
      ],
      "id": "6edeffd4-b8b8-46d4-89f2-7674b07c8caa",
      "name": "FinalizeChatId"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "final_text",
              "name": "response_text",
              "value": "={{ $json.mensagem_final || $json.mensagem || $json.output || \"Erro: N\u00c3\u00a3o foi poss\u00c3\u00advel recuperar a mensagem.\" }}",
              "type": "string"
            },
            {
              "id": "target_chat",
              "name": "target_chat_id",
              "value": "={{ $('DefinirContextoAI').first().json.contexto.telefone + '@c.us' }}",
              "type": "string"
            },
            {
              "id": "target_session",
              "name": "target_session",
              "value": "={{ $('CheckOrigem').first().json.tecnico.session_id }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2352,
        5872
      ],
      "id": "c93daf48-fa9d-4dd1-8ac2-a43727f66d34",
      "name": "Padronizar Output"
    },
    {
      "parameters": {
        "jsCode": "// Este n\u00c3\u00b3 apenas coleta o que chegar e passa adiante\nreturn $input.all();"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2144,
        5872
      ],
      "id": "ded3cf27-6768-4d33-b995-5c624a6f530e",
      "name": "FunilRespostas"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO public.brokeria_registros_brokeria (\n  telefone_whatsapp, \n  nome_cliente, \n  resumo_conversa, \n  assunto_principal,\n  subtipo_solicitacao,\n  tipo_seguro,\n  prioridade,\n  tipo_cliente,\n  status_atendimento, \n  data_atendimento,\n  canal,\n  qtde_mensagens\n)\nVALUES (\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.telefone }}',\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.nome }}',\n  E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"DefinirContextoAI\").first().json.contexto.nome }}' || E': ' || '{{ ($(\"DefinirContextoAI\").first().json.contexto.input_user || \"\").replace(/'/g, \"''\") }}' || E'\\n' ||\n  E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] BrokerIA: ' || '{{ ($json.text || $json.output || \"\").replace(/'/g, \"''\") }}' || E'\\n',\n  '{{ $json.tipo_solicitacao || \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\" }}',\n  '{{ $json.subtipo_solicitacao || \"D\u00c3\u00bavidas gerais\" }}',\n  '{{ $json.tipo_seguro || \"OUTROS\" }}',\n  '{{ $json.prioridade || \"M\u00c3\u00a9dia\" }}',\n  '{{ $json.tipo_cliente || \"N\u00c3\u00a3o cliente\" }}',\n  'PENDENTE',\n  CURRENT_DATE,\n  '{{ $(\"DefinirContextoAI\").first().json.contexto.origem || \"WHATSAPP\" }}',\n  1\n)\nON CONFLICT (telefone_whatsapp, data_atendimento) \nDO UPDATE SET \n  resumo_conversa = brokeria_registros_brokeria.resumo_conversa || \n         E'\\n' ||\n         E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || EXCLUDED.nome_cliente || E': ' || '{{ ($(\"DefinirContextoAI\").first().json.contexto.input_user || \"\").replace(/'/g, \"''\") }}' || E'\\n' ||\n         E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] BrokerIA: ' || '{{ ($json.text || $json.output || \"\").replace(/'/g, \"''\") }}' || E'\\n',\n  qtde_mensagens = COALESCE(brokeria_registros_brokeria.qtde_mensagens, 0) + 1,\n  assunto_principal = EXCLUDED.assunto_principal,\n  subtipo_solicitacao = EXCLUDED.subtipo_solicitacao,\n  prioridade = EXCLUDED.prioridade,\n  data_ultima_atualizacao = NOW();",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        2528,
        5648
      ],
      "id": "ba46fd4c-9c39-44c2-842f-7f4741308505",
      "name": "Registrar_Interacao",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "// 1. Coleta a mensagem de todas as fontes poss\u00c3\u00adveis\nlet mensagem = $json.response_text || $json.mensagem_final || $json.output || \"\";\n\n// 2. Se a mensagem ainda estiver vazia, tenta buscar diretamente nos n\u00c3\u00b3s de origem\nif (!mensagem || mensagem === \"\") {\n    try {\n        mensagem = $(\"LimparOutputValidacao\").first().json.mensagem_final;\n    } catch(e) {\n        try {\n            mensagem = $(\"BrokerIA_Master\").first().json.output;\n        } catch(e2) {}\n    }\n}\n\n// 3. Limpeza de logs t\u00c3\u00a9cnicos\nmensagem = mensagem.replace(/\\[Used tools:.*?\\]/gis, '');\nmensagem = mensagem.replace(/Tool:.*?(?=\\n|$)/gi, '');\nmensagem = mensagem.replace(/Input:.*?(?=\\n|$)/gi, '');\nmensagem = mensagem.replace(/Result:.*?(?=\\n|$)/gi, '');\nmensagem = mensagem.replace(/\\{.*?\"accepted\".*?\\}/gs, '');\nmensagem = mensagem.replace(/\\n{3,}/g, '\\n\\n').trim();\n\n// 4. \u00e2\u0153\u2026 CORRE\u00c3\u2021\u00c3\u0192O: Fallback adequado baseado no tipo de cliente (Agora via v9)\nif (!mensagem) {\n    try {\n        const contexto = $(\"DefinirContextoAI\").first().json.contexto;\n        const nome = contexto.nome || \"Cliente\";\n        const primeiroNome = nome.split(' ')[0];\n        const isClienteCadastrado = contexto.cadastrado; \n        \n        if (isClienteCadastrado) {\n            mensagem = `Ol\u00c3\u00a1 ${primeiroNome}! Como posso te ajudar hoje?`;\n        } else {\n            mensagem = `Ol\u00c3\u00a1 ${primeiroNome}! Seja bem-vindo \u00c3\u00a0 DWF Seguros! \u00f0\u0178\u02dc\u0160\\n\\nEstou aqui para te ajudar com:\\n\u00e2\u20ac\u00a2 Cota\u00c3\u00a7\u00c3\u00b5es de seguros\\n\u00e2\u20ac\u00a2 Informa\u00c3\u00a7\u00c3\u00b5es sobre nossos produtos\\n\u00e2\u20ac\u00a2 D\u00c3\u00bavidas sobre seguros em geral\\n\\nComo posso te ajudar?`;\n        }\n    } catch(e) {\n        mensagem = \"Ol\u00c3\u00a1! Seja bem-vindo \u00c3\u00a0 DWF Seguros! Como posso te ajudar?\";\n    }\n}\n\nreturn {\n  json: {\n    ...$json,\n    text: mensagem\n  }\n}"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2944,
        5872
      ],
      "id": "8b9e05b3-810c-4e71-8a1a-f5b425b38fe9",
      "name": "FiltrarResposta"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.pergunta_cliente }}\n\n",
        "options": {
          "systemMessage": "===================================================================\n\u00f0\u0178\u201c\u00b1 FORMATO DE RESPOSTA (ESTILO MENU/URA) - CR\u00c3\u008dTICO\n==================================================================\nPara melhorar a experi\u00c3\u00aancia do usu\u00c3\u00a1rio, sempre que o cliente solicitar algo que tenha categorias ou variantes, APRESENTE AS OP\u00c3\u2021\u00c3\u2022ES EM LISTA NUMERADA.\nO objetivo \u00c3\u00a9 permitir que o cliente responda de forma r\u00c3\u00a1pida e simples (apenas digitando o n\u00c3\u00bamero).\nEXEMPLO DE INTERA\u00c3\u2021\u00c3\u0192O OBRIGAT\u00c3\u201cRIA:\nCliente: \"Quero uma cota\u00c3\u00a7\u00c3\u00a3o\"\nVoc\u00c3\u00aa: \"\u00c3\u201ctimo! Para qual tipo de seguro voc\u00c3\u00aa deseja cota\u00c3\u00a7\u00c3\u00a3o?\n1. Autom\u00c3\u00b3vel \u00f0\u0178\u0161\u2014\n2. Residencial \u00f0\u0178\u008f\u00a0\n3. Vida \u00e2\u009d\u00a4\u00ef\u00b8\u008f\n4. Empresarial \u00f0\u0178\u008f\u00a2\n5. Outros Assist\u00c3\u00aancias\"\nPRIORIZE SEMPRE esse formato de \"URA Inteligente/Menu\" em vez de perguntas abertas.\n\n=================================================================\n\u00f0\u0178\u0152\u0090 PORTAL DO CLIENTE - ACESSO SEGURO A DADOS\n=================================================================\nQualquer solicita\u00c3\u00a7\u00c3\u00a3o abaixo DEVE ser respondida com redirecionamento ao portal:\n- Documentos (PDFs de ap\u00c3\u00b3lices, cartas verdes, 2\u00c2\u00aa via)\n- Dados detalhados al\u00c3\u00a9m do resumo dispon\u00c3\u00advel no contexto\n- Altera\u00c3\u00a7\u00c3\u00b5es cadastrais\n\n\u00e2\u0153\u2026 RESPOSTA PADR\u00c3\u0192O para esses casos:\n\"Para acessar seus dados e documentos com seguran\u00c3\u00a7a, acesse nosso portal:\n\u00f0\u0178\u201d\u2014 https://brokeria-api-brokeriaweb.cx0m9g.easypanel.host/login.html\n\nL\u00c3\u00a1 voc\u00c3\u00aa encontra todas as suas informa\u00c3\u00a7\u00c3\u00b5es e pode baixar seus documentos! \u00f0\u0178\u02dc\u0160\"\n\nEXEMPLOS que devem ir ao portal:\n- \"Me envie a 2\u00c2\u00aa via da ap\u00c3\u00b3lice\" \u00e2\u2020\u2019 portal\n- \"Qual o endere\u00c3\u00a7o da minha ap\u00c3\u00b3lice?\" \u00e2\u2020\u2019 portal\n- \"Quero alterar meu cadastro\" \u00e2\u2020\u2019 portal\n\nEXEMPLOS que N\u00c3\u0192O v\u00c3\u00a3o ao portal (responda com o contexto):\n- \"Qual o n\u00c3\u00bamero da minha ap\u00c3\u00b3lice?\" \u00e2\u2020\u2019 use resumo_apolices do contexto\n- \"Quando vence meu seguro?\" \u00e2\u2020\u2019 use resumo_apolices do contexto\n- \"Qual a placa do meu carro segurado?\" \u00e2\u2020\u2019 use resumo_apolices do contexto\n- Sauda\u00c3\u00a7\u00c3\u00b5es e perguntas gerais \u00e2\u2020\u2019 responda normalmente\n\n=================================================================\n\u00f0\u0178\u201c\u009d REGISTRO DE COTA\u00c3\u2021\u00c3\u2022ES - REGRA OBRIGAT\u00c3\u201cRIA\n=================================================================\nQuando o cliente solicitar uma cota\u00c3\u00a7\u00c3\u00a3o E voc\u00c3\u00aa j\u00c3\u00a1 tiver: Nome, Email e Tipo de seguro:\n1. Chame IMEDIATAMENTE a ferramenta 'EspecialistaRegistroCotacao'\n2. Passe: nome, email, tipo_seguro, mensagem\n3. AGUARDE a confirma\u00c3\u00a7\u00c3\u00a3o da tool\n4. S\u00c3\u00b3 DEPOIS confirme: \"\u00e2\u0153\u2026 Sua solicita\u00c3\u00a7\u00c3\u00a3o foi registrada! O corretor Washington entrar\u00c3\u00a1 em contato em breve.\"\n\nNUNCA confirme sem a tool retornar sucesso.\n\n-----------------------------------------------------------------\n\u00f0\u0178\u201d\u017d CONTEXTO DIN\u00c3\u201aMICO\n-----------------------------------------------------------------\n- Cliente: {{ $json.contexto.nome }}\n- CPF: {{ $json.contexto.cpf_exibicao }}\n- Telefone: {{ $json.contexto.telefone }}\n- Email Cadastrado: {{ $json.contexto.email_cadastrado }}\n\n\u00f0\u0178\u201c\u00b1 CEN\u00c3\u0081RIO A: CLIENTE CADASTRADO\n- Sa\u00c3\u00bade pelo PRIMEIRO NOME: \"Ol\u00c3\u00a1, {{ $json.contexto.nome }}!\"\n- Dados b\u00c3\u00a1sicos das ap\u00c3\u00b3lices dispon\u00c3\u00adveis no contexto abaixo\n- Para documentos/dados detalhados \u00e2\u2020\u2019 portal\n- N\u00c3\u0192O pe\u00c3\u00a7a CPF se j\u00c3\u00a1 estiver no contexto\n\n\u00f0\u0178\u201c\u00b1 CEN\u00c3\u0081RIO B: TELEFONE N\u00c3\u0192O CADASTRADO (novo contato)\n- Use o nome do WhatsApp: \"Ol\u00c3\u00a1, {{ $json.contexto.nome }}!\"\n- Se mencionar que \u00c3\u2030 cliente, pe\u00c3\u00a7a CPF \u00e2\u2020\u2019 use QueryPostgresClientes\n- Ap\u00c3\u00b3s encontrar: \"Perfeito! Localizei seu cadastro. Como posso ajudar?\"\n\n\u00f0\u0178\u201c\u00b1 CEN\u00c3\u0081RIO C: CLIENTE MENCIONA CPF ESPONTANEAMENTE\n- Use QueryPostgresClientes com { \"documento\": \"CPF_INFORMADO\" }\n- Se encontrar \u00e2\u2020\u2019 trate como CEN\u00c3\u0081RIO A\n\n\u00e2\u0161\u00a0\u00ef\u00b8\u008f SAUDA\u00c3\u2021\u00c3\u0192O: NUNCA diga \"Ol\u00c3\u00a1, N\u00c3\u00a3o Identificado!\" ou \"Ol\u00c3\u00a1, Cliente!\"\n\n\u00f0\u0178\u201c\u0160 RESUMO DE AP\u00c3\u201cLICES (dados b\u00c3\u00a1sicos dispon\u00c3\u00adveis):\n{{ JSON.stringify($json.contexto.resumo_apolices) }}\n\n=================================================================\n\u00f0\u0178\u201c\u2039 INFORMA\u00c3\u2021\u00c3\u2022ES INSTITUCIONAIS\n=================================================================\nRespons\u00c3\u00a1vel: Washington William de Oliveira \u00e2\u20ac\u201c Susep: 10.2028529.9\nEmail: contato@dwfseguros.com.br\nWebsite: https://www.dwfseguros.com.br\nTIPOS DE SEGUROS: Autom\u00c3\u00b3vel, Residencial, Vida, Sa\u00c3\u00bade, Previd\u00c3\u00aancia, Frota, Resp. Civil, Transportes, Garantia, etc.\n\n=================================================================\n\u00f0\u0178\u0161\u00ab LIMITES E LGPD\n=================================================================\n- COTA\u00c3\u2021\u00c3\u2022ES: NUNCA forne\u00c3\u00a7a valores de pr\u00c3\u00aamio. Diga: \"A cota\u00c3\u00a7\u00c3\u00a3o oficial ser\u00c3\u00a1 feita pelo corretor Washington\".\n- CPF/CNPJ: SEMPRE mascarado. Ex: ***.***.***-22\n- Para dados al\u00c3\u00a9m do contexto \u00e2\u2020\u2019 redirecione ao portal\n- Seja formal, consultivo e simp\u00c3\u00a1tico. Saude sempre pelo primeiro nome.\n- NUNCA invente informa\u00c3\u00a7\u00c3\u00b5es.",
          "maxIterations": 10
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        1424,
        5872
      ],
      "id": "6e2a1dbc-1160-4c29-a70a-a070ba8af73b",
      "name": "BrokerIA_Master",
      "executeOnce": false,
      "alwaysOutputData": false,
      "notesInFlow": false
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.contexto.tipo_cliente }}",
                    "rightValue": "=NOVO",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "75010c00-aec1-42d3-ae87-3d67526f7c3b"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "d4159ee7-e43a-477d-90f3-a5e7ac29d9d5",
                    "leftValue": "={{ $json.contexto.tipo_cliente }}",
                    "rightValue": "=CADASTRADO",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        3936,
        5424
      ],
      "id": "98738341-404f-4110-b56f-f3c3dcff6286",
      "name": "Check_Cliente_Novo"
    },
    {
      "parameters": {
        "jsCode": "// RECUPERA DADOS\nconst contexto = $json.contexto || {};\nconst pergunta = $json.pergunta_cliente || \"\";\nconst perguntaLower = pergunta.toLowerCase();\n\n// ==========================================\n// 1. RAMO DO SEGURO (Mapeamento Inteligente)\n// ==========================================\nlet ramoSeguro = \"OUTROS\";\nif (perguntaLower.match(/auto|carro|veic|moto|placa/)) ramoSeguro = \"AUTOMOVEL\";\nelse if (perguntaLower.match(/casa|resid|apart|lar|home/)) ramoSeguro = \"RESIDENCIAL\";\nelse if (perguntaLower.match(/vida|falec|morte|funeral/)) ramoSeguro = \"VIDA\";\nelse if (perguntaLower.match(/saude|m\u00c3\u00a9dic|plano|hospit/)) ramoSeguro = \"SAUDE\";\nelse if (perguntaLower.match(/empresa|pj|comercial/)) ramoSeguro = \"EMPRESARIAL\";\n\n// ==========================================\n// 2. N\u00c3\u008dVEL 1 E N\u00c3\u008dVEL 2 (Classifica\u00c3\u00a7\u00c3\u00a3o)\n// ==========================================\nlet nivel1 = \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\";\nlet nivel2 = \"D\u00c3\u00bavidas gerais sobre seguros\";\nlet prioridade = \"M\u00c3\u00a9dia\";\n\n// L\u00c3\u00b3gica de Classifica\u00c3\u00a7\u00c3\u00a3o Hier\u00c3\u00a1rquica\nif (perguntaLower.match(/cota\u00c3\u00a7\u00c3\u00a3o|cotacao|quanto custa|valor|pre\u00c3\u00a7o|contratar/)) {\n    nivel1 = \"Vendas e Cota\u00c3\u00a7\u00c3\u00b5es\";\n    nivel2 = \"Cota\u00c3\u00a7\u00c3\u00a3o de seguro novo\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/sinistro|bati|acidente|roubo|furto|colis\u00c3\u00a3o/)) {\n    nivel1 = \"Sinistros\";\n    nivel2 = \"Aviso de sinistro\";\n    prioridade = \"Cr\u00c3\u00adtica\";\n} else if (perguntaLower.match(/boleto|pagar|parcela|paguei|segunda via|2 via/)) {\n    nivel1 = \"Financeiro\";\n    nivel2 = \"Segunda via de boleto\";\n} else if (perguntaLower.match(/renovar|renova\u00c3\u00a7\u00c3\u00a3o|vencimento|venceu/)) {\n    nivel1 = \"Renova\u00c3\u00a7\u00c3\u00a3o\";\n    nivel2 = \"Renova\u00c3\u00a7\u00c3\u00a3o autom\u00c3\u00a1tica\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/cancelar|cancelamento|desistir/)) {\n    nivel1 = \"Cancelamento\";\n    nivel2 = \"Cancelamento a pedido do cliente\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/apolice|ap\u00c3\u00b3lice|documento|certificado|carta/)) {\n    nivel1 = \"Documentos\";\n    nivel2 = \"Segunda via de ap\u00c3\u00b3lice\";\n} else if (perguntaLower.match(/mudei|endere\u00c3\u00a7o|troquei|dados|alterar/)) {\n    nivel1 = \"Altera\u00c3\u00a7\u00c3\u00b5es de Ap\u00c3\u00b3lice (Endossos)\";\n    nivel2 = \"Atualiza\u00c3\u00a7\u00c3\u00a3o de dados cadastrais\";\n}\n\n// ==========================================\n// 3. RETORNO FORMATADO PARA O POSTGRES\n// ==========================================\nreturn {\n    json: {\n        telefone: (contexto.telefone || \"\").replace(/\\D/g, ''),\n        nome_whatsapp: (contexto.nome || \"Cliente\"),\n        mensagem_inicial: pergunta,\n        \n        // Padroniza\u00c3\u00a7\u00c3\u00a3o solicitada\n        tipo_solicitacao: nivel1,          // N\u00c3\u00advel 1\n        subtipo_solicitacao: nivel2,       // N\u00c3\u00advel 2\n        tipo_seguro: ramoSeguro,           // Ramo\n        prioridade: prioridade,            // Prioridade\n        tipo_cliente: contexto.cadastrado ? \"Cliente existente\" : \"N\u00c3\u00a3o cliente\",\n        \n        status_atendimento: \"PENDENTE\",\n        origem: \"WHATSAPP\",\n        data_contato: new Date()\n    }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4064,
        5264
      ],
      "id": "bf04d374-7095-4254-8afe-987824f6a1c8",
      "name": "Preparar_Registro_Cliente"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT \n    id_atendimento,\n    telefone_whatsapp,\n    nome_cliente,\n    resumo_conversa,\n    assunto_principal,\n    status_atendimento,\n    qtde_mensagens,\n    data_atendimento\nFROM public.brokeria_registros_brokeria\nWHERE telefone_whatsapp = '{{ $json.telefone }}'\n  AND data_atendimento > NOW() - INTERVAL '24 hours'\nORDER BY data_atendimento DESC\nLIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        4272,
        5264
      ],
      "id": "f61b9514-92e4-466b-bd88-1d16448d70fa",
      "name": "Verificar_Registro_Existente",
      "alwaysOutputData": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.id_atendimento ? String($json.id_atendimento) : '' }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "empty",
                      "singleValue": true
                    },
                    "id": "f21a439a-8d76-455e-8135-20ce8961a9cd"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "32739ffd-b920-42b7-91e3-cc77369defd7",
                    "leftValue": "={{ $json.id_atendimento ? String($json.id_atendimento) : '' }}",
                    "rightValue": "",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        4480,
        5264
      ],
      "id": "4eaa15af-47c8-43b5-bbb5-f03dc3700e6c",
      "name": "Switch_Registro_Existe"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO public.brokeria_registros_brokeria (\n    telefone_whatsapp,\n    nome_cliente,\n    resumo_conversa,    -- Ajustado para o padr\u00c3\u00a3o do Dashboard\n    assunto_principal,\n    canal,\n    status_atendimento,\n    qtde_mensagens,\n    recebeu_arquivos,\n    tipos_documentos,\n    etapa_funil,\n    data_atendimento,\n    hora_inicio\n) VALUES (\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.telefone }}',\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}',\n    -- Inicia o log j\u00c3\u00a1 formatado\n    E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}' || E': ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.mensagem_inicial.replace(/'/g, \"''\") }}' || E'\\n',\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.tipo_solicitacao }}',\n    'WHATSAPP',\n    'PENDENTE',\n    1,\n    {{ $(\"Preparar_Registro_Cliente\").first().json.recebeu_arquivos || false }},\n    '{{ $(\"Preparar_Registro_Cliente\").first().json.tipos_documentos || \"\" }}',\n    'PRIMEIRO_CONTATO',\n    NOW(),\n    NOW()\n)\nRETURNING *;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        4688,
        5072
      ],
      "id": "69249b3e-3a8c-4c1e-a2aa-3952b45d3c05",
      "name": "Inserir_Novo_Registro",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE public.brokeria_registros_brokeria\nSET \n    -- Adiciona a nova mensagem do cliente mantendo o formato [HH:MM]\n    resumo_conversa = resumo_conversa || \n        E'\\n' ||\n        E'[' || TO_CHAR(NOW() AT TIME ZONE 'UTC' AT TIME ZONE 'America/Sao_Paulo', 'HH24:MI, DD/MM/YYYY') || E'] ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.nome_whatsapp }}' || E': ' || '{{ $(\"Preparar_Registro_Cliente\").first().json.mensagem_inicial.replace(/'/g, \"''\") }}' || E'\\n',\n    assunto_principal = '{{ $(\"Preparar_Registro_Cliente\").first().json.tipo_solicitacao }}',\n    qtde_mensagens = COALESCE(qtde_mensagens, 0) + 1,\n    data_ultima_atualizacao = NOW()\nWHERE id_atendimento = {{ $json.id_atendimento }}\nRETURNING *;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        4704,
        5280
      ],
      "id": "981333ac-0559-4767-931c-855bd98594d5",
      "name": "Atualizar_Registro_Existente",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "numberInputs": 3
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        4960,
        5392
      ],
      "id": "8edf33f8-2158-4a80-9612-51f761ba20e4",
      "name": "Merge_Registro"
    },
    {
      "parameters": {
        "description": "Use esta ferramenta OBRIGATORIAMENTE quando o cliente solicitar uma cota\u00c3\u00a7\u00c3\u00a3o de seguro E fornecer nome e-mail e tipo de seguro. Esta tool registra a solicita\u00c3\u00a7\u00c3\u00a3o no sistema para que o corretor Washington entre em contato. IMPORTANTE: S\u00c3\u00b3 chame esta tool APOS coletar nome e-mail e tipo de seguro do cliente.",
        "workflowId": {
          "__rl": true,
          "value": "jzIUf4Qlnf2bunJx599mp",
          "mode": "list",
          "cachedResultUrl": "/workflow/jzIUf4Qlnf2bunJx599mp",
          "cachedResultName": "EspecialistaRegistroCotacao"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "telefone": "={{ $('NormalizarEntrada').first().json.contexto.telefone }}",
            "nome": "={{ $json.nome || $('NormalizarEntrada').first().json.contexto.nome }}",
            "email": "={{ $json.email }}",
            "tipo_seguro": "={{ $json.tipo_seguro }}",
            "mensagem": "={{ $('NormalizarEntrada').first().json.pergunta_cliente || $json.mensagem || 'Solicita\u00c3\u00a7\u00c3\u00a3o de cota\u00c3\u00a7\u00c3\u00a3o via WhatsApp' }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "telefone",
              "displayName": "telefone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "nome",
              "displayName": "nome",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "email",
              "displayName": "email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "tipo_seguro",
              "displayName": "tipo_seguro",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "mensagem",
              "displayName": "mensagem",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "canBeUsedToMatch": true,
              "type": "string",
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.2,
      "position": [
        1792,
        6400
      ],
      "id": "38875765-a0cc-4f13-a0a0-9203dee0898b",
      "name": "EspecialistaRegistroCotacao"
    },
    {
      "parameters": {
        "jsCode": "// RECUPERA DADOS (Tenta buscar de v\u00c3\u00a1rias fontes comuns no seu fluxo)\nconst contexto = $json.contexto || {};\nconst inputUser = contexto.input_user || $json.pergunta_cliente || \"\";\nconst perguntaLower = inputUser.toLowerCase();\n\n// ==========================================\n// 1. RAMO DO SEGURO (Mapeamento Inteligente)\n// ==========================================\n// Para clientes existentes, se j\u00c3\u00a1 tivermos o ramo no contexto, usamos ele.\nlet ramoSeguro = contexto.ramo_seguro || \"OUTROS\";\n\nif (ramoSeguro === \"OUTROS\") {\n    if (perguntaLower.match(/auto|carro|veic|moto|placa/)) ramoSeguro = \"AUTOMOVEL\";\n    else if (perguntaLower.match(/casa|resid|apart|lar|home/)) ramoSeguro = \"RESIDENCIAL\";\n    else if (perguntaLower.match(/vida|falec|morte|funeral/)) ramoSeguro = \"VIDA\";\n    else if (perguntaLower.match(/saude|m\u00c3\u00a9dic|plano|hospit/)) ramoSeguro = \"SAUDE\";\n    else if (perguntaLower.match(/empresa|pj|comercial/)) ramoSeguro = \"EMPRESARIAL\";\n}\n\n// ==========================================\n// 2. N\u00c3\u008dVEL 1 E N\u00c3\u008dVEL 2 (Classifica\u00c3\u00a7\u00c3\u00a3o de Chamado)\n// ==========================================\nlet nivel1 = \"Informa\u00c3\u00a7\u00c3\u00b5es Gerais\";\nlet nivel2 = \"D\u00c3\u00bavidas gerais sobre seguros\";\nlet prioridade = \"M\u00c3\u00a9dia\";\n\n// L\u00c3\u00b3gica para Clientes Existentes (Foco em P\u00c3\u00b3s-Venda/Servi\u00c3\u00a7o)\nif (perguntaLower.match(/sinistro|bati|acidente|roubo|furto|colis\u00c3\u00a3o/)) {\n    nivel1 = \"Sinistros\";\n    nivel2 = \"Aviso de sinistro\";\n    prioridade = \"Cr\u00c3\u00adtica\";\n} else if (perguntaLower.match(/boleto|pagar|parcela|paguei|segunda via|2 via/)) {\n    nivel1 = \"Financeiro\";\n    nivel2 = \"Segunda via de boleto\";\n} else if (perguntaLower.match(/renovar|renova\u00c3\u00a7\u00c3\u00a3o|vencimento|venceu/)) {\n    nivel1 = \"Renova\u00c3\u00a7\u00c3\u00a3o\";\n    nivel2 = \"Revis\u00c3\u00a3o de valor\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/apolice|ap\u00c3\u00b3lice|documento|certificado|carta/)) {\n    nivel1 = \"Documentos\";\n    nivel2 = \"Segunda via de ap\u00c3\u00b3lice\";\n} else if (perguntaLower.match(/mudei|endere\u00c3\u00a7o|troquei|dados|alterar/)) {\n    nivel1 = \"Altera\u00c3\u00a7\u00c3\u00b5es de Ap\u00c3\u00b3lice (Endossos)\";\n    nivel2 = \"Atualiza\u00c3\u00a7\u00c3\u00a3o de dados cadastrais\";\n} else if (perguntaLower.match(/cancelar|cancelamento|desistir/)) {\n    nivel1 = \"Cancelamento\";\n    nivel2 = \"Cancelamento a pedido do cliente\";\n    prioridade = \"Alta\";\n} else if (perguntaLower.match(/reclama\u00c3\u00a7\u00c3\u00a3o|ruim|errado|elogio|queixa/)) {\n    nivel1 = \"P\u00c3\u00b3s-venda e Relacionamento\";\n    nivel2 = \"Reclama\u00c3\u00a7\u00c3\u00a3o geral\";\n} else if (perguntaLower.match(/cota\u00c3\u00a7\u00c3\u00a3o|cotacao|seguro novo|outro carro/)) {\n    nivel1 = \"Vendas e Cota\u00c3\u00a7\u00c3\u00b5es\";\n    nivel2 = \"Cota\u00c3\u00a7\u00c3\u00a3o de seguro novo\";\n    prioridade = \"Alta\";\n}\n\n// ==========================================\n// 3. RETORNO PARA O REGISTRO (Com \"Spread\" para manter dados da IA)\n// ==========================================\nreturn {\n    json: {\n        ...$json, // \u00f0\u0178\u2018\u02c6 ISSO \u00c3\u2030 VITAL: Mant\u00c3\u00a9m a resposta da IA (output) vinda do FunilRespostas\n        \n        // Seus novos campos padronizados\n        tipo_solicitacao: nivel1,\n        subtipo_solicitacao: nivel2,\n        tipo_seguro: ramoSeguro,\n        prioridade: prioridade,\n        tipo_cliente: \"Cliente existente\",\n        \n        // Dados do Cliente\n        telefone: (contexto.telefone || \"\").replace(/\\D/g, ''),\n        nome_whatsapp: (contexto.nome || \"Cliente\")\n    }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2336,
        5648
      ],
      "id": "e3e2ca82-eede-4a70-b7d4-6eb17f307473",
      "name": "Preparar_Registro_Cliente_Existente"
    },
    {
      "parameters": {
        "jsCode": "// Captura o input do n\u00c3\u00b3 anterior\nconst input = $input.first().json;\n\n// Se o webhook agora envia apenas o body, o 'input' j\u00c3\u00a1 \u00c3\u00a9 o conte\u00c3\u00bado direto\nconst data = input;\n\nlet perguntaFinal = data.pergunta_cliente || data.pergunta || \"Ol\u00c3\u00a1\";\nlet contextoFinal = data.contexto || {};\n\n// Identifica\u00c3\u00a7\u00c3\u00a3o robusta: Se tiver 'action' ou 'token' e n\u00c3\u00a3o tiver 'contexto' estruturado, tratamos como Portal Web Inicial\nconst isPortalWebInicial = (data.action || data.token) && (!data.contexto || Object.keys(data.contexto).length === 0);\n\nif (isPortalWebInicial) {\n    const rawIdentifier = data.cpf || data.identifier || data.cpf_cnpj || \"\";\n    const cpfLimpo = rawIdentifier.toString().replace(/\\D/g, '');\n\n    contextoFinal = {\n        nome: data.client_name || data.nome || \"Visitante Web\",\n        email_cadastrado: data.target || data.email || null,\n        cpf_real: cpfLimpo || null, \n        origem: \"PORTAL_WEB\",\n        token_portal: data.token || null, \n        action: data.action || null,\n        tipo_cliente: \"CADASTRADO\",\n        token_validado: \"N\u00c3\u0192O\"\n    };\n\n    if (data.action === \"SEND_2FA_TOKEN\") {\n        if (!contextoFinal.cpf_real) {\n            perguntaFinal = `[PROTOCOLO DE SEGURAN\u00c3\u2021A]: O cliente ${contextoFinal.nome} deseja receber seu c\u00c3\u00b3digo no e-mail ${contextoFinal.email_cadastrado}.\\n\\n### ATEN\u00c3\u2021\u00c3\u0192O AGENTE ###\\nO CPF n\u00c3\u00a3o foi enviado pelo portal. Voc\u00c3\u00aa \u00c3\u00a9 OBRIGADO a seguir estes passos:\\n1. Use a tool 'Validador_Cliente_Brokeria' passando o e-mail '${contextoFinal.email_cadastrado}' no campo 'documento'.\\n2. Identifique o CPF retornado pelo banco.\\n3. Agora sim, chame 'AgentEnviaToken' informando o E-mail, o CPF localizado e o Token: ${contextoFinal.token_portal}.`;\n        } else {\n            perguntaFinal = `[PROTOCOLO DE SEGURAN\u00c3\u2021A]: O cliente ${contextoFinal.nome} deseja receber seu c\u00c3\u00b3digo de acesso.\\n- E-mail: ${contextoFinal.email_cadastrado}\\n- CPF: ${contextoFinal.cpf_real}\\n- C\u00c3\u00b3digo (Token): ${contextoFinal.token_portal}\\n\\nChame a ferramenta AgentEnviaToken IMEDIATAMENTE.`;\n        }\n    } else {\n        contextoFinal.token_validado = \"SIM\";\n    }\n} else {\n    // Fluxo normal (WhatsApp ou Contexto j\u00c3\u00a1 pronto)\n    contextoFinal.token_validado = contextoFinal.token_validado || \"N\u00c3\u0192O\";\n}\n\nlet telefoneDb = contextoFinal.telefone || data.telefone || \"VISITANTE_WEB\";\nif (contextoFinal.cpf_real) {\n    telefoneDb = \"WEB_\" + contextoFinal.cpf_real;\n}\n\ncontextoFinal.tipo_cliente = contextoFinal.tipo_cliente || \"CADASTRADO\";\n// CERTO (Ajustado)\n// Se n\u00c3\u00a3o for Portal Web Inicial, e n\u00c3\u00a3o tiver origem, assume WHATSAPP\ncontextoFinal.origem = contextoFinal.origem || \"WHATSAPP\"; \nreturn [{\n    json: {\n        pergunta_cliente: perguntaFinal,\n        contexto: contextoFinal,\n        telefone: telefoneDb,\n        nome_whatsapp: contextoFinal.nome || \"Visitante Web\",\n        origem: contextoFinal.origem // Preserve o valor definido acima\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3760,
        5424
      ],
      "id": "feff5dc1-d7ab-46fc-8eef-616eabfa2fa5",
      "name": "NormalizarEntrada"
    },
    {
      "parameters": {
        "jsCode": "// =========================================================\n// 1. CAPTURA DE DADOS (Diferencia Portal Web de WhatsApp)\n// =========================================================\nconst inputData = $input.first().json;\nlet contexto = inputData.contexto || {};\nlet perguntaCliente = inputData.pergunta_cliente || \"\";\n\n// Se a pergunta estiver vazia, significa que veio do fluxo do WhatsApp\nif (!perguntaCliente) {\n    try {\n        // Busca o contexto gerado internamente pelo n\u00c3\u00b3 anterior do seu fluxo\n        const nodeContexto = $(\"DefinirContextoAI\").first().json;\n        contexto = nodeContexto.contexto || {};\n        perguntaCliente = nodeContexto.pergunta_cliente || \"\";\n    } catch(e) {\n        console.log(\"Aviso: N\u00c3\u00a3o foi poss\u00c3\u00advel recuperar contexto via n\u00c3\u00b3 DefinirContextoAI\");\n    }\n}\n\n// =========================================================\n// 2. RECUPERA\u00c3\u2021\u00c3\u0192O DE LOGS (Dados do Registro no Postgres)\n// =========================================================\n// Tenta pegar o hist\u00c3\u00b3rico de conversa caso j\u00c3\u00a1 exista um atendimento aberto\nlet dadosRegistro = {};\ntry {\n    const mergeNode = $(\"Merge_Registro\").first().json;\n    dadosRegistro = mergeNode || {};\n} catch(e) {\n    console.log(\"Aviso: Dados do Merge_Registro n\u00c3\u00a3o encontrados\");\n}\n\n// =========================================================\n// 3. FALLBACK DE PERGUNTA\n// =========================================================\n// Se ainda assim a pergunta estiver vazia, mas houver hist\u00c3\u00b3rico no banco, tenta pegar a \u00c3\u00baltima linha\nif (!perguntaCliente && dadosRegistro.resumo_conversa) {\n    const mensagens = dadosRegistro.resumo_conversa.split('--- Nova mensagem em');\n    const ultimaMensagem = mensagens[mensagens.length - 1];\n    perguntaCliente = ultimaMensagem\n        .replace(/---/g, '')\n        .replace(/\\d{4}-\\d{2}-\\d{2}.*?---/g, '')\n        .trim();\n}\n\n// Fallback final de seguran\u00c3\u00a7a (Garanti que a IA nunca receba vazio)\nif (!perguntaCliente) {\n    perguntaCliente = \"Ol\u00c3\u00a1\";\n}\n\n// =========================================================\n// 4. RETORNO FINAL (O que o seu \"BrokerIA_Master\" vai ler)\n// =========================================================\nreturn {\n    json: {\n        pergunta_cliente: perguntaCliente,\n        contexto: contexto,\n        id_atendimento: dadosRegistro.id_atendimento || null,\n        origem_tecnica: inputData.contexto?.origem || \"WHATSAPP\"\n    }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1232,
        5728
      ],
      "id": "a10ebecd-1344-4ee0-a946-b9a6d828ee1a",
      "name": "Preparar_Input_Agent"
    },
    {
      "parameters": {
        "operation": "delete",
        "key": "==buffer:{{ $('CheckOrigem').first().json.tecnico.session_id }}"
      },
      "type": "n8n-nodes-base.redis",
      "typeVersion": 1,
      "position": [
        864,
        5392
      ],
      "id": "d8e3eda1-a904-4b6f-8ab2-cf9d04f08b93",
      "name": "Limpar_Buffer_Pos_Execucao",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "portal-web-chat",
        "responseMode": "lastNode",
        "responseData": "body",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -128,
        6800
      ],
      "id": "aab12345-0001-4000-b000-000000000001",
      "name": "WebhookPortal"
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json.body || $input.first().json;\nconst cpf = (data.cpf || data.identifier || data.user_cpf || '').replace(/\\D/g, '');\nconst nome = data.client_name || data.nome || 'Cliente';\nconst email = data.email || '';\nconst telefone = (data.telefone || data.target || '').replace(/\\D/g, '');\nconst pergunta = data.pergunta_cliente || data.message || data.pergunta || 'Ola';\n// OMNICHANNEL: mesma chave do WhatsApp => mesma memoria Postgres\nconst sessionKey = telefone ? telefone + '_v2' : 'PORTAL_SEM_FONE_' + (cpf || Date.now());\nreturn [{ json: { pergunta_cliente: pergunta, session_key: sessionKey, cpf_portal: cpf, email_portal: email, nome_portal: nome, telefone_portal: telefone, contexto: { nome: nome, cpf_real: cpf, cpf_exibicao: cpf ? '***.***.***-' + cpf.slice(-2) : 'Nao informado', telefone: telefone, email_cadastrado: email, token_validado: 'SIM', cadastrado: true, origem: 'PORTAL_WEB', tipo_cliente: 'CADASTRADO', resumo_apolices: [] } }}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        6800
      ],
      "id": "aab12345-0002-4000-b000-000000000002",
      "name": "NormalizarPortal"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT c.nome_completo, c.cpf, c.email, c.celular, (SELECT json_agg(a) FROM public.apolices_brokeria a WHERE a.id_cliente::text = c.id_cliente::text AND UPPER(a.status_apolice) = 'ATIVA') as apolices_ativas FROM public.clientes_brokeria c WHERE REPLACE(REPLACE(c.cpf, '.', ''), '-', '') = '{{ $json.cpf_portal }}' LIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        480,
        6800
      ],
      "id": "aab12345-0003-4000-b000-000000000003",
      "name": "BuscaClientePortal",
      "alwaysOutputData": true,
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const norm = $('NormalizarPortal').first().json;\nconst db = $input.first().json;\n\n// Garante prote\u00e7\u00e3o contra retorno vazio do banco e diferencia cliente novo/cadastrado\nconst dbData = db || {};\nconst hasCliente = !!(dbData.nome_completo);\n\nconst nomeFinal = dbData.nome_completo || norm.nome_portal || 'Cliente';\nconst emailFinal = dbData.email || norm.email_portal || '';\nconst telFinal = (dbData.celular || norm.telefone_portal || '').toString().replace(/\\D/g, '');\nconst cpfFinal = norm.cpf_portal || (dbData.cpf ? dbData.cpf.replace(/\\D/g, '') : '');\n\nconst apolicesRaw = Array.isArray(dbData.apolices_ativas) ? dbData.apolices_ativas : [];\nconst resumo_apolices = apolicesRaw.map(ap => ({\n    seguradora: ap.seguradora || 'N/A',\n    tipo: ap.ramo || 'N/A',\n    status: ap.status_apolice || 'ATIVA',\n    apolice: ap.numero_apolice || 'N/A',\n    vencimento: ap.vigencia_fim || 'N/A',\n    placa: ap.placa || 'N/A'\n}));\n\nreturn [{\n    json: {\n        pergunta_cliente: norm.pergunta_cliente,\n        session_key: norm.session_key,\n        origem: 'PORTAL_WEB',\n        contexto: {\n            nome: nomeFinal,\n            cpf_real: cpfFinal,\n            cpf_exibicao: cpfFinal ? '***.***.***-' + cpfFinal.slice(-2) : 'Nao informado',\n            telefone: telFinal,\n            email_cadastrado: emailFinal,\n            token_validado: 'SIM',\n            cadastrado: hasCliente,\n            origem: 'PORTAL_WEB',\n            tipo_cliente: hasCliente ? 'CADASTRADO' : 'NOVO',\n            resumo_apolices: resumo_apolices\n        }\n    }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        6800
      ],
      "id": "aab12345-0004-4000-b000-000000000004",
      "name": "MontarContextoPortal"
    },
    {
      "parameters": {
        "jsCode": "const out = $input.first().json;\nconst texto = out.output || out.text || out.response || 'Nao consegui gerar uma resposta. Tente novamente.';\nreturn [{ json: { response: texto } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        6800
      ],
      "id": "aab12345-0008-4000-b000-000000000008",
      "name": "FormatarRespostaPortal"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "portal-origin-check-001",
              "leftValue": "={{ (() => { try { return $('MontarContextoPortal').first().json.origem; } catch(e) { return 'WHATSAPP'; } })() }}",
              "rightValue": "PORTAL_WEB",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        960,
        6800
      ],
      "id": "aab12345-0009-4000-b000-000000000009",
      "name": "IF_Portal_Origem"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "NormalizeInbound",
            "type": "main",
            "index": 0
          },
          {
            "node": "Dados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dados": {
      "main": [
        [
          {
            "node": "Consultar WAHA Direto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Seen": {
      "main": [
        [
          {
            "node": "Start Typing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Typing": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "FiltrarResposta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Consultar WAHA Direto": {
      "main": [
        [
          {
            "node": "Limpar Telefone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limpar Telefone": {
      "main": [
        [
          {
            "node": "MergeDados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Busca_Cliente": {
      "main": [
        [
          {
            "node": "Buscar_Sessao_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agrupar_Texto": {
      "main": [
        [
          {
            "node": "Atualizar_Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar_Buffer": {
      "main": [
        [
          {
            "node": "Espera_3_Segundos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Espera_3_Segundos": {
      "main": [
        [
          {
            "node": "Check_Pos_Espera",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check_Pos_Espera": {
      "main": [
        [
          {
            "node": "Filtro_Ultima_Execucao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtro_Ultima_Execucao": {
      "main": [
        [
          {
            "node": "Limpar_Buffer_Pos_Execucao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recuperar_Buffer": {
      "main": [
        [
          {
            "node": "Agrupar_Texto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CheckOrigem": {
      "main": [
        [
          {
            "node": "Recuperar_Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SwitchOrigem": {
      "main": [
        [
          {
            "node": "Busca_Cliente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Busca_Cliente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Busca_Cliente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar_Sessao_Existente": {
      "main": [
        [
          {
            "node": "SwitchMidia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SwitchMidia": {
      "main": [
        [
          {
            "node": "DownloadMidia",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ImageDownload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DownloadMidia": {
      "main": [
        [
          {
            "node": "IA_Processar_Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ImageDownload": {
      "main": [
        [
          {
            "node": "IA_Processar_Imagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DefinirContextoAI": {
      "main": [
        [
          {
            "node": "NormalizarEntrada",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IA_Processar_Audio": {
      "main": [
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IA_Processar_Imagem": {
      "main": [
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ConsolidarMensagem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ConsolidarMensagem": {
      "main": [
        [
          {
            "node": "TratamentoErroMidia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TratamentoErroMidia": {
      "main": [
        [],
        [
          {
            "node": "DefinirContextoAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "PostgresChatMemory": {
      "ai_memory": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "QueryPostgresClientes": {
      "ai_tool": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "MergeDados": {
      "main": [
        [
          {
            "node": "FinalizeChatId",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NormalizeInbound": {
      "main": [
        [
          {
            "node": "MergeDados",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Padronizar Output": {
      "main": [
        [
          {
            "node": "Send Seen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FunilRespostas": {
      "main": [
        [
          {
            "node": "IF_Portal_Origem",
            "type": "main",
            "index": 0
          },
          {
            "node": "Preparar_Registro_Cliente_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FiltrarResposta": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BrokerIA_Master": {
      "main": [
        [
          {
            "node": "FunilRespostas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check_Cliente_Novo": {
      "main": [
        [
          {
            "node": "Preparar_Registro_Cliente",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Preparar_Registro_Cliente": {
      "main": [
        [
          {
            "node": "Verificar_Registro_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar_Registro_Existente": {
      "main": [
        [
          {
            "node": "Switch_Registro_Existe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch_Registro_Existe": {
      "main": [
        [
          {
            "node": "Inserir_Novo_Registro",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Atualizar_Registro_Existente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Inserir_Novo_Registro": {
      "main": [
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Atualizar_Registro_Existente": {
      "main": [
        [
          {
            "node": "Merge_Registro",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge_Registro": {
      "main": [
        [
          {
            "node": "Preparar_Input_Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EspecialistaRegistroCotacao": {
      "ai_tool": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Preparar_Registro_Cliente_Existente": {
      "main": [
        [
          {
            "node": "Registrar_Interacao",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NormalizarEntrada": {
      "main": [
        [
          {
            "node": "Check_Cliente_Novo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FinalizeChatId": {
      "main": [
        [
          {
            "node": "CheckOrigem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar_Input_Agent": {
      "main": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limpar_Buffer_Pos_Execucao": {
      "main": [
        [
          {
            "node": "SwitchOrigem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WebhookPortal": {
      "main": [
        [
          {
            "node": "NormalizarPortal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NormalizarPortal": {
      "main": [
        [
          {
            "node": "BuscaClientePortal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BuscaClientePortal": {
      "main": [
        [
          {
            "node": "MontarContextoPortal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MontarContextoPortal": {
      "main": [
        [
          {
            "node": "BrokerIA_Master",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF_Portal_Origem": {
      "main": [
        [
          {
            "node": "FormatarRespostaPortal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Padronizar Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FormatarRespostaPortal": {
      "main": []
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false,
    "timeSavedMode": "fixed",
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "bb616334-e869-44e6-bb8e-a34d49572131",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "6ub3s1KYVUm42odIKeQ9M",
  "tags": []
}