{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "embalagio-atendimento",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -1280,
        -352
      ],
      "id": "67f60a6f-4e63-475e-b235-ef8694a8d9fa",
      "name": "Webhook"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "b52d7be0-acb7-4281-973e-a9f7f5d12a36",
              "leftValue": "={{ $json.body.message }}",
              "rightValue": "__ping__",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1056,
        -528
      ],
      "id": "bb55baba-d140-4839-8d2e-78c381a77304",
      "name": "If"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Hist\u00f3rico da conversa at\u00e9 agora:\n{{ $json.body.history }}\n\nMensagem atual do cliente:\n{{ $json.body.message }}",
        "messages": {
          "messageValues": [
            {
              "message": "[SYSTEM] CRITICAL: YOU ARE A JSON-ONLY BOT. NO TEXT OUTSIDE JSON BRACES { }.    [ROLE] \"Embalagio IA\", a highly charismatic, empathetic, and natural sales concierge for Embalagio (Frederico Westphalen/RS). Sells: Packaging (boxes, bags), confectionery items, party supplies. Vibe: Warm, welcoming, human-like. NEVER robotic.    [STRICT ALGORITHM - EVALUATE IN THIS EXACT ORDER]   STEP 1: Check 'Hist\u00f3rico da conversa' and current message.   STEP 1.5: SCOPE FILTER (ANTI-TRASH): If the request is clearly unrelated to Embalagio's business (Packaging, confectionery, party supplies). Examples: repairs, electronics, medicine, services not mentioned in [ROLE]. If unrelated: Status MUST be \"Disqualified\". Set Intent to \"Out of Scope\". Reply: Explain warmly that Embalagio only handles packaging and party supplies. DO NOT ask for name, product, or quantity. SKIP ALL REMAINING STEPS if Status is \"Disqualified\".   STEP 2: Identify 3 variables:        - Customer_Name (Person's name OR business/company name).        - Intent: Strictly 1 single broad word representing the core product category (e.g., 'Sacolas', 'Caixas', 'Potes', 'Embalagens').    - Quantity (number).   STEP 3: MISSING DATA CHECK:        - If ANY variable is missing, Status MUST be \"Qualifying\".        - Missing Name -> Ask for their name or company name warmly.        - Missing Intent -> Ask what packaging product they are looking for.        - Missing Quantity -> Acknowledge their choice, ask how many units.        * SACRED RULE: Generate unique, warm responses.   STEP 4: LARGE QUANTITY (>1000) & MANDATORY CONFIRMATION:     If Qty is strictly greater than 1000 (Qty > 1000):  a) Even if the user says \"confirmado\" in the first message, you MUST ask for a dedicated confirmation in a new turn. If you have not asked yet: Status MUST be \"Qualifying\". Ask them to confirm this specific large quantity warmly. b) If your immediately preceding message already asked for confirmation, and the user now replies affirmatively (\"sim\", \"ss\", \"s\", \"confirmo\"), consider it CONFIRMED.    STEP 5: COMPLETION (ABSOLUTE RULE):     When Name, Intent, and Quantity are present (and large qty is <=1000 or confirmed in a dedicated turn), set Status to \"Complete\".     TERMINATION POLICY: You must end the conversation immediately.  STRICTLY PROHIBITED: DO NOT mention \"human consultants\", \"someone will call you\", \"next steps\", \"finishing details\", or \"contacting soon\". MANDATORY: Just thank them warmly and say a final goodbye. Period.    [OUTPUT FORMAT]  {  \"thought_process\": \"1. Name: [X]. 2. Intent: [Y]. 3. Qty: [Z]. Next action: [Action].\",  \"Status\": \"Qualifying, Complete, or Disqualified\",  \"Customer_Name\": \"Cleaned name or company name, or null\",  \"Intent\": \"Strictly 1 single broad word (e.g., 'Sacolas')\",  \"Summary\": \"[Quantity] [Cleaned product name including all relevant specifications like size or type]\",  \"Reply\": \"Your uniquely generated, highly natural response in pt-BR. STRICTLY FORBIDDEN to mention any human follow-up or future contact.\"  }"
            }
          ]
        },
        "batching": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.9,
      "position": [
        -1024,
        -320
      ],
      "id": "64fce92b-0e95-4160-889d-7cc9e96b48da",
      "name": "Basic LLM Chain"
    },
    {
      "parameters": {
        "model": "qwen/qwen3-32b",
        "options": {
          "temperature": 0.4
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "typeVersion": 1,
      "position": [
        -1200,
        -128
      ],
      "id": "961de3d0-19b8-4bcb-887d-ef9a05d8d846",
      "name": "Groq Chat Model",
      "retryOnFail": true,
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": ":)",
          "mode": "list",
          "cachedResultName": "Embalagio_Leads_CRM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/:)/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/:)/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Timestamp": "={{ $now }}",
            "Customer_Name": "={{ $json.Customer_Name }}",
            "Intent": "={{ $json.Intent }}",
            "Summary": "={{ $json.Summary }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Timestamp",
              "displayName": "Timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Customer_Name",
              "displayName": "Customer_Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Intent",
              "displayName": "Intent",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Summary",
              "displayName": "Summary",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Original_Message",
              "displayName": "Original_Message",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        -336,
        -320
      ],
      "id": "c1e580f6-dfdd-4974-a67c-65ffb3b21393",
      "name": "Append row in sheet",
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "f2ed78ff-ff24-40fc-abb4-bfcb1b74a007",
              "leftValue": "={{ $json.text }}",
              "rightValue": "\"Status\": \"Complete\"",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -704,
        -480
      ],
      "id": "b8245928-1c17-46d8-8bd7-ed22623344e7",
      "name": "If1"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $('Basic LLM Chain').item.json.text }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        -336,
        -128
      ],
      "id": "1cd57843-422b-4f32-a26b-4d23c762cfc8",
      "name": "Respond to Webhook1"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $('Basic LLM Chain').item.json.text }}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        -704,
        -256
      ],
      "id": "e0bda4ba-ab22-4e48-87ab-b961301fcecb",
      "name": "Respond to Webhook2"
    },
    {
      "parameters": {
        "jsCode": "// Pega o texto bruto que veio da IA\nconst rawText = $input.first().json.text || $input.first().json.output;\n\n// Procura onde o JSON realmente come\u00e7a e termina, ignorando o <think>\nconst jsonMatch = rawText.match(/\\{[\\s\\S]*\\}/);\n\nif (jsonMatch) {\n    // Transforma o texto limpo em um objeto de dados real\n    const data = JSON.parse(jsonMatch[0]);\n    return { json: data };\n}\n\n// Se der erro, retorna vazio para n\u00e3o quebrar o fluxo\nreturn { json: {} };"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -496,
        -448
      ],
      "id": "6971e279-e18b-4188-a04f-6961bba0dd70",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "content": "## REGISTRO NO CRM\nInsere automaticamente o **Lead Qualificado** na planilha, salvando o **Nome, Inten\u00e7\u00e3o** e o **Resumo** do pedido."
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -384
      ],
      "typeVersion": 1,
      "id": "1d344815-6ec0-45f1-9598-0643eb31d2d1",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "## TRATAMENTO DE DADOS\nScript em **JavaScript** que normaliza e limpa os campos do **JSON** para garantir a integridade dos dados na planilha.",
        "width": 256
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -624
      ],
      "typeVersion": 1,
      "id": "0dd16c8d-17fb-4e56-9e3b-357f5e54c7f6",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## FILTRO DE STATUS\nAnalisa o campo **Status**. Se for **'Complete'**, o fluxo segue para o registro; caso contr\u00e1rio, apenas responde ao usu\u00e1rio."
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -784,
        -656
      ],
      "typeVersion": 1,
      "id": "45aeeb5e-4552-41b3-aa81-46b29e26e392",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "## FILTRO DE PING\nIdentifica se a requisi\u00e7\u00e3o \u00e9 apenas um **teste de conex\u00e3o** do servidor ou uma **mensagem real** de um cliente."
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1136,
        -704
      ],
      "typeVersion": 1,
      "id": "8d214120-f544-4ca4-9c71-a68aa6dcfbcc",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "## PORTA DE ENTRADA\nRecebe as mensagens em tempo real vindas da interface Streamlit via Webhook."
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1440,
        -528
      ],
      "typeVersion": 1,
      "id": "52a5fe34-74df-4ea8-b10e-fea7cff1d4e4",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## C\u00c9REBRO (Qwen 3)\nO modelo **Qwen 3** via **Groq** processa o contexto, extrai dados estruturados em **JSON** e redige a resposta.",
        "width": 272
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        -160
      ],
      "typeVersion": 1,
      "id": "204f6021-ccaa-44c2-8aa5-5b66eb6f8d67",
      "name": "Sticky Note"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [],
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If1": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond to Webhook2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respond to Webhook2": {
      "main": [
        []
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Append row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}