{
  "id": "AILeadConciergePublic",
  "name": "01 - AI Lead Response & Qualification Concierge [MVP]",
  "nodes": [
    {
      "parameters": {},
      "id": "f7684bf6-cf41-47c8-b836-d36dfde508f3",
      "name": "Manual Test Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1120,
        420
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "e25da9b1-68f1-45a8-8f44-d74510d7e9e1",
              "name": "full_name",
              "value": "Amara Okafor",
              "type": "string"
            },
            {
              "id": "52a3f8a1-104d-4b0c-a119-ea5694cf5cf7",
              "name": "business_email",
              "value": "tester@example.com",
              "type": "string"
            },
            {
              "id": "a637e40b-729e-46d5-9f29-f023dd437293",
              "name": "company_name",
              "value": "Northstar Growth Studio",
              "type": "string"
            },
            {
              "id": "c82f7a7d-8f55-43fe-a579-d9ae544e981e",
              "name": "business_type",
              "value": "Agency",
              "type": "string"
            },
            {
              "id": "174c4af8-61f5-4a72-b0d6-0616847702c2",
              "name": "service_needed",
              "value": "Lead management",
              "type": "string"
            },
            {
              "id": "22a13598-51fb-4aaa-aa0b-75cd61d1a81b",
              "name": "monthly_lead_volume",
              "value": "51-200",
              "type": "string"
            },
            {
              "id": "73d4783a-666c-42fc-975c-9a9f678efbc1",
              "name": "budget_range",
              "value": "$2,000-$5,000",
              "type": "string"
            },
            {
              "id": "f6ed1fc5-f312-4a10-a91d-cd49762dc5b4",
              "name": "timeline",
              "value": "Within 30 days",
              "type": "string"
            },
            {
              "id": "33b94836-d8c4-46fb-9846-c34c75600f51",
              "name": "challenge",
              "value": "We receive enquiries from three channels, but follow-up is inconsistent and strong leads sometimes wait a full day for a response.",
              "type": "string"
            },
            {
              "id": "55f75cd9-b565-4eb8-910b-da0c6388c11d",
              "name": "contact_consent",
              "value": "Yes",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "a02e69f0-a967-4e96-8ec8-d2ba29eca39a",
      "name": "Sample High-Intent Lead",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -880,
        420
      ]
    },
    {
      "parameters": {
        "authentication": "none",
        "formTitle": "AI Automation Enquiry",
        "formDescription": "Tell us where manual work is slowing your business down. This demonstration uses AI to organize and prioritize the enquiry; a human reviews consequential follow-up.",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Full name",
              "fieldName": "full_name",
              "fieldType": "text",
              "placeholder": "e.g. Amara Okafor",
              "requiredField": true
            },
            {
              "fieldLabel": "Business email",
              "fieldName": "business_email",
              "fieldType": "email",
              "placeholder": "you@company.com",
              "requiredField": true
            },
            {
              "fieldLabel": "Company name",
              "fieldName": "company_name",
              "fieldType": "text",
              "placeholder": "Your business",
              "requiredField": true
            },
            {
              "fieldLabel": "Business type",
              "fieldName": "business_type",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Agency"
                  },
                  {
                    "option": "Coaching or consulting"
                  },
                  {
                    "option": "Professional services"
                  },
                  {
                    "option": "Ecommerce"
                  },
                  {
                    "option": "SaaS or technology"
                  },
                  {
                    "option": "Other"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "What would you most like to improve?",
              "fieldName": "service_needed",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Lead management"
                  },
                  {
                    "option": "Customer support"
                  },
                  {
                    "option": "Finance or invoicing"
                  },
                  {
                    "option": "Client onboarding"
                  },
                  {
                    "option": "Content or marketing"
                  },
                  {
                    "option": "Other"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Approximate monthly lead volume",
              "fieldName": "monthly_lead_volume",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "0-10"
                  },
                  {
                    "option": "11-50"
                  },
                  {
                    "option": "51-200"
                  },
                  {
                    "option": "200+"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Indicative implementation budget",
              "fieldName": "budget_range",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Under $500"
                  },
                  {
                    "option": "$500-$2,000"
                  },
                  {
                    "option": "$2,000-$5,000"
                  },
                  {
                    "option": "$5,000+"
                  },
                  {
                    "option": "Not sure"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "When would you like to improve this process?",
              "fieldName": "timeline",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Immediately"
                  },
                  {
                    "option": "Within 30 days"
                  },
                  {
                    "option": "1-3 months"
                  },
                  {
                    "option": "Exploring"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Describe the bottleneck and its impact",
              "fieldName": "challenge",
              "fieldType": "textarea",
              "placeholder": "What happens today, what goes wrong, and what would a better outcome look like?",
              "requiredField": true
            },
            {
              "fieldLabel": "May we contact you about this enquiry?",
              "fieldName": "contact_consent",
              "fieldType": "radio",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Yes"
                  },
                  {
                    "option": "No"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        },
        "responseMode": "onReceived",
        "options": {
          "buttonLabel": "Send enquiry",
          "ignoreBots": true,
          "useWorkflowTimezone": true
        }
      },
      "id": "95375145-f262-4747-867b-e0c82c91108f",
      "name": "Lead Intake Form",
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.6,
      "position": [
        -880,
        100
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "id": "5d7b6ae8-211d-4bf8-a2a4-f87d7c9cbe91",
      "name": "Poll Google Form Responses",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -1160,
        -20
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "read",
        "documentId": {
          "mode": "id",
          "value": "SPREADSHEET_ID"
        },
        "sheetName": {
          "mode": "id",
          "value": "RESPONSE_SHEET_ID"
        },
        "filtersUI": {},
        "combineFilters": "AND",
        "options": {}
      },
      "id": "30b0bf3c-b8d4-421d-8743-f6aab9f227f4",
      "name": "Read Google Form Response Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        -920,
        -20
      ]
    },
    {
      "parameters": {
        "jsCode": "const state = $getWorkflowStaticData('global');\nconst now = Date.now();\nconst retentionMs = 90 * 24 * 60 * 60 * 1000;\nconst previous = state.google_form_seen;\nconst seen = {};\n\n// Migrate the original array format, then retain fingerprints for 90 days.\nif (Array.isArray(previous)) {\n  for (const fingerprint of previous) seen[fingerprint] = now;\n} else if (previous && typeof previous === 'object') {\n  for (const [fingerprint, recordedAt] of Object.entries(previous)) {\n    const timestamp = Number(recordedAt);\n    if (Number.isFinite(timestamp) && now - timestamp < retentionMs) seen[fingerprint] = timestamp;\n  }\n}\n\nconst fresh = [];\nfunction fnv1a(text) {\n  let hash = 2166136261;\n  for (let i = 0; i < text.length; i++) {\n    hash ^= text.charCodeAt(i);\n    hash = Math.imul(hash, 16777619);\n  }\n  return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\nfor (const item of $input.all()) {\n  const row = item.json;\n  if (!row.Timestamp && !row['Business email']) continue;\n  const fingerprint = fnv1a(JSON.stringify(row));\n  if (seen[fingerprint]) continue;\n  seen[fingerprint] = now;\n  fresh.push({ json: { ...row, _google_form_fingerprint: fingerprint } });\n}\n\nstate.google_form_seen = seen;\nreturn fresh;"
      },
      "id": "8f552727-6ad2-4b74-9aba-802451a77cc7",
      "name": "Only New Google Form Responses",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -680,
        -20
      ]
    },
    {
      "parameters": {
        "jsCode": "const row = $json;\nconst pick = (...keys) => {\n  for (const key of keys) {\n    if (row[key] !== undefined && row[key] !== null && String(row[key]).trim() !== '') return row[key];\n  }\n  return '';\n};\n\nreturn [{\n  json: {\n    full_name: pick('Full name', 'Full Name', 'full_name'),\n    business_email: pick('Business email', 'Email Address', 'business_email'),\n    company_name: pick('Company name', 'Company Name', 'company_name'),\n    business_type: pick('Business type', 'Business Type', 'business_type'),\n    service_needed: pick('What would you most like to improve?', 'Service needed', 'service_needed'),\n    monthly_lead_volume: pick('Approximate monthly lead volume', 'Monthly lead volume', 'monthly_lead_volume'),\n    budget_range: pick('Indicative implementation budget', 'Budget range', 'budget_range'),\n    timeline: pick('When would you like to improve this process?', 'Timeline', 'timeline'),\n    challenge: pick('Describe the bottleneck and its impact', 'Challenge', 'challenge'),\n    contact_consent: pick('May we contact you about this enquiry?', 'Contact consent', 'contact_consent'),\n    submitted_at: pick('Timestamp', 'submitted_at') || new Date().toISOString(),\n    _intake_source: 'GOOGLE_FORM'\n  }\n}];"
      },
      "id": "7bce99a7-20b2-44c2-88fb-e28a3b12d608",
      "name": "Map Google Form Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -820,
        -20
      ]
    },
    {
      "parameters": {
        "jsCode": "const source = $json;\n\nconst clean = (value) => String(value ?? '').trim();\nconst lead = {\n  full_name: clean(source.full_name),\n  business_email: clean(source.business_email).toLowerCase(),\n  company_name: clean(source.company_name),\n  business_type: clean(source.business_type),\n  service_needed: clean(source.service_needed),\n  monthly_lead_volume: clean(source.monthly_lead_volume),\n  budget_range: clean(source.budget_range),\n  timeline: clean(source.timeline),\n  challenge: clean(source.challenge),\n  contact_consent: clean(source.contact_consent),\n  submitted_at: source.submittedAt || source.submitted_at || new Date().toISOString()\n};\n\nconst required = ['full_name','business_email','company_name','business_type','service_needed','monthly_lead_volume','budget_range','timeline','challenge','contact_consent'];\nconst missing = required.filter((key) => !lead[key]);\nif (missing.length) throw new Error(`Missing required lead fields: ${missing.join(', ')}`);\nif (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(lead.business_email)) throw new Error('Invalid business email address');\nif (lead.challenge.length < 20) throw new Error('Challenge description must contain at least 20 characters');\n\nconst budgetScores = {'Under $500': 5, '$500-$2,000': 15, '$2,000-$5,000': 25, '$5,000+': 35, 'Not sure': 10};\nconst timelineScores = {'Immediately': 25, 'Within 30 days': 20, '1-3 months': 10, 'Exploring': 5};\nconst volumeScores = {'0-10': 5, '11-50': 12, '51-200': 20, '200+': 25};\nconst consentScore = lead.contact_consent === 'Yes' ? 15 : 0;\nconst rule_score = Math.min(100, (budgetScores[lead.budget_range] || 0) + (timelineScores[lead.timeline] || 0) + (volumeScores[lead.monthly_lead_volume] || 0) + consentScore);\nconst rule_tier = rule_score >= 70 ? 'HOT' : rule_score >= 40 ? 'WARM' : 'COLD';\n\nfunction fnv1a(text) {\n  let hash = 2166136261;\n  for (let i = 0; i < text.length; i++) {\n    hash ^= text.charCodeAt(i);\n    hash = Math.imul(hash, 16777619);\n  }\n  return (hash >>> 0).toString(16).padStart(8, '0');\n}\n\nreturn [{\n  json: {\n    ...lead,\n    lead_id: `lead_${fnv1a(`${lead.business_email}|${lead.company_name}|${lead.challenge}`)}`,\n    rule_score,\n    rule_tier,\n    validation_status: 'VALID',\n    source: source._intake_source || (source.formMode ? 'N8N_FORM' : 'MANUAL_TEST')\n  }\n}];"
      },
      "id": "98b1883c-5825-47c4-bcea-8ef9372c61f4",
      "name": "Validate, Normalize & Pre-Score",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -600,
        260
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=You are a careful B2B lead qualification assistant for an AI automation consultancy. Return JSON only and follow the connected output schema. Never invent facts. Analyse the lead's fit, urgency, pain, and safest next action. The rule-based score is context, not permission to contact the lead. If consent is No, choose MANUAL_REVIEW and do not draft outreach. Keep the reply helpful, specific, warm, and under 140 words. Do not promise results or quote prices.\n\nLEAD JSON:\n{{ JSON.stringify($json) }}",
        "hasOutputParser": true,
        "needsFallback": false,
        "messages": {
          "messageValues": [
            {
              "type": "SystemMessagePromptTemplate",
              "message": "You qualify business enquiries conservatively. Use only supplied evidence. Consequential actions always remain subject to human approval."
            }
          ]
        },
        "batching": {
          "batchSize": 1,
          "delayBetweenBatches": 0
        }
      },
      "id": "e9ca4e9c-d764-49ff-b61c-26223ac4338c",
      "name": "NVIDIA Lead Analysis",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.9,
      "position": [
        -300,
        260
      ],
      "retryOnFail": true,
      "maxTries": 2,
      "waitBetweenTries": 10000,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "model": "nvidia/llama-3.3-nemotron-super-49b-v1.5",
        "options": {
          "maxTokens": 900,
          "responseFormat": "json_object",
          "temperature": 0.2,
          "timeout": 120000,
          "maxRetries": 2,
          "topP": 1
        }
      },
      "id": "bc749010-4fb7-438b-acb0-597b39100211",
      "name": "NVIDIA Nemotron Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatNvidia",
      "typeVersion": 1,
      "position": [
        -390,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "const lead = $('Validate, Normalize & Pre-Score').item.json;\nconst rawError = $json.error ?? $json;\nconst message = String(rawError.message ?? rawError.description ?? 'NVIDIA analysis failed after retries').slice(0, 500);\nconst timestamp = new Date().toISOString();\nconst escapeHtml = (value) => String(value ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\nconst alert = `🚨 AI LEAD WORKFLOW ERROR\\n\\nWorkflow: ${$workflow.name}\\nExecution: ${$execution.id}\\nLead ID: ${lead.lead_id}\\nLead: ${lead.full_name} / ${lead.company_name}\\nFailed node: NVIDIA Lead Analysis\\nError: ${message}\\nTime: ${timestamp}\\n\\nThe lead was not sent for approval. Review the execution before retrying.`;\nreturn [{\n  json: {\n    lead_id: lead.lead_id,\n    processing_status: 'NVIDIA_FAILED',\n    failed_at: timestamp,\n    alert_text: escapeHtml(alert)\n  }\n}];"
      },
      "id": "b0ee7fe6-8e5e-49e2-a153-6eb0cb65a8dd",
      "name": "Prepare NVIDIA Failure Alert",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -40,
        650
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "sendMessage",
        "chatId": "OWNER_CHAT_ID",
        "text": "={{ $json.alert_text }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "d2e8ba35-4d50-4898-ae12-f2ad7d63a533",
      "name": "Notify NVIDIA Failure (Telegram)",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        220,
        650
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"additionalProperties\": false,\n  \"properties\": {\n    \"lead_tier\": {\"type\": \"string\", \"enum\": [\"HOT\", \"WARM\", \"COLD\"]},\n    \"fit_score\": {\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100},\n    \"urgency_score\": {\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100},\n    \"summary\": {\"type\": \"string\"},\n    \"pain_points\": {\"type\": \"array\", \"items\": {\"type\": \"string\"}, \"maxItems\": 5},\n    \"recommended_next_action\": {\"type\": \"string\", \"enum\": [\"BOOK_DISCOVERY_CALL\", \"SEND_PERSONALIZED_REPLY\", \"NURTURE\", \"MANUAL_REVIEW\"]},\n    \"reply_subject\": {\"type\": \"string\"},\n    \"reply_draft\": {\"type\": \"string\"},\n    \"confidence\": {\"type\": \"number\", \"minimum\": 0, \"maximum\": 1},\n    \"review_reason\": {\"type\": \"string\"}\n  },\n  \"required\": [\"lead_tier\", \"fit_score\", \"urgency_score\", \"summary\", \"pain_points\", \"recommended_next_action\", \"reply_subject\", \"reply_draft\", \"confidence\", \"review_reason\"]\n}",
        "autoFix": false
      },
      "id": "7c763c18-966a-4a28-8736-b2f0669d77b1",
      "name": "Validated Lead JSON",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -130,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "const lead = $('Validate, Normalize & Pre-Score').item.json;\nconst analysis = $json.output ?? $json;\nconst validTiers = ['HOT', 'WARM', 'COLD'];\nconst validActions = ['BOOK_DISCOVERY_CALL', 'SEND_PERSONALIZED_REPLY', 'NURTURE', 'MANUAL_REVIEW'];\nif (!validTiers.includes(analysis.lead_tier)) throw new Error('AI returned an invalid lead tier');\nif (!validActions.includes(analysis.recommended_next_action)) throw new Error('AI returned an invalid next action');\n\nconst scoreDelta = Math.abs(Number(analysis.fit_score) - Number(lead.rule_score));\nconst reviewReasons = [];\nif (lead.contact_consent !== 'Yes') reviewReasons.push('Contact consent was not granted');\nif (Number(analysis.confidence) < 0.75) reviewReasons.push('AI confidence is below 0.75');\nif (scoreDelta > 30) reviewReasons.push('AI score differs materially from deterministic score');\nif (analysis.recommended_next_action === 'MANUAL_REVIEW') reviewReasons.push('AI requested manual review');\nif (analysis.lead_tier === 'HOT') reviewReasons.push('High-value lead requires approval before outreach');\n\nreturn [{\n  json: {\n    ...lead,\n    ai_lead_tier: analysis.lead_tier,\n    ai_fit_score: Number(analysis.fit_score),\n    ai_urgency_score: Number(analysis.urgency_score),\n    ai_confidence: Number(analysis.confidence),\n    summary: analysis.summary,\n    pain_points: analysis.pain_points,\n    recommended_next_action: analysis.recommended_next_action,\n    reply_subject: analysis.reply_subject,\n    reply_draft: analysis.reply_draft,\n    review_required: reviewReasons.length > 0,\n    review_reason: [...reviewReasons, analysis.review_reason].filter(Boolean).join('; '),\n    processing_status: 'ANALYSED',\n    processed_at: new Date().toISOString()\n  }\n}];"
      },
      "id": "c0155091-0ad1-4761-8f45-b8d9c3b1936a",
      "name": "Apply Safety & Approval Rules",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        20,
        260
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "bf548d46-d8a4-47b2-ad8f-4c947b59a020",
              "leftValue": "={{ true }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "26b84d79-5032-42d3-95b1-02e8f1bf27ce",
      "name": "Human Review Required?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        290,
        260
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "a3bd1e29-3f73-4c28-bc63-ecc843b20ae1",
              "name": "processing_status",
              "value": "PENDING_HUMAN_REVIEW",
              "type": "string"
            },
            {
              "id": "41f74f5d-70d2-4e42-891e-7bb2713457fc",
              "name": "approval_decision",
              "value": "PENDING",
              "type": "string"
            },
            {
              "id": "24e7af50-823c-4fb4-a2a7-4fcfe24c8e7b",
              "name": "review_required",
              "value": true,
              "type": "boolean"
            },
            {
              "id": "3130ca46-cbf5-46cc-8c90-c02a2a7a922e",
              "name": "review_reason",
              "value": "={{ ['Owner review is required for every lead', $json.review_reason].filter(Boolean).join('; ') }}",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "12ac7807-c0e3-4539-96c1-74f2f83c2c6c",
      "name": "Queue for Human Review",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        560,
        170
      ]
    },
    {
      "parameters": {
        "jsCode": "const lead = $json;\nconst now = new Date().toISOString();\nconst needsReview = lead.review_required === true;\nconst painPoints = Array.isArray(lead.pain_points) ? lead.pain_points.join(' | ') : String(lead.pain_points || '');\nconst escapeHtml = (value) => String(value ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\nconst reviewText = `🧭 LEAD REVIEW\\n\\nLead: ${lead.full_name}\\nCompany: ${lead.company_name}\\nEmail: ${lead.business_email}\\nSource: ${lead.source}\\n\\nScores\\n• AI fit: ${lead.ai_fit_score}/100 (${lead.ai_lead_tier})\\n• Urgency: ${lead.ai_urgency_score}/100\\n• Rule score: ${lead.rule_score}/100\\n• Confidence: ${Math.round(Number(lead.ai_confidence || 0) * 100)}%\\n\\nSummary\\n${lead.summary}\\n\\nPain points\\n${painPoints}\\n\\nReview reason\\n${lead.review_reason}\\n\\nProposed reply\\nSubject: ${lead.reply_subject}\\n${lead.reply_draft}\\n\\nChoose an action below.`;\nreturn [{ json: {\n  created_at: now,\n  lead_id: lead.lead_id,\n  submitted_at: lead.submitted_at,\n  full_name: lead.full_name,\n  business_email: lead.business_email,\n  company_name: lead.company_name,\n  business_type: lead.business_type,\n  service_needed: lead.service_needed,\n  source: lead.source,\n  rule_score: lead.rule_score,\n  rule_tier: lead.rule_tier,\n  ai_fit_score: lead.ai_fit_score,\n  ai_lead_tier: lead.ai_lead_tier,\n  ai_urgency_score: lead.ai_urgency_score,\n  ai_confidence: lead.ai_confidence,\n  summary: lead.summary,\n  pain_points: painPoints,\n  review_reason: lead.review_reason,\n  reply_subject: lead.reply_subject,\n  proposed_reply: lead.reply_draft,\n  final_reply: '',\n  approval_action: needsReview ? 'PENDING' : 'NOT_REQUIRED',\n  approval_status: needsReview ? 'PENDING' : 'NOT_REQUIRED',\n  telegram_context: '',\n  email_delivery: JSON.stringify({ provider: 'SMTP', status: 'NOT_SENT' }),\n  last_updated_at: now,\n  telegram_review_text: escapeHtml(reviewText)\n} }];"
      },
      "id": "52c61cc9-acde-41c4-9663-d4dcadfcff63",
      "name": "Build Workflow Report Row",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        820,
        260
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "appendOrUpdate",
        "documentId": {
          "mode": "id",
          "value": "SPREADSHEET_ID"
        },
        "sheetName": {
          "mode": "id",
          "value": "REPORT_SHEET_ID"
        },
        "dataMode": "autoMapInputData",
        "columnToMatchOn": "lead_id",
        "options": {
          "handlingExtraData": "ignoreIt"
        }
      },
      "id": "91cd104b-e334-4909-904f-2035583da520",
      "name": "Upsert Workflow Report",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 3,
      "position": [
        1080,
        260
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "b12d01b0-8c9f-4d5f-b6c2-2f8779efcb51",
              "leftValue": "={{ $('Build Workflow Report Row').item.json.approval_status }}",
              "rightValue": "PENDING",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "b8e45b38-b335-4f66-a42e-fea72710e054",
      "name": "Needs Telegram Review?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1320,
        260
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "sendMessage",
        "chatId": "OWNER_CHAT_ID",
        "text": "={{ $('Build Workflow Report Row').item.json.telegram_review_text }}",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "✅ Approve",
                    "additionalFields": {
                      "callback_data": "={{ 'approve|' + $('Build Workflow Report Row').item.json.lead_id }}"
                    }
                  },
                  {
                    "text": "✏️ Edit reply",
                    "additionalFields": {
                      "callback_data": "={{ 'edit|' + $('Build Workflow Report Row').item.json.lead_id }}"
                    }
                  }
                ]
              }
            },
            {
              "row": {
                "buttons": [
                  {
                    "text": "❌ Reject",
                    "additionalFields": {
                      "callback_data": "={{ 'reject|' + $('Build Workflow Report Row').item.json.lead_id }}"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "08cbfc39-b264-4298-aa0c-f2b931dfb234",
      "name": "Send Telegram Review Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1560,
        170
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "jsCode": "const report = $('Build Workflow Report Row').item.json;\nconst response = $json.result ?? $json;\nreturn [{ json: { ...report, telegram_context: String(response.message_id ?? ''), last_updated_at: new Date().toISOString() } }];"
      },
      "id": "5d6ed537-8604-43b9-8b38-c9c9a098fbee",
      "name": "Capture Review Message Context",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1800,
        170
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "appendOrUpdate",
        "documentId": {
          "mode": "id",
          "value": "SPREADSHEET_ID"
        },
        "sheetName": {
          "mode": "id",
          "value": "REPORT_SHEET_ID"
        },
        "dataMode": "autoMapInputData",
        "columnToMatchOn": "lead_id",
        "options": {
          "handlingExtraData": "ignoreIt"
        }
      },
      "id": "50dc78e9-81bc-44ad-af7e-e049054a0820",
      "name": "Save Review Message Context",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 3,
      "position": [
        2040,
        170
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "6b681c51-f64c-40e1-ab70-b47e93ac1df4",
              "name": "processing_status",
              "value": "READY_FOR_FOLLOW_UP",
              "type": "string"
            },
            {
              "id": "8fc91451-0195-4c1c-8f67-82a469680b16",
              "name": "approval_decision",
              "value": "NOT_REQUIRED_FOR_LOW_RISK_DRAFT",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      },
      "id": "b29e6856-a48b-4e52-943c-b88fd1ac5369",
      "name": "Ready for Follow-Up",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        560,
        350
      ]
    },
    {
      "parameters": {
        "content": "## Production lead intake\n\nThis workflow validates intake, scores the lead, uses NVIDIA Nemotron for structured analysis, writes a durable Workflow Report row, and sends a Telegram-native review message. It does not wait: new leads continue processing independently.\n\nThe separate Telegram Approval & Email Dispatcher handles Approve, Edit reply, Reject, SMTP/Gmail delivery, and final report updates.",
        "height": 330,
        "width": 410,
        "color": 5
      },
      "id": "64af6081-3695-47c8-8644-cda788df6fd0",
      "name": "MVP Scope",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1130,
        -260
      ]
    },
    {
      "parameters": {
        "content": "## Safety and approval gates\n\nHuman review is required when:\n- the lead is classified HOT;\n- consent is not Yes;\n- AI confidence is below 0.75;\n- deterministic and AI scores differ by more than 30 points; or\n- the model requests manual review.\n\nTelegram uses inline callback buttons. Only the connected owner chat can authorize email. Pending records expire after 24 hours in the dispatcher.",
        "height": 330,
        "width": 390,
        "color": 3
      },
      "id": "bf685ab1-fdc0-4249-a845-b53aa1bdd1d4",
      "name": "Safety Rules",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        220,
        -260
      ]
    },
    {
      "parameters": {
        "content": "## Google Form intake\n\n1. Create the form using the field titles documented in README.md.\n2. In Google Forms, link responses to a Google Sheet.\n3. Connect Google Sheets Trigger OAuth2 in n8n.\n4. Select the response spreadsheet and the `Form Responses 1` sheet.\n5. Enable the trigger after a controlled test.\n\nThe mapper accepts the documented labels and converts them to the workflow's canonical field names.",
        "height": 330,
        "width": 410,
        "color": 4
      },
      "id": "f4fb1c10-d36a-452c-b958-0dcc23887687",
      "name": "Google Form Setup",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1160,
        -410
      ]
    },
    {
      "parameters": {
        "content": "## Telegram-native approval\n\nThe review message provides Approve, Edit reply, and Reject buttons without opening a browser.\n\nApprove sends the proposed reply. Edit reply prompts the owner to reply directly to the bot's draft; that edited message is sent. Reject records the decision without contacting the lead. The dispatcher uses SMTP by default and includes a configured Gmail alternative.",
        "height": 350,
        "width": 430,
        "color": 6
      },
      "id": "c9710716-0cb6-458d-b8d3-1c3c5a3c080d",
      "name": "Telegram Setup",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        760,
        -350
      ]
    }
  ],
  "connections": {
    "Manual Test Trigger": {
      "main": [
        [
          {
            "node": "Sample High-Intent Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample High-Intent Lead": {
      "main": [
        [
          {
            "node": "Validate, Normalize & Pre-Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Intake Form": {
      "main": [
        [
          {
            "node": "Validate, Normalize & Pre-Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Google Form Responses": {
      "main": [
        [
          {
            "node": "Read Google Form Response Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Google Form Response Sheet": {
      "main": [
        [
          {
            "node": "Only New Google Form Responses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only New Google Form Responses": {
      "main": [
        [
          {
            "node": "Map Google Form Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Google Form Response": {
      "main": [
        [
          {
            "node": "Validate, Normalize & Pre-Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate, Normalize & Pre-Score": {
      "main": [
        [
          {
            "node": "NVIDIA Lead Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NVIDIA Nemotron Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "NVIDIA Lead Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Validated Lead JSON": {
      "ai_outputParser": [
        [
          {
            "node": "NVIDIA Lead Analysis",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "NVIDIA Lead Analysis": {
      "main": [
        [
          {
            "node": "Apply Safety & Approval Rules",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare NVIDIA Failure Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare NVIDIA Failure Alert": {
      "main": [
        [
          {
            "node": "Notify NVIDIA Failure (Telegram)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Safety & Approval Rules": {
      "main": [
        [
          {
            "node": "Human Review Required?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Human Review Required?": {
      "main": [
        [
          {
            "node": "Queue for Human Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Ready for Follow-Up",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Queue for Human Review": {
      "main": [
        [
          {
            "node": "Build Workflow Report Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ready for Follow-Up": {
      "main": [
        [
          {
            "node": "Build Workflow Report Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Workflow Report Row": {
      "main": [
        [
          {
            "node": "Upsert Workflow Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Workflow Report": {
      "main": [
        [
          {
            "node": "Needs Telegram Review?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Needs Telegram Review?": {
      "main": [
        [
          {
            "node": "Send Telegram Review Message",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Send Telegram Review Message": {
      "main": [
        [
          {
            "node": "Capture Review Message Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Capture Review Message Context": {
      "main": [
        [
          {
            "node": "Save Review Message Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1",
    "timezone": "UTC",
    "saveManualExecutions": true,
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all",
    "executionTimeout": 600,
    "errorWorkflow": "AILeadErrorHandlerPublic"
  },
  "active": false,
  "tags": []
}
