This workflow corresponds to n8n.io template #15621 — we link there as the canonical source.
This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "jPodSrGZLNPzZ2cy",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI WhatsApp Sales Closer Bot",
"tags": [
{
"id": "DiwTzDkTaFSX5bEX",
"name": "recruitment",
"createdAt": "2026-05-11T13:01:00.870Z",
"updatedAt": "2026-05-11T13:01:00.870Z"
},
{
"id": "z6mxJFPmp5Jq0Lnu",
"name": "whatsapp",
"createdAt": "2026-05-11T13:01:00.955Z",
"updatedAt": "2026-05-11T13:01:00.955Z"
},
{
"id": "s4xffeURdnx7oinT",
"name": "hr-automation",
"createdAt": "2026-05-11T13:01:00.986Z",
"updatedAt": "2026-05-11T13:01:00.986Z"
},
{
"id": "fmYbvcTTTlbTp6aj",
"name": "ai-powered",
"createdAt": "2026-05-11T13:01:00.986Z",
"updatedAt": "2026-05-11T13:01:00.986Z"
},
{
"id": "aVLSLG3iHePWjrQE",
"name": "sales",
"createdAt": "2026-05-11T13:05:19.233Z",
"updatedAt": "2026-05-11T13:05:19.233Z"
},
{
"id": "F89H8wlybgmonk5J",
"name": "ai-bot",
"createdAt": "2026-05-11T13:05:19.248Z",
"updatedAt": "2026-05-11T13:05:19.248Z"
},
{
"id": "9lOfmvXjZotSSkKk",
"name": "lead-qualification",
"createdAt": "2026-05-11T13:05:19.238Z",
"updatedAt": "2026-05-11T13:05:19.238Z"
}
],
"nodes": [
{
"id": "d3fbe3c4-2541-4591-af90-bf54a3b6b13a",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 980,
"height": 960,
"content": "## AI WhatsApp Sales Closer Bot\n\nThis workflow automatically qualifies leads, answers FAQs, and books sales calls via WhatsApp using AI-powered conversation logic.\n\n### Who's it for\n\u2022 Sales teams handling high inbound message volume\n\u2022 SaaS / service businesses using WhatsApp for outreach\n\u2022 Agencies automating lead qualification pipelines\n\n### How it works\n1. WhatsApp message arrives via webhook (Twilio/Meta Cloud API)\n2. Conversation state is loaded from memory/sheet\n3. AI qualifies lead (Budget, Authority, Need, Timeline)\n4. Bot answers FAQs automatically\n5. Qualified leads get calendar booking link / slot picker\n6. All activity is logged to Google Sheets CRM\n7. Hot leads trigger Slack/email alert to sales rep\n\n### How to set up\n1. Import this workflow into n8n\n2. Set up credentials: Twilio/Meta WhatsApp, Google Sheets, Google Calendar, OpenAI\n3. Update YOUR_SHEET_ID and YOUR_CALENDAR_ID placeholders\n4. Update your product FAQ knowledge base in the AI node\n5. Activate workflow and configure your WhatsApp webhook URL\n\n### Requirements\n\u2022 Twilio WhatsApp API or Meta Cloud API\n\u2022 Google Sheets (CRM tracker)\n\u2022 Google Calendar or Calendly\n\u2022 OpenAI API key\n\u2022 n8n instance (cloud or self-hosted)\n\n### Customization\n\u2022 Edit BANT scoring thresholds in JS node\n\u2022 Update FAQ knowledge base in AI system prompt\n\u2022 Modify booking time slots in calendar node\n\u2022 Adjust Slack alert conditions"
},
"typeVersion": 1
},
{
"id": "3f408032-4ab3-4d60-8a8a-cfc8ea7d193c",
"name": "Sticky Note - Intake",
"type": "n8n-nodes-base.stickyNote",
"position": [
1104,
240
],
"parameters": {
"color": 4,
"width": 780,
"height": 520,
"content": "## 1. Intake & State Load"
},
"typeVersion": 1
},
{
"id": "e7c28836-9c41-41f8-a458-2431470eb6bb",
"name": "Sticky Note - Intent",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
160
],
"parameters": {
"color": 3,
"width": 852,
"height": 620,
"content": "## 2. Intent Detection & Lead Scoring"
},
"typeVersion": 1
},
{
"id": "29201094-f5ff-4721-a097-e0d0c94306ab",
"name": "Sticky Note - AI Response",
"type": "n8n-nodes-base.stickyNote",
"position": [
2832,
160
],
"parameters": {
"color": 4,
"width": 820,
"height": 640,
"content": "## 3. AI Response & Booking"
},
"typeVersion": 1
},
{
"id": "10573369-9b91-4bbb-bf6c-3c7b34cad857",
"name": "Sticky Note - Send Track",
"type": "n8n-nodes-base.stickyNote",
"position": [
3712,
208
],
"parameters": {
"color": 3,
"width": 1012,
"height": 580,
"content": "## 4. Send & Track"
},
"typeVersion": 1
},
{
"id": "777ea74f-90b7-4629-82c0-800a60d6041c",
"name": "Webhook - WhatsApp Inbound",
"type": "n8n-nodes-base.webhook",
"position": [
1264,
400
],
"parameters": {
"path": "whatsapp-inbound",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 1.1
},
{
"id": "47ce6d03-f271-4a6a-89bd-6460930841df",
"name": "Normalize Message Fields",
"type": "n8n-nodes-base.set",
"position": [
1504,
400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"name": "phoneNumber",
"type": "string",
"value": "={{ $json.From || $json.body?.From || $json.WaId || $json.contacts?.[0]?.wa_id }}"
},
{
"name": "incomingMessage",
"type": "string",
"value": "={{ $json.Body || $json.body?.Body || $json.messages?.[0]?.text?.body || $json.body }}"
},
{
"name": "messageId",
"type": "string",
"value": "={{ $json.MessageSid || $json.messages?.[0]?.id || $now.toMillis().toString() }}"
},
{
"name": "senderName",
"type": "string",
"value": "={{ $json.ProfileName || $json.contacts?.[0]?.profile?.name || 'Prospect' }}"
},
{
"name": "timestamp",
"type": "string",
"value": "={{ $now.toISO() }}"
},
{
"name": "channel",
"type": "string",
"value": "WhatsApp"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f94351b4-644a-44d7-8863-4b5f2391ee8a",
"name": "Load Lead State from Sheet",
"type": "n8n-nodes-base.httpRequest",
"position": [
1728,
400
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/Leads!A:J?majorDimension=ROWS",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "4c66e12a-940a-4c14-95d0-9acda08cb7ef",
"name": "JS - Resolve Lead State",
"type": "n8n-nodes-base.code",
"position": [
1952,
400
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Find existing lead record by phone number\nconst phone = $('Normalize Message Fields').item.json.phoneNumber;\nconst sheetData = $input.item.json;\n\nlet existingLead = null;\nlet conversationStage = 'new';\nlet bantScore = { budget: false, authority: false, need: false, timeline: false };\nlet conversationHistory = [];\nlet leadScore = 0;\n\nif (sheetData.values && sheetData.values.length > 1) {\n const rows = sheetData.values.slice(1); // skip header\n const found = rows.find(row => row[1] === phone);\n if (found) {\n existingLead = {\n id: found[0],\n phone: found[1],\n name: found[2],\n stage: found[3] || 'new',\n leadScore: parseInt(found[4]) || 0,\n bantBudget: found[5] === 'TRUE',\n bantAuthority: found[6] === 'TRUE',\n bantNeed: found[7] === 'TRUE',\n bantTimeline: found[8] === 'TRUE',\n conversationHistory: found[9] ? JSON.parse(found[9]) : []\n };\n conversationStage = existingLead.stage;\n bantScore = {\n budget: existingLead.bantBudget,\n authority: existingLead.bantAuthority,\n need: existingLead.bantNeed,\n timeline: existingLead.bantTimeline\n };\n conversationHistory = existingLead.conversationHistory;\n leadScore = existingLead.leadScore;\n }\n}\n\nconst message = $('Normalize Message Fields').item.json.incomingMessage;\n\n// Add incoming message to history\nconversationHistory.push({\n role: 'user',\n content: message,\n ts: new Date().toISOString()\n});\n\n// Cap history at last 20 messages to stay within token limits\nif (conversationHistory.length > 20) {\n conversationHistory = conversationHistory.slice(-20);\n}\n\nreturn {\n json: {\n ...$('Normalize Message Fields').item.json,\n isNewLead: !existingLead,\n conversationStage,\n bantScore,\n leadScore,\n conversationHistory,\n existingLead\n }\n};"
},
"typeVersion": 2
},
{
"id": "e03347d4-08b6-4693-a1eb-6f36ddeb0787",
"name": "Python - Detect Intent",
"type": "n8n-nodes-base.code",
"position": [
2192,
400
],
"parameters": {
"mode": "runOnceForEachItem",
"language": "python"
},
"typeVersion": 2
},
{
"id": "ce92a186-75c4-4c80-86ed-5779b7534fd5",
"name": "Route - Book Call?",
"type": "n8n-nodes-base.filter",
"position": [
2432,
304
],
"parameters": {
"options": {},
"conditions": {
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "book_call"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "7b92ceb9-885a-4da0-a3ab-69904b165450",
"name": "Route - FAQ?",
"type": "n8n-nodes-base.filter",
"position": [
2432,
464
],
"parameters": {
"options": {},
"conditions": {
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "faq"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "5cab22e2-d764-4480-829f-7bc0eb14a69e",
"name": "Route - Hot Lead?",
"type": "n8n-nodes-base.filter",
"position": [
2432,
624
],
"parameters": {
"options": {},
"conditions": {
"conditions": [
{
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.leadScore }}",
"rightValue": 75
}
]
}
},
"typeVersion": 2.2
},
{
"id": "53406cc1-40b3-4c52-b9f6-0d0b631cd4a2",
"name": "Wait - Rate Limit",
"type": "n8n-nodes-base.wait",
"position": [
2672,
464
],
"parameters": {},
"typeVersion": 1
},
{
"id": "4e49f5d6-ad28-40b1-9fcb-ed4a5a060d41",
"name": "AI - Sales Closer Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
3088,
400
],
"parameters": {
"text": "={{ JSON.stringify($json.conversationHistory.map(m => ({role: m.role, content: m.content}))) }}",
"options": {
"systemMessage": "=You are Alex, a friendly and professional sales assistant for [YOUR COMPANY NAME]. Your goal is to qualify leads using the BANT framework, answer product questions, and book sales calls.\n\n## Your Personality\n- Warm, conversational, and consultative \u2014 never pushy\n- Use the prospect's first name when known\n- Keep messages short (under 80 words) \u2014 this is WhatsApp, not email\n- Use line breaks and emojis sparingly for readability\n- Never use more than 3 emojis per message\n\n## BANT Qualification (collect one at a time, naturally)\n- **Budget**: Do they have the budget? ($500\u2013$5000/mo range)\n- **Authority**: Are they the decision maker?\n- **Need**: What problem are they solving?\n- **Timeline**: When do they want to start?\n\nCurrent BANT status: {{ JSON.stringify($json.bantScore) }}\nCurrent lead score: {{ $json.leadScore }}/100\nConversation stage: {{ $json.conversationStage }}\nProspect name: {{ $json.senderName }}\n\n## FAQ Knowledge Base\n**What does your product do?**\nWe help [TARGET PERSONA] achieve [OUTCOME] through [METHOD]. Typical clients see [RESULT] within [TIMEFRAME].\n\n**How much does it cost?**\nOur plans range from $X to $Y/month depending on team size and features. We also offer custom enterprise pricing.\n\n**Do you offer a free trial?**\nYes! We offer a 14-day free trial, no credit card required.\n\n**How long does onboarding take?**\nMost clients are fully onboarded within 1\u20132 weeks. We provide dedicated support.\n\n**What integrations do you support?**\nWe integrate with Salesforce, HubSpot, Slack, Google Workspace, and 50+ tools via Zapier/n8n.\n\n**Is my data secure?**\nAbsolutely. We are SOC 2 Type II certified and GDPR compliant.\n\n## Booking a Call\nWhen a lead is qualified (score \u2265 75) or asks to book, say:\n\"Great! I'd love to connect you with our team. Here's a link to pick a time that works for you: [CALENDLY_LINK]\"\n\n## Guardrails\n- Never make up pricing or features not listed above\n- If you don't know the answer, say: \"Great question! Let me connect you with a specialist who can answer that.\"\n- Never discuss competitors\n- If the user seems frustrated, offer to escalate to a human immediately"
},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "a171ada3-410b-44e1-b019-6026dbe0c554",
"name": "OpenAI GPT-4.1-mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
3008,
608
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {
"temperature": 0.7
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "d0f78a88-a412-4eb8-aa09-926d3207606b",
"name": "JS - Score & Format Reply",
"type": "n8n-nodes-base.code",
"position": [
3424,
400
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\nconst aiResponse = item.output || item.response || item.text || 'Thank you for reaching out! How can I help you today?';\n\n// Update BANT score based on AI output hints\nconst bantScore = item.bantScore || { budget: false, authority: false, need: false, timeline: false };\nconst responseLower = aiResponse.toLowerCase();\n\n// Simple keyword-based BANT detection (AI handles the nuanced conversation)\nif (responseLower.includes('[budget_confirmed]')) bantScore.budget = true;\nif (responseLower.includes('[authority_confirmed]')) bantScore.authority = true;\nif (responseLower.includes('[need_confirmed]')) bantScore.need = true;\nif (responseLower.includes('[timeline_confirmed]')) bantScore.timeline = true;\n\n// Calculate lead score (25 points per BANT element)\nconst newLeadScore = Object.values(bantScore).filter(Boolean).length * 25;\n\n// Determine conversation stage\nlet stage = item.conversationStage || 'new';\nif (newLeadScore === 0) stage = 'awareness';\nelse if (newLeadScore <= 25) stage = 'qualifying';\nelse if (newLeadScore <= 75) stage = 'engaged';\nelse stage = 'hot_lead';\n\n// Add AI reply to history\nconst updatedHistory = [...(item.conversationHistory || []), {\n role: 'assistant',\n content: aiResponse,\n ts: new Date().toISOString()\n}];\n\n// Clean reply text (remove internal tags)\nconst cleanReply = aiResponse\n .replace(/\\[budget_confirmed\\]/gi, '')\n .replace(/\\[authority_confirmed\\]/gi, '')\n .replace(/\\[need_confirmed\\]/gi, '')\n .replace(/\\[timeline_confirmed\\]/gi, '')\n .trim();\n\nreturn {\n json: {\n ...item,\n replyText: cleanReply,\n bantScore,\n leadScore: newLeadScore,\n conversationStage: stage,\n conversationHistory: updatedHistory,\n updatedAt: new Date().toISOString().split('T')[0]\n }\n};"
},
"typeVersion": 2
},
{
"id": "54fa865e-c43c-4e58-a802-738748ac320d",
"name": "Send WhatsApp Reply (Twilio)",
"type": "n8n-nodes-base.httpRequest",
"position": [
3760,
320
],
"parameters": {
"url": "https://api.twilio.com/2010-04-01/Accounts/YOUR_TWILIO_ACCOUNT_SID/Messages.json",
"method": "POST",
"options": {},
"sendBody": true,
"specifyBody": "formUrlEncoded",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "twilioApi"
},
"credentials": {
"twilioApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "07b30862-a4da-4689-8b2c-c9143b59e612",
"name": "Upsert Lead in Google Sheets",
"type": "n8n-nodes-base.httpRequest",
"position": [
3776,
576
],
"parameters": {
"url": "https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/Leads!A1:append?valueInputOption=USER_ENTERED&insertDataOption=INSERT_ROWS",
"method": "POST",
"options": {},
"jsonBody": "={\n \"values\": [[\n \"{{ $json.isNewLead ? $now.toMillis().toString() : ($json.existingLead?.id || $now.toMillis().toString()) }}\",\n \"{{ $json.phoneNumber }}\",\n \"{{ $json.senderName }}\",\n \"{{ $json.conversationStage }}\",\n \"{{ $json.leadScore }}\",\n \"{{ $json.bantScore?.budget }}\",\n \"{{ $json.bantScore?.authority }}\",\n \"{{ $json.bantScore?.need }}\",\n \"{{ $json.bantScore?.timeline }}\",\n {{ JSON.stringify(JSON.stringify($json.conversationHistory)) }},\n \"{{ $json.updatedAt }}\",\n \"{{ $json.channel }}\"\n ]]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "c0fcac11-cafa-416b-9272-f582bbd618cc",
"name": "Check - Hot Lead Alert?",
"type": "n8n-nodes-base.filter",
"position": [
4000,
400
],
"parameters": {
"options": {},
"conditions": {
"conditions": [
{
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.leadScore }}",
"rightValue": 75
}
]
}
},
"typeVersion": 2.2
},
{
"id": "191427d9-bb14-42a9-8ed2-b9be6bbd6c99",
"name": "Slack - Hot Lead Alert",
"type": "n8n-nodes-base.httpRequest",
"position": [
4240,
320
],
"parameters": {
"url": "https://slack.com/api/chat.postMessage",
"method": "POST",
"options": {},
"jsonBody": "={\n \"channel\": \"#sales-alerts\",\n \"text\": \"\ud83d\udd25 *Hot Lead Alert!*\",\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"\ud83d\udd25 *Hot Lead Qualified!*\\n*Name:* {{ $json.senderName }}\\n*Phone:* {{ $json.phoneNumber }}\\n*Lead Score:* {{ $json.leadScore }}/100\\n*Stage:* {{ $json.conversationStage }}\\n*BANT:* Budget={{ $json.bantScore?.budget }} | Authority={{ $json.bantScore?.authority }} | Need={{ $json.bantScore?.need }} | Timeline={{ $json.bantScore?.timeline }}\\n\\n_Last message:_ {{ $json.incomingMessage?.substring(0, 200) }}\"\n }\n },\n {\n \"type\": \"actions\",\n \"elements\": [\n {\n \"type\": \"button\",\n \"text\": { \"type\": \"plain_text\", \"text\": \"View in CRM\" },\n \"url\": \"https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID\",\n \"style\": \"primary\"\n }\n ]\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "slackApi"
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "7fcdb351-5a31-43aa-b3d7-0eea271e5dec",
"name": "Book Call in Google Calendar",
"type": "n8n-nodes-base.httpRequest",
"position": [
4240,
480
],
"parameters": {
"url": "https://www.googleapis.com/calendar/v3/calendars/YOUR_CALENDAR_ID/events",
"method": "POST",
"options": {},
"jsonBody": "={\n \"summary\": \"Sales Call - {{ $json.senderName }}\",\n \"description\": \"WhatsApp Lead\\nPhone: {{ $json.phoneNumber }}\\nLead Score: {{ $json.leadScore }}/100\\nBANT: Budget={{ $json.bantScore?.budget }}, Authority={{ $json.bantScore?.authority }}, Need={{ $json.bantScore?.need }}, Timeline={{ $json.bantScore?.timeline }}\\n\\nConversation Summary: Auto-booked via WhatsApp Sales Bot\",\n \"start\": {\n \"dateTime\": \"{{ $now.plus({days: 2}).startOf('day').plus({hours: 10}).toISO() }}\",\n \"timeZone\": \"America/New_York\"\n },\n \"end\": {\n \"dateTime\": \"{{ $now.plus({days: 2}).startOf('day').plus({hours: 10, minutes: 30}).toISO() }}\",\n \"timeZone\": \"America/New_York\"\n },\n \"attendees\": [],\n \"reminders\": {\n \"useDefault\": false,\n \"overrides\": [\n { \"method\": \"email\", \"minutes\": 1440 },\n { \"method\": \"popup\", \"minutes\": 30 }\n ]\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleCalendarOAuth2Api"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "932736bb-ae5c-4b72-a08d-e207840c7483",
"name": "Webhook Response - 200 OK",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
4480,
400
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ status: 'ok', messageId: $json.messageId }) }}"
},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "a3e24126-aa3b-4aaa-a5ad-ca1d0f404091",
"connections": {
"Route - FAQ?": {
"main": [
[
{
"node": "Wait - Rate Limit",
"type": "main",
"index": 0
}
]
]
},
"Route - Hot Lead?": {
"main": [
[
{
"node": "Wait - Rate Limit",
"type": "main",
"index": 0
}
]
]
},
"Wait - Rate Limit": {
"main": [
[
{
"node": "AI - Sales Closer Agent",
"type": "main",
"index": 0
}
]
]
},
"Route - Book Call?": {
"main": [
[
{
"node": "Wait - Rate Limit",
"type": "main",
"index": 0
}
]
]
},
"OpenAI GPT-4.1-mini": {
"ai_languageModel": [
[
{
"node": "AI - Sales Closer Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Python - Detect Intent": {
"main": [
[
{
"node": "Route - Book Call?",
"type": "main",
"index": 0
},
{
"node": "Route - FAQ?",
"type": "main",
"index": 0
},
{
"node": "Route - Hot Lead?",
"type": "main",
"index": 0
}
]
]
},
"Slack - Hot Lead Alert": {
"main": [
[
{
"node": "Webhook Response - 200 OK",
"type": "main",
"index": 0
}
]
]
},
"AI - Sales Closer Agent": {
"main": [
[
{
"node": "JS - Score & Format Reply",
"type": "main",
"index": 0
}
]
]
},
"Check - Hot Lead Alert?": {
"main": [
[
{
"node": "Slack - Hot Lead Alert",
"type": "main",
"index": 0
},
{
"node": "Book Call in Google Calendar",
"type": "main",
"index": 0
}
]
]
},
"JS - Resolve Lead State": {
"main": [
[
{
"node": "Python - Detect Intent",
"type": "main",
"index": 0
}
]
]
},
"Normalize Message Fields": {
"main": [
[
{
"node": "Load Lead State from Sheet",
"type": "main",
"index": 0
}
]
]
},
"JS - Score & Format Reply": {
"main": [
[
{
"node": "Send WhatsApp Reply (Twilio)",
"type": "main",
"index": 0
},
{
"node": "Upsert Lead in Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Load Lead State from Sheet": {
"main": [
[
{
"node": "JS - Resolve Lead State",
"type": "main",
"index": 0
}
]
]
},
"Webhook - WhatsApp Inbound": {
"main": [
[
{
"node": "Normalize Message Fields",
"type": "main",
"index": 0
}
]
]
},
"Book Call in Google Calendar": {
"main": [
[
{
"node": "Webhook Response - 200 OK",
"type": "main",
"index": 0
}
]
]
},
"Send WhatsApp Reply (Twilio)": {
"main": [
[
{
"node": "Check - Hot Lead Alert?",
"type": "main",
"index": 0
}
]
]
},
"Upsert Lead in Google Sheets": {
"main": [
[
{
"node": "Check - Hot Lead Alert?",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleCalendarOAuth2ApigoogleSheetsOAuth2ApiopenAiApislackApitwilioApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically qualifies leads, answers FAQs, and books sales calls via WhatsApp using AI-powered conversation logic.
Source: https://n8n.io/workflows/15621/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
⏺ 🚀 How it works
L&D_AgentsAI_ATIVO. Uses httpRequest, agent, googleCalendarTool, toolSerpApi. Webhook trigger; 93 nodes.
CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.
Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La