{
  "name": "\u00c1ncorA v5 \u2014 WhatsApp Completo (Texto + Voz + Foto + Disparo)",
  "nodes": [
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\"error\":\"Unauthorized\"}",
        "options": {
          "responseCode": 401
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -480,
        1408
      ],
      "id": "af4693f4-bd95-433b-a8b9-5540b831e4b6",
      "name": "401"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "webhook",
        "responseMode": "lastNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -720,
        208
      ],
      "id": "95543d13-b4ab-40d6-ba99-a930906099ba",
      "name": "Webhook WAHA"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "ancora/disparo",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -720,
        1200
      ],
      "id": "6bed354e-1a1b-4b2f-adc7-24659239fcd1",
      "name": "Webhook Defesa Civil"
    },
    {
      "parameters": {
        "jsCode": "// Parse entrada WAHA \u2014 detecta tipo de m\u00eddia\nconst body = $input.first().json.body ?? $input.first().json;\nconst msg = body.message ?? body.payload ?? body;\n\nconst mediaUrl = msg.mediaUrl || msg.media?.url || body.mediaUrl || null;\nconst mimetype = msg.mimetype || msg.media?.mimetype || '';\nconst hasImage = !!(mediaUrl && mimetype.startsWith('image/'));\nconst hasAudio = !!(mediaUrl && (mimetype.startsWith('audio/') || mimetype.includes('ogg')));\nconst text = msg.body || msg.text || msg.message || '';\n\nreturn [{ json: {\n  session: body.session || 'default',\n  chatId: msg.from || body.chatId || '',\n  payload_id: msg.id || body.payload?.id || '',\n  pushName: msg.pushName || msg._data?.Info?.PushName || msg.notifyName || 'usu\u00e1rio',\n  sessionId: (msg.from || body.chatId || 'unknown').replace('@c.us',''),\n  whatsappId: msg.from || body.chatId || '',\n  message: text,\n  nome: msg.pushName || msg._data?.Info?.PushName || msg.notifyName || 'usu\u00e1rio',\n  hasImage,\n  hasAudio,\n  hasText: !!text && !hasImage && !hasAudio,\n  mediaUrl,\n  mimetype\n}}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -480,
        208
      ],
      "id": "c16d4b4c-22d1-455b-9199-199a4592f135",
      "name": "Parse WAHA"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.hasImage }}",
                    "rightValue": true,
                    "operator": {
                      "type": "boolean",
                      "operation": "equals"
                    },
                    "id": "c-img"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "IMAGEM"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.hasAudio }}",
                    "rightValue": true,
                    "operator": {
                      "type": "boolean",
                      "operation": "equals"
                    },
                    "id": "c-aud"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "AUDIO"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.hasText }}",
                    "rightValue": true,
                    "operator": {
                      "type": "boolean",
                      "operation": "equals"
                    },
                    "id": "c-txt"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "TEXTO"
            }
          ]
        },
        "options": {
          "allMatchingOutputs": false
        }
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        -240,
        208
      ],
      "id": "3b401190-2e1c-415c-883b-5b208af004cc",
      "name": "Tipo M\u00eddia?"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Descreva esta imagem de emerg\u00eancia clim\u00e1tica em 2 frases: {{ $json.mediaUrl }}",
        "options": {
          "systemMessage": "# Vision Agent (Gemini Vision)\n\nO Vision Agent \u00e9 respons\u00e1vel por processar e descrever imagens enviadas pelos usu\u00e1rios via WhatsApp, identificando situa\u00e7\u00f5es de emerg\u00eancia clim\u00e1tica.\n\n## Responsabilidades\n\n- Analisar imagens de alagamentos, deslizamentos ou danos estruturais.\n- Estimar o n\u00edvel da \u00e1gua e riscos vis\u00edveis.\n- Converter a percep\u00e7\u00e3o visual em um resumo textual para o Classificador.\n\n## Configura\u00e7\u00e3o T\u00e9cnica\n\n- **Modelo:** `gemini-2.5-flash`\n- **Temperatura:** 0.1\n- **Input:** `mediaUrl` (URL da imagem no gateway WAHA).\n\n## System Message (Prompt)\n\n> Descreva objetivamente: n\u00edvel de \u00e1gua, danos vis\u00edveis, risco. M\u00e1ximo 2 frases. Se n\u00e3o conseguir ver a imagem, diga 'Imagem recebida \u2014 descreva sua situa\u00e7\u00e3o por texto ou \u00e1udio'.\n\n## Exemplo de Output\n\n`[FOTO] \u00c1gua atingindo a altura dos joelhos na rua, dificultando a passagem de ve\u00edculos. Risco moderado de invas\u00e3o em resid\u00eancias.`\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        0,
        0
      ],
      "id": "9c847252-dd49-43dd-a6e0-776dc4285a1d",
      "name": "Gemini Vision"
    },
    {
      "parameters": {
        "modelName": "models/gemini-3-pro-preview",
        "options": {
          "temperature": 0.4
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        0,
        208
      ],
      "id": "a6dd3130-3c2f-4022-958e-cef23b98c2c6",
      "name": "LLM Vision",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const desc = $input.first().json.output || $input.first().json.text || 'Foto recebida';\nconst ctx = $('Tipo M\u00eddia?').item.json;\nreturn [{ json: { ...ctx, message: '[FOTO] ' + desc + (ctx.message ? '. ' + ctx.message : ''), hasImage: false, hasText: true }}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ],
      "id": "c1a47355-2ce8-4296-ab9c-07a8bba41e00",
      "name": "Texto + Foto"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Transcreva este \u00e1udio fielmente. Apenas o texto falado: {{ $json.mediaUrl }}",
        "options": {
          "systemMessage": "Transcreva o \u00e1udio. Retorne apenas o texto falado sem coment\u00e1rios. Se n\u00e3o conseguir, retorne 'N\u00e3o consegui ouvir \u2014 pode repetir por texto?'"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        0,
        304
      ],
      "id": "80d88ba4-3350-4289-8029-a69c400fb5df",
      "name": "Gemini Transcri\u00e7\u00e3o"
    },
    {
      "parameters": {
        "modelName": "models/gemini-3-pro-preview",
        "options": {
          "temperature": 0.4
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        0,
        512
      ],
      "id": "3010b2bf-375f-4151-96e7-055722341f0a",
      "name": "LLM \u00c1udio",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const trans = $input.first().json.output || $input.first().json.text || '';\nconst ctx = $('Tipo M\u00eddia?').item.json;\nreturn [{ json: { ...ctx, message: '[VOZ] ' + trans, hasAudio: false, hasText: true }}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        304
      ],
      "id": "dd41fe93-70ef-4967-98d5-6644121541a5",
      "name": "Texto + \u00c1udio"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=SESS\u00c3O: {{ $json.sessionId }}\nNOME: {{ $json.nome }}\nMENSAGEM: {{ $json.message }}",
        "options": {
          "systemMessage": "# \u00c1ncorA \u2014 Classificador v5\n\nClassifique a mensagem. Retorne APENAS JSON.\n\n## PANIC SCORE\n1=informativo, 2=preocupa\u00e7\u00e3o, 3=alerta, 4=emerg\u00eancia, 5=perigo de vida\n\n[FOTO] com \u00e1gua/enchente \u2192 m\u00ednimo 3\n[VOZ] com desespero/gritos \u2192 m\u00ednimo 4\n\n## BAIRROS SALVADOR\nLiberdade, Cajazeiras, Sussuarana, Boca do Rio, Plataforma, Sub\u00farbio, Pau da Lima, Lobato, S\u00e3o Caetano, Val\u00e9ria, Fazenda Coutos, Mussurunga, Itapu\u00e3, Pernambu\u00e9s, Saramandaia, Bom Ju\u00e1, Calabet\u00e3o, Sete de Abril.\n\n## SA\u00cdDA\n{\"panicScore\":<1-5>,\"riskLevel\":\"BAIXO|MEDIO|ALTO|CRITICO\",\"isSalvador\":<bool>,\"bairroDetectado\":\"<ou null>\",\"cidadeDetectada\":\"<cidade>\",\"tipoRisco\":\"ALAGAMENTO|DESLIZAMENTO|ENCHENTE|DESCONHECIDO\",\"resumoContexto\":\"<frase>\",\"ROUTE\":\"INFO|SALVADOR\"}\n\nROUTE: panicScore<=2 OU !isSalvador \u2192 INFO. panicScore>=3 E isSalvador \u2192 SALVADOR"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        480,
        208
      ],
      "id": "df8eda85-ed7d-4ebe-8ba0-0dbc29035d12",
      "name": "Classificador"
    },
    {
      "parameters": {
        "options": {
          "temperature": 0.1
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        480,
        432
      ],
      "id": "addb16b3-4710-4b71-ac3f-800e1b50bbab",
      "name": "LLM Classificador",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "=cls_{{ $json.sessionId }}",
        "sessionTTL": 3600,
        "contextWindowLength": 4
      },
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "typeVersion": 1.5,
      "position": [
        608,
        432
      ],
      "id": "d37c3a46-67bd-4ff7-9897-52ba973caeaa",
      "name": "Redis Class",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const raw = $input.first().json.output ?? $input.first().json.text ?? '';\nlet c;\ntry { const m = raw.match(/{[\\s\\S]*}/); c = JSON.parse(m ? m[0] : raw); }\ncatch(e) { c = { panicScore:2, riskLevel:'MEDIO', isSalvador:false, bairroDetectado:null, cidadeDetectada:'desconhecida', tipoRisco:'DESCONHECIDO', resumoContexto:'Fallback', ROUTE:'INFO' }; }\n\n// FIX: cidade desconhecida \u2192 assume Salvador (contexto do piloto)\nif (!c.cidadeDetectada || c.cidadeDetectada === 'DESCONHECIDO'  || c.cidadeDetectada === 'desconhecida') {\n  c.isSalvador = true;\n  c.cidadeDetectada = 'Salvador';\n  c.ROUTE = c.panicScore <= 2 ? 'INFO' : 'SALVADOR';\n}\n\nconst prev = $('Classificador').item.json;\nreturn [{ json: { ...c, route: c.ROUTE, sessionId: prev.sessionId, whatsappId: prev.whatsappId ||  prev.sessionId, message: prev.message, nome: prev.nome, bairro: c.bairroDetectado  || '', showEmergencyButton: c.panicScore >= 5 }}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        208
      ],
      "id": "a22899fc-b0c5-4adc-87bb-e4b839ee64db",
      "name": "Extrair JSON"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.route }}",
                    "rightValue": "INFO",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-info"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "INFO"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.route }}",
                    "rightValue": "SALVADOR",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-ssa"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "SALVADOR"
            }
          ]
        },
        "options": {
          "allMatchingOutputs": false
        }
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        944,
        208
      ],
      "id": "fb25b814-fd56-4d1b-836f-5d33a28334a2",
      "name": "Roteador"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=NOME: {{ $json.nome }}\nPANIC: {{ $json.panicScore }}\nCIDADE: {{ $json.cidadeDetectada }}\nIS_SALVADOR: {{ $json.isSalvador }}\nMENSAGEM: {{ $json.message }}",
        "options": {
          "systemMessage": "Voc\u00ea \u00e9 a \u00c1ncorA, assistente clim\u00e1tica (piloto em Salvador).\n\nSE isSalvador=false: \"Ol\u00e1! O \u00c1ncorA est\u00e1 em piloto em *Salvador*. Para emerg\u00eancias em [Cidade]:\n\ud83c\udd98 Defesa Civil: *199*\n\ud83d\ude92 Bombeiros: *193*\n\ud83d\ude91 SAMU: *192*\nEstamos expandindo! \u2693\"\n\nSE panicScore 1-2 e Salvador: resposta preventiva, acolhedora, curta. Dica \u00fatil.\n\nWhatsApp. Frases curtas. *negrito* nativo. Sem JSON."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1184,
        0
      ],
      "id": "2f82a19a-0f32-439f-8ba2-f7fe1c51d43b",
      "name": "Agente Info"
    },
    {
      "parameters": {
        "options": {
          "temperature": 0.5
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1184,
        208
      ],
      "id": "82b7d7e0-4960-46ad-ab80-3ac7458ee7d6",
      "name": "LLM Info",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "=info_{{ $json.sessionId }}",
        "sessionTTL": 3600,
        "contextWindowLength": 8
      },
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "typeVersion": 1.5,
      "position": [
        1312,
        208
      ],
      "id": "c6a985b0-64cf-4646-8342-0b70d4307cc7",
      "name": "Redis Info",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://api:4000/risk/analyze",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1184,
        400
      ],
      "id": "995f7d06-e54c-4a0b-a710-e22e312688b2",
      "name": "POST /risk/analyze",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://api:4000/climate/risk",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1184,
        608
      ],
      "id": "d59c1de0-8b5e-4736-8bf4-14923c8a9c92",
      "name": "POST /climate/risk",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "mode": "combineAll"
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1424,
        512
      ],
      "id": "777163d8-f7e2-46e2-91b8-aa1fc729a65a",
      "name": "Merge Abrigo + Clima"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=DADOS APIs:\n{{ JSON.stringify($json) }}\n\nNOME: {{ $('Extrair JSON').item.json.nome }}\nMENSAGEM: {{ $('Extrair JSON').item.json.message }}\nPANIC: {{ $('Extrair JSON').item.json.panicScore }}\nRISCO: {{ $('Extrair JSON').item.json.tipoRisco }}\nBOT\u00c3O EMERG\u00caNCIA: {{ $('Extrair JSON').item.json.showEmergencyButton }}",
        "options": {
          "systemMessage": "# \u00c1ncorA \u2014 Executor Salvador v5\n\nVoc\u00ea recebe dados de 2 APIs:\n- /risk/analyze: { riskLevel, shelter:{nome,endereco,distancia}, nearbyShelters, emergencyContacts }\n- /climate/risk: { riskLevel, summary, historicalPattern, context }\n\n## FORMATO POR PANIC SCORE\n\n**3 (Alerta):** Tom firme. Contexto hist\u00f3rico. Orienta a\u00e7\u00e3o. Menciona abrigo.\n\n**4 (Emerg\u00eancia):** URGENTE. Primeira linha = a\u00e7\u00e3o. Abrigo obrigat\u00f3rio.\n\"*Saia agora.* N\u00e3o espere a \u00e1gua entrar.\"\n\ud83d\udccd *[nome abrigo]* \u2014 [endereco] ([distancia])\n\n**5 (Cr\u00edtico):** Primeira linha = emerg\u00eancia.\n\"\ud83c\udd98 *Defesa Civil: 199 | Bombeiros: 193 | SAMU: 192*\"\nInstru\u00e7\u00e3o de sobreviv\u00eancia + abrigo.\n\n## REGRAS\n- Use NOME na primeira linha: \"*[Nome]*, ...\"\n- WhatsApp: *negrito*, _it\u00e1lico_. Frases curtas.\n- Emojis: \u26a0\ufe0f \ud83d\udccd \ud83c\udd98 \ud83d\udeb6 \u2614\n- Se shelter=null: \"Suba para o ponto mais alto da sua rua.\"\n- showEmergencyButton=true \u2192 SEMPRE termine com: \ud83c\udd98 *199* | *193* | *192*\n- NUNCA mencione API, JSON, backend, ChromaDB\n\nTexto direto. SEM JSON."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1664,
        512
      ],
      "id": "980208e5-e0bf-4898-bc8f-57c6933a6e7b",
      "name": "Executor Salvador"
    },
    {
      "parameters": {
        "options": {
          "temperature": 0.3
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1664,
        720
      ],
      "id": "f199e32a-b4fd-4cf6-9acf-c69d339dd79f",
      "name": "LLM Salvador",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "=ssa_{{ $('Extrair JSON').item.json.sessionId }}",
        "sessionTTL": 3600,
        "contextWindowLength": 10
      },
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "typeVersion": 1.5,
      "position": [
        1792,
        720
      ],
      "id": "23bd42c7-4486-479e-8b7c-74b89509aadb",
      "name": "Redis SSA",
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Seen",
        "session": "={{ $('Parse WAHA').item.json.session }}",
        "chatId": "={{ $('Parse WAHA').item.json.chatId }}",
        "messageId": "={{ $('Parse WAHA').item.json.payload_id }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2032,
        384
      ],
      "id": "445145dc-f1d4-480e-8b3b-e7aab3cb5f71",
      "name": "Send Seen",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Text",
        "session": "={{ $('Parse WAHA').item.json.session }}",
        "chatId": "={{ $('Parse WAHA').item.json.chatId }}",
        "text": "={{ $input.first().json.output ?? $input.first().json.text ?? 'Desculpe, tive um problema. Ligue 199 (Defesa Civil) se for emerg\u00eancia.' }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        2224,
        128
      ],
      "id": "483d4bcc-a28d-4ae8-85fe-2d2c7e32e650",
      "name": "WAHA Responde",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{ $json.headers['x-dc-token'] ?? $json.body?.token }}",
              "rightValue": "={{ $env.DEFESA_CIVIL_TOKEN ?? 'ancora-dc-2026' }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "id": "tk"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -480,
        1200
      ],
      "id": "f4f8ce82-4443-400e-8cd8-f0c63d5840ac",
      "name": "Token V\u00e1lido?"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://api:4000/contacts/search",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -208,
        1200
      ],
      "id": "96c1bc71-f5c6-4b83-ab18-e1bfa49326f0",
      "name": "POST /contacts/search"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status:'accepted', total: $json.total ?? 0, area: $('Webhook Defesa Civil').item.json.body.area, timestamp: new Date().toISOString() }) }}",
        "options": {
          "responseCode": 202
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -208,
        1408
      ],
      "id": "44752dcd-f90f-4ef6-ba07-33f3ed2fb790",
      "name": "202 Aceito"
    },
    {
      "parameters": {
        "jsCode": "// Transforma contacts em itens individuais pra split\nconst contacts = $json.contacts || [];\nreturn contacts.map(c => ({ json: c }));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        80,
        1200
      ],
      "id": "792e3fb1-1b31-49ac-af03-a11b70af0f6b",
      "name": "Explode Contatos"
    },
    {
      "parameters": {
        "batchSize": 5,
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        320,
        1200
      ],
      "id": "c8e46523-92ce-435d-b669-4638b752c1e9",
      "name": "Lotes de 5"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=ALERTA:\n{{ JSON.stringify($('Webhook Defesa Civil').item.json.body) }}\n\nDESTINAT\u00c1RIO: {{ $json.nome || $json.primeiroNome || 'Morador' }}",
        "options": {
          "systemMessage": "# \u00c1ncorA \u2014 Alerta Ativo\n\nGere mensagem WhatsApp curta (m\u00e1x 3 par\u00e1grafos) para o destinat\u00e1rio.\n\n## FORMATO\n\u26a0\ufe0f *[Nome]*, alerta da Defesa Civil:\n\n[Risco + \u00e1rea em 1-2 frases]\n\n[A\u00e7\u00e3o imediata]\n\ud83c\udd98 Defesa Civil: *199* | Bombeiros: *193*\n\n*negrito* nativo WA. Texto direto. SEM JSON."
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        560,
        1200
      ],
      "id": "f4bd1845-4341-4466-b90a-d0a57fc8f9d6",
      "name": "Gera Alerta"
    },
    {
      "parameters": {
        "options": {
          "temperature": 0.4
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        560,
        1408
      ],
      "id": "ac3071dc-f2c6-4d94-8c43-4ba53f54fbca",
      "name": "LLM Disparo",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "Chatting",
        "operation": "Send Text",
        "session": "={{ $env.WAHA_SESSION ?? 'default' }}",
        "chatId": "={{ $('Lotes de 5').item.json.formatoE164 || $('Lotes de 5').item.json.telefone }}@c.us",
        "text": "={{ $json.output ?? $json.text ?? '' }}",
        "requestOptions": {}
      },
      "type": "n8n-nodes-waha.WAHA",
      "typeVersion": 202411,
      "position": [
        800,
        1200
      ],
      "id": "7082cfbf-7be9-4d40-ba24-4a757b7a89df",
      "name": "WAHA Disparo",
      "credentials": {
        "wahaApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Webhook WAHA": {
      "main": [
        [
          {
            "node": "Parse WAHA",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse WAHA": {
      "main": [
        [
          {
            "node": "Tipo M\u00eddia?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tipo M\u00eddia?": {
      "main": [
        [
          {
            "node": "Gemini Vision",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gemini Transcri\u00e7\u00e3o",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Classificador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM Vision": {
      "ai_languageModel": [
        [
          {
            "node": "Gemini Vision",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Vision": {
      "main": [
        [
          {
            "node": "Texto + Foto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Texto + Foto": {
      "main": [
        [
          {
            "node": "Classificador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM \u00c1udio": {
      "ai_languageModel": [
        [
          {
            "node": "Gemini Transcri\u00e7\u00e3o",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Transcri\u00e7\u00e3o": {
      "main": [
        [
          {
            "node": "Texto + \u00c1udio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Texto + \u00c1udio": {
      "main": [
        [
          {
            "node": "Classificador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM Classificador": {
      "ai_languageModel": [
        [
          {
            "node": "Classificador",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Redis Class": {
      "ai_memory": [
        [
          {
            "node": "Classificador",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Classificador": {
      "main": [
        [
          {
            "node": "Extrair JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extrair JSON": {
      "main": [
        [
          {
            "node": "Roteador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Roteador": {
      "main": [
        [
          {
            "node": "Agente Info",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "POST /risk/analyze",
            "type": "main",
            "index": 0
          },
          {
            "node": "POST /climate/risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM Info": {
      "ai_languageModel": [
        [
          {
            "node": "Agente Info",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Redis Info": {
      "ai_memory": [
        [
          {
            "node": "Agente Info",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Agente Info": {
      "main": [
        [
          {
            "node": "WAHA Responde",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "POST /risk/analyze": {
      "main": [
        [
          {
            "node": "Merge Abrigo + Clima",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "POST /climate/risk": {
      "main": [
        [
          {
            "node": "Merge Abrigo + Clima",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Abrigo + Clima": {
      "main": [
        [
          {
            "node": "Executor Salvador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM Salvador": {
      "ai_languageModel": [
        [
          {
            "node": "Executor Salvador",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Redis SSA": {
      "ai_memory": [
        [
          {
            "node": "Executor Salvador",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Executor Salvador": {
      "main": [
        [
          {
            "node": "Send Seen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Seen": {
      "main": [
        [
          {
            "node": "WAHA Responde",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Defesa Civil": {
      "main": [
        [
          {
            "node": "Token V\u00e1lido?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Token V\u00e1lido?": {
      "main": [
        [
          {
            "node": "POST /contacts/search",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "401",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "POST /contacts/search": {
      "main": [
        [
          {
            "node": "202 Aceito",
            "type": "main",
            "index": 0
          },
          {
            "node": "Explode Contatos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Explode Contatos": {
      "main": [
        [
          {
            "node": "Lotes de 5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lotes de 5": {
      "main": [
        [
          {
            "node": "Gera Alerta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM Disparo": {
      "ai_languageModel": [
        [
          {
            "node": "Gera Alerta",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gera Alerta": {
      "main": [
        [
          {
            "node": "WAHA Disparo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "72dc2661-ae95-45c3-9136-357c58ccea93",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "g16fLYM40CxSI2Ic",
  "tags": [
    {
      "name": "ancora-v5",
      "id": "reg621S013nfFSJb",
      "updatedAt": "2026-05-22T13:15:44.454Z",
      "createdAt": "2026-05-22T13:15:44.454Z"
    }
  ]
}