This workflow corresponds to n8n.io template #12956 — we link there as the canonical source.
This workflow follows the Apifyn8N Nodes Apify → Google Sheets 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": "So1xTD1DaxSeHILl",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI_Local_Business_Receptionist_Agent_Generator_v2",
"tags": [],
"nodes": [
{
"id": "4db698dc-7ecd-4248-8e82-c4d4676c0a8e",
"name": "Generate Agent Messages",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"position": [
-1360,
64
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-20250514",
"cachedResultName": "claude-sonnet-4-20250514"
},
"options": {
"system": "You are an expert in creating messages for professional AI voice agents.\nYou must generate 4 distinct messages for a voice reception agent:\n1. **system_message**: Complete system prompt (300-500 words)\n2. **firstMessage**: Welcome greeting (1 short sentence)\n3. **voicemailMessage**: Voicemail message (1-4 words MAX)\n4. **endCallMessage**: End call message (1-4 words MAX)\n\nSTRICT RULES:\n- Formal and professional tone\n- No emojis, no familiarity\n- Perfect English\n- Short messages (except system_message)\n- No line breaks in your outputs\n\nReply ONLY in strict JSON format."
},
"messages": {
"values": [
{
"content": "=={{ JSON.stringify($json) }}\n\nHAIR SALON / BARBER:\n\n'HAIR SALON TEMPLATE:\\n\\n' +\n'SYSTEM MESSAGE:\\n' +\n'You are the receptionist at ' + $('Business Parameters').item.json[\"Business Name\"] + ', ' + $('Scrape Local Businesses').item.json.categoryName + ', located at ' + $('Business Parameters').item.json[\"Street\"] + ', ' + $('Business Parameters').item.json[\"City\"] + '.\\n\\n' +\n'ROLE: Handle calls, schedule appointments, provide service information.\\n\\n' +\n'STANDARD SERVICES:\\n' +\n'- Men\\'s/Women\\'s haircuts\\n' +\n'- Hair coloring\\n' +\n'- Hair treatments\\n' +\n'- Beard grooming (if barber)\\n\\n' +\n'APPOINTMENT BOOKING:\\n' +\n'1. Ask for: first name, service type, preferred date\\n' +\n'2. Offer 2 available time slots\\n' +\n'3. Confirm phone number\\n\\n' +\n'HOURS:\\n' + JSON.stringify($('Business Parameters').item.json[\"Opening Hours\"]) + '\\n\\n' +\n'RULES:\\n' +\n'- Short responses (2-3 sentences max)\\n' +\n'- One question at a time\\n' +\n'- Wait for customer response\\n' +\n'- If complex request: offer callback\\n' +\n'- Stay professional\\n\\n' +\n'FIRST MESSAGE: \"Hello, ' + $('Business Parameters').item.json[\"Business Name\"] + '. How may I help you?\"\\n\\n' +\n'VOICEMAIL MESSAGE: \"Hello, you\\'ve reached ' + $('Business Parameters').item.json[\"Business Name\"] + '. We are currently closed. Please leave a message with your contact details.\"\\n\\n' +\n'END CALL MESSAGE: \"Thank you for contacting ' + $('Business Parameters').item.json[\"Business Name\"] + '. Goodbye.\"'\n\nDENTIST\n\n'DENTAL OFFICE TEMPLATE:\\n\\n' +\n'SYSTEM MESSAGE:\\n' +\n'You are the receptionist at ' + $('Business Parameters').item.json[\"Business Name\"] + ' dental office, located at ' + $('Business Parameters').item.json[\"Street\"] + ', ' + $('Business Parameters').item.json[\"City\"] + '.\\n\\n' +\n'ROLE: Handle calls, schedule appointments, assess emergencies.\\n\\n' +\n'STANDARD SERVICES:\\n' +\n'- General consultations\\n' +\n'- Dental care\\n' +\n'- Teeth cleaning\\n' +\n'- Dental emergencies\\n\\n' +\n'APPOINTMENT BOOKING:\\n' +\n'1. Ask for: last name, first name, reason for visit\\n' +\n'2. If emergency: assess severity (pain, trauma)\\n' +\n'3. Offer appropriate time slots\\n' +\n'4. Confirm phone number\\n\\n' +\n'EMERGENCIES: For intense pain or trauma, offer appointment within 24-48h.\\n\\n' +\n'HOURS:\\n' + JSON.stringify($('Business Parameters').item.json[\"Opening Hours\"]) + '\\n\\n' +\n'RULES:\\n' +\n'- Reassuring and professional tone\\n' +\n'- Short responses (2-3 sentences)\\n' +\n'- One question at a time\\n' +\n'- For medical questions: suggest practitioner consultation\\n\\n' +\n'FIRST MESSAGE: \"Hello, ' + $('Business Parameters').item.json[\"Business Name\"] + ' dental office. How may I help you?\"\\n\\n' +\n'VOICEMAIL MESSAGE: \"Hello, you\\'ve reached ' + $('Business Parameters').item.json[\"Business Name\"] + ' dental office. For emergencies, please call the dental emergency line. Otherwise, leave a message.\"\\n\\n' +\n'END CALL MESSAGE: \"Thank you for contacting ' + $('Business Parameters').item.json[\"Business Name\"] + '. Have a great day.\"'\n\nRESTAURANT\n\n'RESTAURANT TEMPLATE:\\n\\n' +\n'SYSTEM MESSAGE:\\n' +\n'You are the receptionist at ' + $('Business Parameters').item.json[\"Business Name\"] + ' restaurant, located at ' + $('Business Parameters').item.json[\"Street\"] + ', ' + $('Business Parameters').item.json[\"City\"] + '.\\n\\n' +\n'ROLE: Manage reservations, provide menu information.\\n\\n' +\n'SERVICES:\\n' +\n'- Lunch and dinner reservations\\n' +\n'- Menu information\\n' +\n'- Private events\\n\\n' +\n'RESERVATION BOOKING:\\n' +\n'1. Ask for: name, party size, date, time\\n' +\n'2. Offer available time slots\\n' +\n'3. Note special requests (allergies, birthday)\\n' +\n'4. Confirm phone number\\n\\n' +\n'HOURS:\\n' + JSON.stringify($('Business Parameters').item.json[\"Opening Hours\"]) + '\\n\\n' +\n'RULES:\\n' +\n'- Welcoming and professional tone\\n' +\n'- Short responses (2-3 sentences)\\n' +\n'- One question at a time\\n' +\n'- For groups of 10+: transfer to manager\\n\\n' +\n'FIRST MESSAGE: \"Hello, ' + $('Business Parameters').item.json[\"Business Name\"] + ' restaurant. How may I help you?\"\\n\\n' +\n'VOICEMAIL MESSAGE: \"Hello, you\\'ve reached ' + $('Business Parameters').item.json[\"Business Name\"] + ' restaurant. Please leave your contact details for a reservation.\"\\n\\n' +\n'END CALL MESSAGE: \"Thank you for contacting ' + $('Business Parameters').item.json[\"Business Name\"] + ' restaurant. Goodbye.\"'\n\nSPA / WELLNESS\n\n'SPA / WELLNESS TEMPLATE:\\n\\n' +\n'SYSTEM MESSAGE:\\n' +\n'You are the receptionist at ' + $('Business Parameters').item.json[\"Business Name\"] + ' spa, located at ' + $('Business Parameters').item.json[\"Street\"] + ', ' + $('Business Parameters').item.json[\"City\"] + '.\\n\\n' +\n'ROLE: Schedule appointments, advise on treatments.\\n\\n' +\n'SERVICES:\\n' +\n'- Massages\\n' +\n'- Facial and body treatments\\n' +\n'- Relaxation packages\\n\\n' +\n'APPOINTMENT BOOKING:\\n' +\n'1. Ask for: first name, treatment type, preferred date\\n' +\n'2. Recommend based on needs\\n' +\n'3. Inform about total duration\\n' +\n'4. Confirm phone number\\n\\n' +\n'HOURS:\\n' + JSON.stringify($('Business Parameters').item.json[\"Opening Hours\"]) + '\\n\\n' +\n'RULES:\\n' +\n'- Calm and professional tone\\n' +\n'- Short responses (2-3 sentences)\\n' +\n'- One question at a time\\n' +\n'- For medical questions: transfer to practitioner\\n\\n' +\n'FIRST MESSAGE: \"Hello, ' + $('Business Parameters').item.json[\"Business Name\"] + ' spa. How may I help you?\"\\n\\n' +\n'VOICEMAIL MESSAGE: \"Hello, you\\'ve reached ' + $('Business Parameters').item.json[\"Business Name\"] + ' spa. Please leave your contact details, we will call you back.\"\\n\\n' +\n'END CALL MESSAGE: \"Thank you for contacting ' + $('Business Parameters').item.json[\"Business Name\"] + '. Have a great day.\"'\n\n{{\n`\n\nINTELLIGENT CUSTOMIZATION:\n\nAnalyze the provided data and intelligently adapt:\n\n1. **COMMUNICATION TONE**:\n - If \"premium\" category: slightly more refined tone\n - If modern barber: relaxed but professional tone\n - If medical office: reassuring and empathetic tone\n - If fine dining restaurant: elegant tone\n\n2. **SERVICES TO HIGHLIGHT**:\n - Extract services mentioned on the website\n - Use keywords from customer reviews if available\n - Adapt based on Google Maps category\n\n3. **LOCAL SPECIFICS**:\n - Mention the neighborhood if recognized (e.g., \"in the heart of...\")\n - Adapt if parking available, wheelchair accessible\n - Mention if kid-friendly, LGBTQ+ friendly (based on Info)\n\n4. **FIRSTMESSAGE CUSTOMIZATION**:\n - If high-end salon: \"Hello, welcome to [Name]...\"\n - If quick service: \"Hello, [Name]. I'm listening.\"\n - Keep simple by default: \"Hello, [Name]. How may I help you?\"\n\n5. **HOURS ADAPTATION**:\n - If closed Sunday/Monday: specify in system message\n - If extended hours (8pm+): mention availability\n - If unusual hours: adapt voicemailMessage\n\nSTRICT JSON OUTPUT FORMAT:\n\n{\n \"system_message\": \"[The complete customized system prompt of 400-600 words]\",\n \"firstMessage\": \"[Short and adapted welcome message]\",\n \"voicemailMessage\": \"[Voicemail message]\",\n \"endCallMessage\": \"[Short end call message]\"\n}\n\nIMPORTANT: Reply ONLY with the JSON, no text before or after.\n`\n}}"
}
]
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "ff69a612-48c4-4fd7-8598-78f03f1bf7b4",
"name": "Parse Agent Responses",
"type": "n8n-nodes-base.code",
"position": [
-1040,
64
],
"parameters": {
"jsCode": "const inputData = $input.first().json.content[0].text;\n\nconst startIndex = inputData.indexOf('{');\nconst endIndex = inputData.lastIndexOf('}') + 1;\nconst jsonString = inputData.substring(startIndex, endIndex);\n\nconst jsonContent = JSON.parse(jsonString);\n\nconst messagesArray = [\n {\n type: \"system_message\",\n content: jsonContent.system_message\n },\n {\n type: \"first_message\",\n content: jsonContent.firstMessage\n },\n {\n type: \"voicemail_message\",\n content: jsonContent.voicemailMessage\n }\n];\n\nreturn [{\n json: {\n messages: messagesArray\n }\n}];"
},
"typeVersion": 2
},
{
"id": "4a019ffe-c8a2-474d-a182-de2616441426",
"name": "Create Vapi Assistant",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-816,
64
],
"parameters": {
"url": "https://api.vapi.ai/assistant",
"method": "POST",
"options": {},
"jsonBody": "={\n \"name\": \"{{ $('Scrape Local Businesses').item.json.title }}\",\n \"voice\": {\n \"model\": \"eleven_turbo_v2_5\",\n \"voiceId\": \"Qrl71rx6Yg8RvyPYRGCQ\",\n \"provider\": \"11labs\",\n \"stability\": 0.7,\n \"similarityBoost\": 0.8,\n \"optimizeStreamingLatency\": 3\n },\n \"model\": {\n \"model\": \"gpt-4o-mini\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"{{ $json.messages[0].content }}\"\n }\n ],\n \"provider\": \"openai\",\n \"maxTokens\": 200,\n \"temperature\": 0.5\n },\n \"firstMessage\": \"{{ $json.messages[1].content }}\",\n \"voicemailMessage\": \"{{ $json.messages[2].content }}\",\n \"endCallMessage\": \"Merci de votre appel, \u00e0 bient\u00f4t chez {{ $('Scrape Local Businesses').item.json.title }}\",\n \"transcriber\": {\n \"model\": \"nova-2\",\n \"language\": \"fr\",\n \"provider\": \"deepgram\",\n \"endpointing\": 150,\n \"smartFormat\": true\n },\n \"firstMessageMode\": \"assistant-speaks-first\",\n \"silenceTimeoutSeconds\": 30,\n \"responseDelaySeconds\": 0.3,\n \"backgroundDenoisingEnabled\": true\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.1
},
{
"id": "fc2f5adb-627f-41ed-b5b1-d6f021c3be2c",
"name": "Log Agent to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-608,
176
],
"parameters": {
"columns": {
"value": {
"Agent ID": "={{ $json.id }}",
"Agent URL": "=https://dashboard.vapi.ai/assistants/{{ $json.id }}",
"Nom du business": "={{ $json.name }}"
},
"schema": [
{
"id": "Agent URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Agent URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom du business",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Nom du business",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cat\u00e9gorie",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Cat\u00e9gorie",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rue",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Rue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Ville",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Ville",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Code postal",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Code postal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Site web",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Site web",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "N\u00b0 T\u00e9l",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "N\u00b0 T\u00e9l",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Opening Hours",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Opening Hours",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Infos",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Infos",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Site Web Data",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Site Web Data",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Agent ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Agent ID",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Nom du business"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=[PASTE ID HERE]"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "=[PASTE URL HERE]"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "25a6d8eb-72d2-4ab3-a8be-2bc2854c15a1",
"name": "Scrape Local Businesses",
"type": "@apify/n8n-nodes-apify.apify",
"position": [
-2784,
176
],
"parameters": {
"actorId": {
"__rl": true,
"mode": "list",
"value": "nwua9Gu5YrADL7ZDj",
"cachedResultUrl": "https://console.apify.com/actors/nwua9Gu5YrADL7ZDj/input",
"cachedResultName": "Google Maps Scraper (compass/crawler-google-places)"
},
"operation": "Run actor and get dataset",
"customBody": "={{ JSON.stringify($json) }}"
},
"credentials": {
"apifyApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "32940446-3a74-453d-9707-c84d3e23ae05",
"name": "Process Businesses",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-2480,
64
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "9beba509-5cfd-455c-ba23-c3f23f664466",
"name": "Fetch Website",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2208,
80
],
"parameters": {
"url": "={{ $json.website.match(/https:\\/\\/.*/)[0] }}",
"options": {
"timeout": 10000,
"allowUnauthorizedCerts": true
}
},
"typeVersion": 4.1,
"continueOnFail": true
},
{
"id": "794a9b18-dc09-42d1-b6fb-681b83c45c9b",
"name": "Format Business Data",
"type": "n8n-nodes-base.set",
"position": [
-1728,
64
],
"parameters": {
"fields": {
"values": [
{
"name": "Nom du business",
"stringValue": "={{ $('Scrape Local Businesses').item.json.title }}"
},
{
"name": "Cat\u00e9gorie",
"stringValue": "={{ $('Scrape Local Businesses').item.json.categoryName }}"
},
{
"name": "Rue",
"stringValue": "={{ $('Scrape Local Businesses').item.json.street }}"
},
{
"name": "Ville",
"stringValue": "={{ $('Scrape Local Businesses').item.json.city }}"
},
{
"name": "Code postal",
"stringValue": "={{ $('Scrape Local Businesses').item.json.postalCode }}"
},
{
"name": "Site web",
"stringValue": "={{ $('Scrape Local Businesses').item.json.website }}"
},
{
"name": "N\u00b0 T\u00e9l",
"stringValue": "={{ $('Scrape Local Businesses').item.json.phone }}"
},
{
"name": "Opening Hours",
"type": "arrayValue",
"arrayValue": "={{ $('Scrape Local Businesses').item.json.openingHours }}"
},
{
"name": "Infos",
"type": "objectValue",
"objectValue": "={{ $('Scrape Local Businesses').item.json.additionalInfo }}"
},
{
"name": "Site Web Data",
"stringValue": "={{ $json.output['Texte clean'] }}"
}
]
},
"include": "none",
"options": {
"ignoreConversionErrors": true
}
},
"typeVersion": 3.2
},
{
"id": "e292ee23-24d3-44a0-a434-35557bb25b29",
"name": "Extract Website Text / Clean",
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
"position": [
-2032,
64
],
"parameters": {
"text": "={{ $json.data || \"Aucun//tu peux output un item qui dit que le site n'\u00e9tait pas accesible\" }}",
"options": {},
"attributes": {
"attributes": [
{
"name": "Clean Text",
"required": true,
"description": "Text without HTML tags."
}
]
}
},
"typeVersion": 1.2
},
{
"id": "c8803aae-257b-485e-a3b9-d4350918a4c6",
"name": "Sync to Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1552,
64
],
"parameters": {
"columns": {
"value": {
"Rue": "={{ $json.Street }}",
"Infos": "={{ $json.Infos }}",
"Ville": "={{ $json.City }}",
"N\u00b0 T\u00e9l": "={{ $json[\"Phone Number\"].replace(/[\\s+]/g, '') }}",
"Site web": "={{ $json[\"Website\"] }}",
"Cat\u00e9gorie": "={{ $json[\"Category\"] }}",
"Code postal": "={{ $json[\"ZIPCODE\"] }}",
"Opening Hours": "={{ $json[\"Opening Hours\"] }}",
"Site Web Data": "={{ $json[\"Website Data\"] }}",
"Nom du business": "={{ $json[\"Business Name\"] }}"
},
"schema": [
{
"id": "Agent URL",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Agent URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom du business",
"type": "string",
"display": true,
"required": false,
"displayName": "Nom du business",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cat\u00e9gorie",
"type": "string",
"display": true,
"required": false,
"displayName": "Cat\u00e9gorie",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rue",
"type": "string",
"display": true,
"required": false,
"displayName": "Rue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Ville",
"type": "string",
"display": true,
"required": false,
"displayName": "Ville",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Code postal",
"type": "string",
"display": true,
"required": false,
"displayName": "Code postal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Site web",
"type": "string",
"display": true,
"required": false,
"displayName": "Site web",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "N\u00b0 T\u00e9l",
"type": "string",
"display": true,
"required": false,
"displayName": "N\u00b0 T\u00e9l",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Opening Hours",
"type": "string",
"display": true,
"required": false,
"displayName": "Opening Hours",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Infos",
"type": "string",
"display": true,
"required": false,
"displayName": "Infos",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Site Web Data",
"type": "string",
"display": true,
"required": false,
"displayName": "Site Web Data",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Agent ID",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Agent ID",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "=[PASTE ID HERE]"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "=[PASTE URL HERE]"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "8cf203d7-7307-43ae-a96a-93e8ef772835",
"name": "Form Trigger - Business Location Input",
"type": "n8n-nodes-base.formTrigger",
"position": [
-3328,
176
],
"parameters": {
"options": {
"customCss": ":root {\n\t--font-family: 'Open Sans', sans-serif;\n\t--font-weight-normal: 400;\n\t--font-weight-bold: 600;\n\t--font-size-body: 12px;\n\t--font-size-label: 14px;\n\t--font-size-test-notice: 12px;\n\t--font-size-input: 14px;\n\t--font-size-header: 20px;\n\t--font-size-paragraph: 14px;\n\t--font-size-link: 12px;\n\t--font-size-error: 12px;\n\t--font-size-html-h1: 28px;\n\t--font-size-html-h2: 20px;\n\t--font-size-html-h3: 16px;\n\t--font-size-html-h4: 14px;\n\t--font-size-html-h5: 12px;\n\t--font-size-html-h6: 10px;\n\t--font-size-subheader: 14px;\n\t\n\t/* Colors - Palette Tech Violet/Bleu */\n\t--color-background: #0f0f1e;\n\t--color-test-notice-text: #a78bfa;\n\t--color-test-notice-bg: #1a1a2e;\n\t--color-test-notice-border: #4c1d95;\n\t--color-card-bg: #1a1a2e;\n\t--color-card-border: #2d2d4a;\n\t--color-card-shadow: rgba(139, 92, 246, 0.15);\n\t--color-link: #a78bfa;\n\t--color-header: #e5e7eb;\n\t--color-label: #d1d5db;\n\t--color-input-border: #3b3b5c;\n\t--color-input-text: #9ca3af;\n\t--color-focus-border: #8b5cf6;\n\t--color-submit-btn-bg: #00d9ff;\n\t--color-submit-btn-text: #0a0a14;\n\t--color-submit-btn-shadow: rgba(0, 217, 255, 0.4);\n\t--color-error: #f87171;\n\t--color-required: #a78bfa;\n\t--color-clear-button-bg: #4b5563;\n\t--color-html-text: #d1d5db;\n\t--color-html-link: #8b5cf6;\n\t--color-header-subtext: #9ca3af;\n\t\n\t/* Border Radii */\n\t--border-radius-card: 12px;\n\t--border-radius-input: 8px;\n\t--border-radius-clear-btn: 50%;\n\t--card-border-radius: 12px;\n\t\n\t/* Spacing */\n\t--padding-container-top: 24px;\n\t--padding-card: 28px;\n\t--padding-test-notice-vertical: 14px;\n\t--padding-test-notice-horizontal: 24px;\n\t--margin-bottom-card: 20px;\n\t--padding-form-input: 14px;\n\t--card-padding: 28px;\n\t--card-margin-bottom: 20px;\n\t\n\t/* Dimensions */\n\t--container-width: 448px;\n\t--submit-btn-height: 52px;\n\t--checkbox-size: 20px;\n\t\n\t/* Others */\n\t--box-shadow-card: 0px 8px 24px 0px var(--color-card-shadow), 0px 0px 1px 0px rgba(139, 92, 246, 0.3);\n\t--box-shadow-submit-btn: 0px 4px 20px var(--color-submit-btn-shadow), 0px 0px 40px rgba(0, 217, 255, 0.2);\n\t--opacity-placeholder: 0.4;\n}",
"buttonLabel": "Generate Agents",
"appendAttribution": false,
"respondWithOptions": {
"values": {
"formSubmittedText": "Voici l'URL de votre Agent IA vocal :"
}
}
},
"formTitle": "AI Voice Agent Generator",
"formFields": {
"values": [
{
"fieldLabel": "City",
"placeholder": "Paris",
"requiredField": true
},
{
"fieldLabel": "State / Region",
"placeholder": "\u00cele-de-France",
"requiredField": true
},
{
"fieldType": "number",
"fieldLabel": "ZIPCODE",
"placeholder": "75001",
"requiredField": true
},
{
"fieldType": "number",
"fieldLabel": "Number of businesses to do",
"placeholder": "3",
"defaultValue": "1",
"requiredField": true
},
{
"fieldLabel": "Keywords (separated by comma)",
"placeholder": "barbier,barber,coiffeur,salon de coiffure,salon capillaire",
"requiredField": true
}
]
},
"responseMode": "lastNode",
"formDescription": "Enter the location parameters where the businesses are located for which you want to generate AI Voice Agents."
},
"typeVersion": 2.3
},
{
"id": "028b875f-fe79-44a6-91c1-0bc167157122",
"name": "Build Apify Request",
"type": "n8n-nodes-base.code",
"position": [
-3120,
176
],
"parameters": {
"jsCode": "const formData = $('Form Trigger - Business Location Input').first().json;\n\nconst searchStringsArray = formData['Keywords (separated by comma)']\n .split(',')\n .map(keyword => keyword.trim())\n .filter(keyword => keyword.length > 0);\n\nreturn [{\n json: {\n city: formData['City'],\n countryCode: \"[Change here]\",\n county: formData['State / Region'],\n includeWebResults: true,\n language: \"[Input your Language here]\",\n locationQuery: `${formData['City']}, [Input Here your country]`,\n maxCrawledPlacesPerSearch: formData['Number of businesses to do'],\n maxImages: 0,\n maximumLeadsEnrichmentRecords: 400,\n postalCode: String(formData['ZIPCODE']),\n scrapeContacts: true,\n scrapeDirectories: true,\n scrapeImageAuthors: false,\n scrapePlaceDetailPage: true,\n scrapeReviewsPersonalData: true,\n scrapeTableReservationProvider: true,\n searchMatching: \"all\",\n searchStringsArray: searchStringsArray,\n skipClosedPlaces: false,\n website: \"withWebsite\"\n }\n}];"
},
"typeVersion": 2
},
{
"id": "05911965-2e42-4475-8ff3-b4883cc1a44c",
"name": "Display Results Page",
"type": "n8n-nodes-base.form",
"position": [
-1968,
-224
],
"parameters": {
"operation": "completion",
"respondWith": "showText",
"responseText": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Your AI Voice Agent - {{ $json[\"Business Name\"] }}</title>\n <link href=\"https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap\" rel=\"stylesheet\">\n <style>\n :root {\n --font-family: 'Open Sans', sans-serif;\n --font-weight-normal: 400;\n --font-weight-bold: 600;\n --font-size-body: 12px;\n --font-size-label: 14px;\n --font-size-input: 14px;\n --font-size-header: 24px;\n --font-size-subheader: 16px;\n --font-size-paragraph: 14px;\n \n --color-background: #0f0f1e;\n --color-card-bg: #1a1a2e;\n --color-card-border: #2d2d4a;\n --color-card-shadow: rgba(139, 92, 246, 0.15);\n --color-header: #e5e7eb;\n --color-label: #d1d5db;\n --color-text: #9ca3af;\n --color-accent: #8b5cf6;\n --color-accent-hover: #7c3aed;\n --color-btn-primary: #00d9ff;\n --color-btn-primary-hover: #00b8d4;\n --color-btn-text: #0a0a14;\n --color-code-bg: #0a0a14;\n --color-code-border: #3b3b5c;\n \n --border-radius-card: 12px;\n --border-radius-btn: 8px;\n --padding-card: 28px;\n --margin-bottom-card: 20px;\n \n --box-shadow-card: 0px 8px 24px 0px var(--color-card-shadow), 0px 0px 1px 0px rgba(139, 92, 246, 0.3);\n --box-shadow-btn: 0px 4px 20px rgba(0, 217, 255, 0.4), 0px 0px 40px rgba(0, 217, 255, 0.2);\n }\n \n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n body {\n font-family: var(--font-family);\n font-size: var(--font-size-body);\n background-color: var(--color-background);\n color: var(--color-text);\n padding: 24px;\n line-height: 1.6;\n }\n \n .container {\n max-width: 800px;\n margin: 0 auto;\n }\n \n .header {\n text-align: center;\n margin-bottom: 32px;\n }\n \n .header h1 {\n font-size: var(--font-size-header);\n font-weight: var(--font-weight-bold);\n color: var(--color-header);\n margin-bottom: 8px;\n }\n \n .header p {\n font-size: var(--font-size-paragraph);\n color: var(--color-text);\n }\n \n .card {\n background: var(--color-card-bg);\n border: 1px solid var(--color-card-border);\n border-radius: var(--border-radius-card);\n padding: var(--padding-card);\n margin-bottom: var(--margin-bottom-card);\n box-shadow: var(--box-shadow-card);\n }\n \n .card h2 {\n font-size: var(--font-size-subheader);\n font-weight: var(--font-weight-bold);\n color: var(--color-header);\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n \n .card h2::before {\n content: \"\u2192\";\n color: var(--color-accent);\n }\n \n .param-group {\n margin-bottom: 20px;\n }\n \n .param-label {\n font-size: var(--font-size-label);\n font-weight: var(--font-weight-bold);\n color: var(--color-label);\n margin-bottom: 8px;\n display: block;\n }\n \n .param-value {\n background: var(--color-code-bg);\n border: 1px solid var(--color-code-border);\n border-radius: 6px;\n padding: 12px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n color: #a78bfa;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-all;\n }\n \n .param-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 16px;\n margin-top: 16px;\n }\n \n .param-item {\n background: var(--color-code-bg);\n border: 1px solid var(--color-code-border);\n border-radius: 6px;\n padding: 12px;\n }\n \n .param-item-label {\n font-size: 11px;\n text-transform: uppercase;\n color: var(--color-text);\n margin-bottom: 4px;\n }\n \n .param-item-value {\n font-size: var(--font-size-label);\n color: var(--color-accent);\n font-weight: var(--font-weight-bold);\n }\n \n .btn {\n display: inline-block;\n padding: 14px 28px;\n border-radius: var(--border-radius-btn);\n font-size: var(--font-size-label);\n font-weight: var(--font-weight-bold);\n text-decoration: none;\n cursor: pointer;\n border: none;\n transition: all 0.3s ease;\n text-align: center;\n }\n \n .btn-primary {\n background: var(--color-btn-primary);\n color: var(--color-btn-text);\n box-shadow: var(--box-shadow-btn);\n }\n \n .btn-primary:hover {\n background: var(--color-btn-primary-hover);\n transform: translateY(-2px);\n }\n \n .btn-secondary {\n background: transparent;\n color: var(--color-accent);\n border: 2px solid var(--color-accent);\n }\n \n .btn-secondary:hover {\n background: var(--color-accent);\n color: white;\n }\n \n .action-buttons {\n display: flex;\n gap: 12px;\n margin-top: 24px;\n flex-wrap: wrap;\n justify-content: center;\n }\n \n .info-box {\n background: rgba(139, 92, 246, 0.1);\n border: 1px solid var(--color-accent);\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 20px;\n }\n \n .info-box p {\n font-size: var(--font-size-paragraph);\n color: var(--color-label);\n margin-bottom: 8px;\n }\n \n .info-box p:last-child {\n margin-bottom: 0;\n }\n \n .highlight {\n color: var(--color-accent);\n font-weight: var(--font-weight-bold);\n }\n \n code {\n background: var(--color-code-bg);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n color: #a78bfa;\n }\n \n .message-preview {\n background: var(--color-code-bg);\n border-left: 3px solid var(--color-accent);\n padding: 12px 16px;\n margin: 12px 0;\n border-radius: 4px;\n }\n \n .message-type {\n font-size: 11px;\n text-transform: uppercase;\n color: var(--color-accent);\n margin-bottom: 6px;\n font-weight: var(--font-weight-bold);\n }\n \n .message-content {\n color: var(--color-label);\n font-size: var(--font-size-paragraph);\n line-height: 1.5;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>\ud83c\udf99\ufe0f Your AI Voice Agent</h1>\n <p>Custom configuration for <span class=\"highlight\">{{ $json[\"Business Name\"] }}</span></p>\n </div>\n \n <div class=\"info-box\">\n <p>\ud83c\udf89 Your intelligent voice agent is ready to be deployed!</p>\n <p>We have generated an optimized configuration for your business. Follow the steps below to activate your AI phone assistant.</p>\n </div>\n \n <!-- Messages Configuration -->\n <div class=\"card\">\n <h2>Agent Messages</h2>\n \n <div class=\"message-preview\">\n <div class=\"message-type\">Welcome Message</div>\n <div class=\"message-content\">{{ $('Parse Agent Responses').item.json.messages[1].content }}</div>\n </div>\n \n <div class=\"message-preview\">\n <div class=\"message-type\">Voicemail Message</div>\n <div class=\"message-content\">{{ $('Parse Agent Responses').item.json.messages[2].content }}</div>\n </div>\n \n <div class=\"message-preview\">\n <div class=\"message-type\">End Call Message</div>\n <div class=\"message-content\">Thank you for your call, see you soon at {{ $json[\"Business Name\"] }}</div>\n </div>\n </div>\n \n <!-- Voice Configuration -->\n <div class=\"card\">\n <h2>Voice Configuration</h2>\n <div class=\"param-grid\">\n <div class=\"param-item\">\n <div class=\"param-item-label\">Provider</div>\n <div class=\"param-item-value\">ElevenLabs</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Model</div>\n <div class=\"param-item-value\">Turbo v2.5</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Stability</div>\n <div class=\"param-item-value\">0.7</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Similarity</div>\n <div class=\"param-item-value\">0.8</div>\n </div>\n </div>\n </div>\n \n <!-- AI Model Configuration -->\n <div class=\"card\">\n <h2>AI Configuration</h2>\n <div class=\"param-grid\">\n <div class=\"param-item\">\n <div class=\"param-item-label\">LLM Model</div>\n <div class=\"param-item-value\">GPT-4o Mini</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Provider</div>\n <div class=\"param-item-value\">OpenAI</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Max Tokens</div>\n <div class=\"param-item-value\">200</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Temperature</div>\n <div class=\"param-item-value\">0.5</div>\n </div>\n </div>\n </div>\n \n <!-- Transcription Configuration -->\n <div class=\"card\">\n <h2>Transcription Configuration</h2>\n <div class=\"param-grid\">\n <div class=\"param-item\">\n <div class=\"param-item-label\">Provider</div>\n <div class=\"param-item-value\">Deepgram</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Model</div>\n <div class=\"param-item-value\">Nova-2</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Language</div>\n <div class=\"param-item-value\">English</div>\n </div>\n <div class=\"param-item\">\n <div class=\"param-item-label\">Smart Format</div>\n <div class=\"param-item-value\">Enabled</div>\n </div>\n </div>\n </div>\n \n <!-- System Prompt -->\n <div class=\"card\">\n <h2>System Prompt</h2>\n <div class=\"param-group\">\n <label class=\"param-label\">Complete agent instructions</label>\n <div class=\"param-value\">{{ $('Parse Agent Responses').item.json.messages[0].content }}</div>\n </div>\n </div>\n \n <!-- Complete JSON Configuration -->\n <div class=\"card\">\n <h2>Complete JSON Configuration</h2>\n <div class=\"param-group\">\n <label class=\"param-label\">Copy-paste this configuration into VAPI</label>\n <div class=\"param-value\">{\n \"name\": \"{{ $json[\"Business Name\"] }}\",\n \"voice\": {\n \"model\": \"eleven_turbo_v2_5\",\n \"voiceId\": \"YOUR_ELEVENLABS_VOICE_ID\",\n \"provider\": \"11labs\",\n \"stability\": 0.7,\n \"similarityBoost\": 0.8,\n \"optimizeStreamingLatency\": 3\n },\n \"model\": {\n \"model\": \"gpt-4o-mini\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"{{ $('Parse Agent Responses').item.json.messages[0].content }}\"\n }\n ],\n \"provider\": \"openai\",\n \"maxTokens\": 200,\n \"temperature\": 0.5\n },\n \"firstMessage\": \"{{ $('Parse Agent Responses').item.json.messages[1].content }}\",\n \"voicemailMessage\": \"{{ $('Parse Agent Responses').item.json.messages[2].content }}\",\n \"endCallMessage\": \"Thank you for your call, see you soon at {{ $json[\"Business Name\"] }}\",\n \"transcriber\": {\n \"model\": \"nova-2\",\n \"language\": \"en\",\n \"provider\": \"deepgram\",\n \"endpointing\": 150,\n \"smartFormat\": true\n },\n \"firstMessageMode\": \"assistant-speaks-first\",\n \"silenceTimeoutSeconds\": 30,\n \"responseDelaySeconds\": 0.3,\n \"backgroundDenoisingEnabled\": true\n}</div>\n </div>\n </div>\n \n <!-- Actions -->\n <div class=\"card\">\n <h2>Next Steps</h2>\n \n <div class=\"info-box\">\n <p><strong>Don't have a VAPI account yet?</strong></p>\n <p>Create your free account and get <span class=\"highlight\">10 free conversation minutes</span> to test your agent.</p>\n </div>\n \n <div class=\"action-buttons\">\n <a href=\"https://vapi.ai\" target=\"_blank\" class=\"btn btn-secondary\">\n Create VAPI Account\n </a>\n <a href=\"https://dashboard.vapi.ai/assistants/{{ $('Create Vapi Assistant').item.json.id }}\" target=\"_blank\" class=\"btn btn-primary\">\n Access Your Agent\n </a>\n </div>\n \n <div style=\"margin-top: 24px; padding-top: 24px; border-top: 1px solid var(--color-card-border);\">\n <p style=\"color: var(--color-text); font-size: var(--font-size-paragraph); margin-bottom: 12px;\">\n <strong>How to deploy your agent:</strong>\n </p>\n <ol style=\"color: var(--color-text); font-size: var(--font-size-paragraph); padding-left: 20px; line-height: 1.8;\">\n <li>Log in to your VAPI dashboard</li>\n <li>Click \"Access Your Agent\" or create a new assistant</li>\n <li>Copy-paste the complete JSON configuration above</li>\n <li>Test your agent with the built-in simulator</li>\n <li>Connect a phone number to receive calls</li>\n </ol>\n </div>\n </div>\n </div>\n</body>\n</html>"
},
"typeVersion": 2.3
},
{
"id": "809b9d89-ab30-461d-aadf-70081dc4d28c",
"name": "Limit to 1st result for preview",
"type": "n8n-nodes-base.limit",
"position": [
-2192,
-224
],
"parameters": {},
"typeVersion": 1
},
{
"id": "b3459595-8b0d-4999-bf81-c859c9c67e33",
"name": "Grok-4-fast",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
-1904,
288
],
"parameters": {
"model": "x-ai/grok-4-fast",
"options": {}
},
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "271c0ee1-0b4c-474e-b988-549e10593122",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2944,
16
],
"parameters": {
"color": 3,
"width": 384,
"height": 320,
"content": "**\u26a0\ufe0f CONFIGURE FOR YOUR COUNTRY**\n\nUpdate:\n- `countryCode`: \"us\" (or your country)\n- `language`: \"en\" (or your language)\n- `locationQuery`: \"${city}, United States\" (or your country)"
},
"typeVersion": 1
},
{
"id": "d333a6a4-11a3-464c-9149-f758f2c1a699",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3424,
-96
],
"parameters": {
"color": 7,
"width": 896,
"height": 448,
"content": "## 1. Data Collection & Scraping\n\nCaptures user input via form and scrapes matching businesses from Google Maps using Apify."
},
"typeVersion": 1
},
{
"id": "01ccd84e-d1c6-4299-b623-62639739181a",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4304,
-272
],
"parameters": {
"width": 870,
"height": 624,
"content": "## AI Voice Agent Generator for Local Businesses\n\nAutomatically create personalized AI voice receptionist agents for local businesses using VAPI, by scraping Google Maps data and analyzing their websites.\n\n### How it works\n1. **Form input**: User submits city, region, postal code, and business keywords\n2. **Google Maps scraping**: Apify scrapes local businesses matching criteria\n3. **Website analysis**: LLM extracts relevant content from each business website\n4. **AI prompt generation**: Claude generates customized system prompts, greetings, and voicemail messages based on business type\n5. **VAPI provisioning**: Automatically creates voice agents via VAPI API\n6. **Logging**: Stores all generated agents in Google Sheets for tracking\n\n### Setup steps\n1. Connect **Apify** credentials (Google Maps Scraper actor)\n2. Connect **Anthropic** API key\n3. Connect **OpenRouter** API key (for website analysis)\n4. Add your **VAPI API key** in the HTTP Request node\n5. Connect **Google Sheets** OAuth\n6. Activate the workflow\n\n### Customization\n- Modify business category templates in the \"Generate Agent Messages\" node\n- Adjust voice settings (stability, similarity) in the VAPI provisioning node\n- Change the LLM model for prompt generation (default: Claude Sonnet)"
},
"typeVersion": 1
},
{
"id": "9cd0dd96-970a-480e-abb8-12094fb01cb4",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
-32
],
"parameters": {
"color": 7,
"width": 480,
"height": 256,
"content": "## 2. Business Analysis\nFetches each business website and extracts relevant text content using LLM."
},
"typeVersion": 1
},
{
"id": "3287f7f6-b291-48ea-b164-6781950d61f2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1392,
-64
],
"parameters": {
"color": 7,
"width": 288,
"height": 256,
"content": "## 3. Agent Generation\nUses Claude to generate customized voice agent prompts based on business type and data."
},
"typeVersion": 1
},
{
"id": "be2fa8ff-f587-450e-bd32-cd9c4b4b78a7",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-944,
-80
],
"parameters": {
"color": 7,
"width": 432,
"height": 448,
"content": "## 4. VAPI Deployment\nCreates the voice assistant via VAPI API and logs details to Google Sheets."
},
"typeVersion": 1
},
{
"id": "9edc3ce5-7ec3-4cbf-9da9-f085deeb7cfc",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
16
],
"parameters": {
"color": 3,
"height": 208,
"content": "**\u26a0\ufe0f REQUIRED:** Add your VAPI API key in the Authorization header"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "yrXce9YKtrOLslV3",
"timeSavedMode": "fixed",
"availableInMCP": true,
"executionOrder": "v1",
"timeSavedPerExecution": 30
},
"versionId": "b54a45c5-2baf-4856-9ea1-9e9adba269c4",
"connections": {
"Grok-4-fast": {
"ai_languageModel": [
[
{
"node": "Extract Website Text / Clean",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Fetch Website": {
"main": [
[
{
"node": "Extract Website Text / Clean",
"type": "main",
"index": 0
}
]
]
},
"Log Agent to Sheet": {
"main": [
[
{
"node": "Process Businesses",
"type": "main",
"index": 0
}
]
]
},
"Process Businesses": {
"main": [
[
{
"node": "Limit to 1st result for preview",
"type": "main",
"index": 0
}
],
[
{
"node": "Fetch Website",
"type": "main",
"index": 0
}
]
]
},
"Build Apify Request": {
"main": [
[
{
"node": "Scrape Local Businesses",
"type": "main",
"index": 0
}
]
]
},
"Display Results Page": {
"main": [
[]
]
},
"Format Business Data": {
"main": [
[
{
"node": "Sync to Google Sheet",
"type": "main",
"index": 0
}
]
]
},
"Sync to Google Sheet": {
"main": [
[
{
"node": "Generate Agent Messages",
"type": "main",
"index": 0
}
]
]
},
"Create Vapi Assistant": {
"main": [
[
{
"node": "Log Agent to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Parse Agent Responses": {
"main": [
[
{
"node": "Create Vapi Assistant",
"type": "main",
"index": 0
}
]
]
},
"Generate Agent Messages": {
"main": [
[
{
"node": "Parse Agent Responses",
"type": "main",
"index": 0
}
]
]
},
"Scrape Local Businesses": {
"main": [
[
{
"node": "Process Businesses",
"type": "main",
"index": 0
}
]
]
},
"Extract Website Text / Clean": {
"main": [
[
{
"node": "Format Business Data",
"type": "main",
"index": 0
}
]
]
},
"Limit to 1st result for preview": {
"main": [
[
{
"node": "Display Results Page",
"type": "main",
"index": 0
}
]
]
},
"Form Trigger - Business Location Input": {
"main": [
[
{
"node": "Build Apify Request",
"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.
anthropicApiapifyApigoogleSheetsOAuth2ApihttpHeaderAuthopenRouterApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate the creation of personalized AI phone receptionists for local businesses by scraping Google Maps, analyzing websites, and deploying voice agents to VAPI. Agencies offering AI voice solutions to local businesses Consultants helping SMBs modernize their phone systems…
Source: https://n8n.io/workflows/12956/ — 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.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes — all on autopilot.
Deep Research new (fr). Uses outputParserStructured, formTrigger, chainLlm, form. Event-driven trigger; 82 nodes.
My workflow 53. Uses formTrigger, httpRequest, lmChatOpenAi, form. Event-driven trigger; 74 nodes.
Digistars - Scrape & Crawl. Uses httpRequest, n8n-nodes-firecrawl-scraper, googleSheets, lmChatOpenAi. Event-driven trigger; 63 nodes.