使用AI助手和智能SMS提醒(24/7)自动化WhatsApp预约
高级
这是一个Support, AI领域的自动化工作流,包含 25 个节点。主要使用 Code, Sms77, Switch, Webhook, HttpRequest 等节点,结合人工智能技术实现智能自动化。 使用GPT-4助手、Cal.com和SMS提醒自动化WhatsApp预约系统
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
- •OpenAI API Key
使用的节点 (25)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "IyhsZQh7TFAGsDqL",
"meta": {
"instanceId": "a2b23892dd6989fda7c1209b381f5850373a7d2b85609624d7c2b7a092671d44",
"templateCredsSetupCompleted": true
},
"name": "使用 AI 助手和智能 SMS 提醒(24/7)自动化 WhatsApp 预约",
"tags": [],
"nodes": [
{
"id": "1d45c88a-5c71-42bb-9207-a7060a64030b",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-500,
480
],
"parameters": {
"color": 4,
"width": 1620,
"height": 280,
"content": "# 🟩 步骤 3 — 在预约前发送 SMS 提醒"
},
"typeVersion": 1
},
{
"id": "1274c8bb-78fd-445f-b3bb-c1adedba3acc",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-500,
-540
],
"parameters": {
"width": 1620,
"height": 460,
"content": "# 🟫 步骤 1 — 筛选用户并建议预约"
},
"typeVersion": 1
},
{
"id": "bb147090-c21c-4b75-bfd7-92b1b61646f5",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-500,
-60
],
"parameters": {
"color": 3,
"width": 1620,
"height": 520,
"content": "# 🟥 步骤 2 — 自动预约"
},
"typeVersion": 1
},
{
"id": "3b2b3031-55a6-4c98-a6a5-75eb746b2c99",
"name": "Webhook 触发器(WhatsApp 输入)",
"type": "n8n-nodes-base.webhook",
"position": [
-960,
-80
],
"webhookId": "6438cd95-74cb-4f40-a1a5-853706fe96f6",
"parameters": {
"path": "6438cd95-74cb-4f40-a1a5-853706fe96f6",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "6c7ffde6-b3bc-4162-b45d-8e483e347d49",
"name": "切换:确认与聊天流程",
"type": "n8n-nodes-base.switch",
"position": [
-740,
-80
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Discussion",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2b0aa9e5-7215-435b-8b66-fddb9973c7d0",
"operator": {
"type": "string",
"operation": "notContains"
},
"leftValue": "={{ $json.body.userInput }}",
"rightValue": "confirm"
}
]
},
"renameOutput": true
},
{
"outputKey": "Confirm booking",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ed81f2e7-f97d-4581-bc84-ed703db2ec08",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.body.userInput }}",
"rightValue": "confirm"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "f7f43574-cfed-4448-983f-dc53343ec4ab",
"name": "AI 预约助手(Dr Firas)",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
40,
-460
],
"parameters": {
"text": "=input : {{ $json.body.userInput }}",
"options": {
"systemMessage": "=#IMPORTANT \nLes rendez-vous ne peuvent être pris qu’après avoir collecté le nom, l’e-mail/Courriel et le service choisi.\n\n#IDENTITÉ \nVous êtes l’assistant de Dr Firas, coach expert en automatisation n8n, sur WhatsApp.\n\n#CONTEXTE \n- Dr Firas propose des coachings et ateliers en ligne pour maîtriser n8n \n- Horaires : du lundi au vendredi, 9 h–18 h (heure de Paris) \n- Français et anglais possibles\n- La date d'aujourd'hui est : {{$now}}\n\n#SERVICES ET MAPPING (CRITIQUE) \n- « Audit express n8n » (30 min) – 40 $ – Event ID : 2638115 \n- « Coaching Workflow n8n » (60 min) – 65 $ – Event ID : 2638127 \n- « Atelier Automatisation Avancée » (90 min) – 99 $ – Event ID : 2638131 \n\nQuand l’utilisateur choisit un service, mémorisez l’Event ID correspondant.\n\n#TON \nDynamique, professionnel et chaleureux. Emojis légers 👍🤖.\n\n#FLUX DE CONVERSATION\n\n## 1. Accueil \n« Bonjour ! Je suis l’assistant de Dr Firas, prêt à vous guider pour votre session n8n. Puis-je vous poser quelques questions ? »\n\n## 2. Choix du service (une question à la fois) \na) « Quel service souhaitez-vous ? » \n- Si « je ne sais pas » ou « que proposez-vous » → listez les 3 services avec durée, prix et bénéfice court. \n- Sinon, continuez.\n\n## 3. Collecte des infos client \n« Parfait ! Pour réserver votre [nom du service], j’ai besoin de votre prénom et de votre e-mail. »\n\n→ Après avoir reçu nom + e-mail/Courriel , enregistrez dans le Google Sheet Prospect (nom, e-mail, téléphone={{ $json.body.phoneNumber }}, service, Event ID, résumé).\n\n## 4. Proposition de créneaux \n« Souhaitez-vous voir les disponibilités immédiatement ? » \n- Si oui : \n 1. Appelez l’outil **Get Availability** avec : \n - Event ID du service \n - startTime = maintenant (ISO 8601, UTC, ex. `2025-06-13T12:00:00Z`) \n - endTime = +48 h (ISO 8601, UTC) \n - max 5 créneaux \n 2. Convertissez chaque horaire UTC en heure de Paris (+02:00) et affichez-les en plain text (ex. “14:30”).\n\n## 5. Choix du créneau \n« Lequel de ces créneaux vous convient ? » \n- L’utilisateur répond date+heure → \n - Demandez « Tapez “oui” pour confirmer ce créneau ». \n - À « oui », enregistrez via Google Sheet Update_Leads (nom, e-mail, service, Event ID, date+heure). \n - Puis : « Votre rendez-vous est fixé au [date] à [heure] (heure de Paris). Tapez “confirm” pour finaliser. »\n\n## 6. Confirmation finale \n- À “confirm” → \n - Confirmez la réservation et rappelez la politique d’annulation 24 h à l’avance. \n - Proposez un lien d’ajout au calendrier si besoin.\n\n#CONTRAINTES OUTIL “Get Availability” \n- Toujours ISO 8601 UTC \n- startTime = maintenant, endTime = +48 h \n- Maximum 5 créneaux \n- Plain text, < 400 car.\n\n#RÈGLES GÉNÉRALES \n- Une question à la fois \n- Ne jamais redemander une info déjà fournie \n- “RESET” relance la conversation depuis le début \n"
},
"promptType": "define"
},
"typeVersion": 1.8
},
{
"id": "03d391f5-43b5-462e-8c56-cdce426f9751",
"name": "LLM:GPT-4o 聊天模型",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-200,
-260
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o",
"cachedResultName": "gpt-4o"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "6h3DfVhNPw9I25nO",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "365fc08f-6514-4182-b77f-86a13ef55576",
"name": "AI 对话记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-40,
-260
],
"parameters": {
"sessionKey": "={{ $json.body.contactId }}",
"sessionIdType": "customKey",
"contextWindowLength": 50
},
"typeVersion": 1.3
},
{
"id": "96eeb9b5-aea9-46cc-893f-4ea3697a3fb5",
"name": "在 Google Sheets 中创建新潜在客户",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
140,
-260
],
"parameters": {
"columns": {
"value": {
"Nom": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Nom', ``, 'string') }}",
"Courriel": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Courriel', ``, 'string') }}",
"Résumé": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('R_sum_', `ici il y a le résumé de toute la conversation`, 'string') }}",
"ID du contact": "={{ $json.body.contactId }}",
"Numéro de téléphone": "={{ $json.body.phoneNumber }}"
},
"schema": [
{
"id": "Nom",
"type": "string",
"display": true,
"required": false,
"displayName": "Nom",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Courriel",
"type": "string",
"display": true,
"required": false,
"displayName": "Courriel",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Numéro de téléphone",
"type": "string",
"display": true,
"required": false,
"displayName": "Numéro de téléphone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Résumé",
"type": "string",
"display": true,
"required": false,
"displayName": "Résumé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Réservé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Réservé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "ID de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date du rendez-vous",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Date du rendez-vous",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rappel SMS envoyé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Rappel SMS envoyé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID du contact",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID du contact",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID du contact"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit#gid=0",
"cachedResultName": "mes RDV"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit?usp=drivesdk",
"cachedResultName": "MES RDV"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "9fcb6a32-34e7-4c5a-997a-cd0fe58f62cd",
"name": "使用预约详情更新潜在客户",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
320,
-260
],
"parameters": {
"columns": {
"value": {
"ID du contact": "={{ $json.body.contactId }}",
"Date du rendez-vous": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Date_du_rendez-vous', ``, 'string') }}",
"ID de l’événement": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('ID_de_l__v_nement', ``, 'string') }}",
"Nom de l’événement": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Nom_de_l__v_nement', ``, 'string') }}"
},
"schema": [
{
"id": "Nom",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Courriel",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Courriel",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Numéro de téléphone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Numéro de téléphone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Résumé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Résumé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Réservé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Réservé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom de l’événement",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Nom de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID de l’événement",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date du rendez-vous",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Date du rendez-vous",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rappel SMS envoyé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Rappel SMS envoyé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID du contact",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID du contact",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID du contact"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit#gid=0",
"cachedResultName": "mes RDV"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit?usp=drivesdk",
"cachedResultName": "MES RDV"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "9e1a6470-0937-4190-9d24-259ea2749190",
"name": "获取可用时间段",
"type": "@n8n/n8n-nodes-langchain.toolHttpRequest",
"position": [
520,
-260
],
"parameters": {
"url": "https://api.cal.com/v2/slots/available",
"sendQuery": true,
"sendHeaders": true,
"parametersQuery": {
"values": [
{
"name": "eventTypeId"
},
{
"name": "startTime"
},
{
"name": "endTime"
}
]
},
"toolDescription": "Appelez cet outil pour récupérer la disponibilité des rendez-vous.\nVous devez impérativement utiliser le fuseau horaire de Paris.\nRespectez strictement le format ISO pour les dates, par exemple :\n2025-01-01T09:00:00-02:00\nExemple de schéma d’entrée :\n{\n \"startTime\": \"...\",\n \"endTime\": \"...\"\n}",
"parametersHeaders": {
"values": [
{
"name": "Authorization",
"value": "Bearer cal_live_6cd60e462f8dc9b065fb48624e5918d8",
"valueProvider": "fieldValue"
},
{
"name": "Content-Type",
"value": "application/json",
"valueProvider": "fieldValue"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "5d8dc1ce-020f-4df3-88cc-7f61594a3347",
"name": "发送响应到 WhatsApp",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
700,
-460
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.1
},
{
"id": "5cd00123-c0ea-48f9-85e6-e496a0bd6620",
"name": "检索潜在客户详情",
"type": "n8n-nodes-base.googleSheets",
"position": [
-420,
140
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $('Webhook Trigger (WhatsApp Input)').item.json.body.contactId }}",
"lookupColumn": "ID du contact"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit#gid=0",
"cachedResultName": "mes RDV"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit?usp=drivesdk",
"cachedResultName": "MES RDV"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "9696140f-857f-42b6-9bb9-3d25f5d893d4",
"name": "标准化预约时间(UTC 格式)",
"type": "n8n-nodes-base.code",
"position": [
-200,
140
],
"parameters": {
"jsCode": "const input = $input.first().json['Date du rendez-vous']; // e.g.,\n\"2025-06-04T09:00:00+02:00\"\nfunction normalizeToUTCZFormat(dateString) {\ntry {\nif\n(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$/.test(dateString)\n) {\nreturn new Date(dateString).toISOString();\n}\nconst date = new Date(dateString);\nif (isNaN(date.getTime())) {\nthrow new Error(\"Invalid date format\");\n}\nreturn date.toISOString(); // Returns in UTC with Z\n} catch (e) {\nreturn `Invalid input: ${e.message}`;\n}\n}\nreturn [\n{\njson: {\noriginal: input,\nnormalized: normalizeToUTCZFormat(input),\n},\n},\n];"
},
"typeVersion": 2
},
{
"id": "6d2ef19a-93d1-46f1-bc31-ad1010d3bb4a",
"name": "发送预约",
"type": "n8n-nodes-base.httpRequest",
"position": [
20,
140
],
"parameters": {
"url": "https://api.cal.com/v2/bookings",
"method": "POST",
"options": {},
"jsonBody": "={\n\"eventTypeId\": {{ $('Retrieve Prospect Details').item.json['ID de l’événement'] }},\n\"start\": \"{{ $json.normalized }}\",\n\"attendee\": {\n\"name\": \"{{ $('Retrieve Prospect Details').item.json.Nom }}\",\n\"email\": \"{{ $('Retrieve Prospect Details').item.json.Courriel }}\",\n\"timeZone\": \"Europe/Paris\"\n},\n\"bookingFieldsResponses\": {\n\"title\": \"{{ $('Retrieve Prospect Details').item.json['Résumé'] }}\"\n}\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer cal_live_6cd60e462f8dc9b065fb48624e5918d8"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "cal-api-version",
"value": "2024-08-13"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "472dc55f-b42f-483f-b6cc-1f8c25f0158e",
"name": "格式化日期以便阅读(显示)",
"type": "n8n-nodes-base.code",
"position": [
240,
140
],
"parameters": {
"jsCode": "const input = $('Retrieve Prospect Details').first().json['Date du rendez-vous']; \nfunction formatToReadableDate(dateString) {\ntry {\nconst date = new Date(dateString);\nif (isNaN(date.getTime())) throw new Error(\"Invalid date\");\nconst options = {\ntimeZone: \"Europe/Berlin\", // Ensures correct local time\nmonth: \"long\",\nday: \"numeric\",\nhour: \"numeric\",\nminute: \"2-digit\",\nhour12: true,\n};\nconst formatted = date.toLocaleString(\"en-US\", options);\n// Example output: \"June 4, 09:00 AM\" → make it shorter like\n\"June 4, 9am\"\nreturn formatted\n.replace(\":00\", \"\") // remove :00 if exact hour\n.replace(\"AM\", \"am\")\n.replace(\"PM\", \"pm\");\n} catch (e) {\nreturn `Invalid input: ${e.message}`;\n}\n}\nreturn [\n{\njson: {\noriginal: input,\nformatted: formatToReadableDate(input),\n},\n},\n]; "
},
"typeVersion": 2
},
{
"id": "7f0f86bc-8199-4d81-8bce-e96ced534f6e",
"name": "检查预约状态(成功或错误)",
"type": "n8n-nodes-base.switch",
"position": [
460,
140
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "succeeded",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cbf9b691-0bc1-4a14-b35d-96664d82bc91",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Send Booking').item.json.status }}",
"rightValue": "success"
}
]
},
"renameOutput": true
},
{
"outputKey": "Failed",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f78214f9-ecd4-4913-aef0-9a2a453b052c",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Send Booking').item.json.status }}",
"rightValue": "error"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "108c9a6b-a345-4f33-ab22-113b6e63914b",
"name": "Webhook 响应:预约已确认",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
700,
-20
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "\n[\n{\n\"output\": \"Votre réservation a été effectuée avec succès. Vous recevrez bientôt un e-mail de confirmation pour votre massage, RDV : .\"\n}\n]"
},
"typeVersion": 1.1
},
{
"id": "8c3d9734-7aad-4445-9810-29d7045fbc78",
"name": "Webhook 响应:预约失败",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
700,
280
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "[\n{\n\"output\": \"Il semble que le créneau horaire que vous avez choisi ne soit plus disponible. Veuillez en sélectionner un autre.\"\n}\n]"
},
"typeVersion": 1.1
},
{
"id": "2a3ed659-5cec-497b-bde8-f6a15585cc41",
"name": "在表格中标记预约为已确认",
"type": "n8n-nodes-base.googleSheets",
"position": [
920,
140
],
"parameters": {
"columns": {
"value": {
"Réservé": "confirm",
"ID du contact": "={{ $('Retrieve Prospect Details').item.json['ID du contact'] }}"
},
"schema": [
{
"id": "Nom",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Courriel",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Courriel",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Numéro de téléphone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Numéro de téléphone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Résumé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Résumé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Réservé",
"type": "string",
"display": true,
"required": false,
"displayName": "Réservé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "ID de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date du rendez-vous",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Date du rendez-vous",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rappel SMS envoyé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Rappel SMS envoyé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID du contact",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID du contact",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID du contact"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit#gid=0",
"cachedResultName": "mes RDV"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit?usp=drivesdk",
"cachedResultName": "MES RDV"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "5bfa51a3-e939-41e8-a1df-b4e59c4feef1",
"name": "触发器:每小时检查预约",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-420,
580
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "0413b7b7-b523-4e22-ad4a-40d7342abed9",
"name": "从表格中读取即将到来的预约",
"type": "n8n-nodes-base.googleSheets",
"position": [
-200,
580
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit#gid=0",
"cachedResultName": "mes RDV"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsuURJg5nxVnb18OMDShjC-sTA9i_32pyBSjfswOpqc/edit?usp=drivesdk",
"cachedResultName": "MES RDV"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
},
{
"id": "408e1330-29e4-4de7-b681-1bb372b5f841",
"name": "筛选未来 2 小时内的预约",
"type": "n8n-nodes-base.code",
"position": [
20,
580
],
"parameters": {
"jsCode": "const nowParis = new Date(\n new Date().toLocaleString(\"en-US\", { timeZone: \"Europe/Paris\" })\n);\nconst nowTimestamp = nowParis.getTime();\nconst twoHoursFromNow = nowTimestamp + 2 * 60 * 60 * 1000;\n\nreturn items\n .filter(item => {\n const booked = item.json[\"Réservé\"]?.toLowerCase() === \"confirm\";\n const reminderSent = item.json[\"Rappel SMS envoyé\"]?.toLowerCase() === \"envoyer\";\n const rawDate = item.json[\"Date du rendez-vous\"];\n if (!booked || reminderSent || !rawDate) {\n return false;\n }\n\n const appointmentTimestamp = Date.parse(rawDate);\n return appointmentTimestamp > nowTimestamp &&\n appointmentTimestamp <= twoHoursFromNow;\n })\n .map(item => {\n const rawDate = item.json[\"Date du rendez-vous\"];\n const date = new Date(rawDate);\n if (isNaN(date.getTime())) {\n item.json.appointmentDisplayTime = \"(Invalid date)\";\n return item;\n }\n\n const options = {\n timeZone: \"Europe/Paris\",\n month: \"long\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true\n };\n\n const formatted = date.toLocaleString(\"en-US\", options)\n .replace(\":00\", \"\")\n .replace(\"AM\", \"AM\")\n .replace(\"PM\", \"PM\");\n\n item.json.appointmentDisplayTime = formatted;\n return item;\n });\n"
},
"typeVersion": 2
},
{
"id": "0a9d6747-85d2-400e-a9fd-b5768ae4605c",
"name": "发送 SMS 提醒",
"type": "n8n-nodes-base.sms77",
"position": [
240,
580
],
"parameters": {
"to": "={{ $('Read Upcoming Appointments from Sheet').item.json['Numéro de téléphone'] }}",
"message": "=Bonjour {{ $json.Nom }}, ceci est un petit rappel : votre rendez-vous pour {{ $json['Nom de l’événement'] }} est prévu dans les 2 prochaines heures ",
"options": {}
},
"credentials": {
"sms77Api": {
"id": "nC2L4tQyF03xEMAX",
"name": "seven account"
}
},
"typeVersion": 1
},
{
"id": "3a01ec5e-57ea-43ac-8e59-97d66e85454f",
"name": "在表格中标记 SMS 已发送",
"type": "n8n-nodes-base.googleSheets",
"position": [
460,
580
],
"parameters": {
"columns": {
"value": {
"ID du contact": "={{ $('Read Upcoming Appointments from Sheet').item.json['ID du contact'] }}",
"Rappel SMS envoyé": "envoyer"
},
"schema": [
{
"id": "Nom",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Courriel",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Courriel",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Numéro de téléphone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Numéro de téléphone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Résumé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Résumé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Réservé",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Réservé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Nom de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Nom de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID de l’événement",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "ID de l’événement",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Date du rendez-vous",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Date du rendez-vous",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rappel SMS envoyé",
"type": "string",
"display": true,
"required": false,
"displayName": "Rappel SMS envoyé",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ID du contact",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ID du contact",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"ID du contact"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "51us92xkOlrvArhV",
"name": "Google Sheets account"
}
},
"typeVersion": 4.5
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "5c82e86c-e3b2-4b70-b686-a782edbaee55",
"connections": {
"Send Booking": {
"main": [
[
{
"node": "Format Date for Readability (Display)",
"type": "main",
"index": 0
}
]
]
},
"Send SMS Reminder": {
"main": [
[
{
"node": "Mark SMS as Sent in Sheet",
"type": "main",
"index": 0
}
]
]
},
"AI Conversation Memory": {
"ai_memory": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "ai_memory",
"index": 0
}
]
]
},
"LLM: GPT-4o Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Retrieve Prospect Details": {
"main": [
[
{
"node": "Normalize Booking Time (UTC Format)",
"type": "main",
"index": 0
}
]
]
},
"Fetch Available Time Slots": {
"ai_tool": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "ai_tool",
"index": 0
}
]
]
},
"Switch: Confirm vs Chat Flow": {
"main": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "main",
"index": 0
}
],
[
{
"node": "Retrieve Prospect Details",
"type": "main",
"index": 0
}
]
]
},
"AI Booking Assistant (Dr Firas)": {
"main": [
[
{
"node": "Send Response to WhatsApp",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger (WhatsApp Input)": {
"main": [
[
{
"node": "Switch: Confirm vs Chat Flow",
"type": "main",
"index": 0
}
]
]
},
"Create New Prospect in Google Sheet": {
"ai_tool": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "ai_tool",
"index": 0
}
]
]
},
"Normalize Booking Time (UTC Format)": {
"main": [
[
{
"node": "Send Booking",
"type": "main",
"index": 0
}
]
]
},
"Webhook Response: Booking Confirmed": {
"main": [
[
{
"node": "Mark Booking as Confirmed in Sheet",
"type": "main",
"index": 0
}
]
]
},
"Update Prospect with Booking Details": {
"ai_tool": [
[
{
"node": "AI Booking Assistant (Dr Firas)",
"type": "ai_tool",
"index": 0
}
]
]
},
"Format Date for Readability (Display)": {
"main": [
[
{
"node": "Check Booking Status (Success or Error)",
"type": "main",
"index": 0
}
]
]
},
"Read Upcoming Appointments from Sheet": {
"main": [
[
{
"node": "Filter Appointments Within Next 2 Hours",
"type": "main",
"index": 0
}
]
]
},
"Trigger: Check Appointments Every Hour": {
"main": [
[
{
"node": "Read Upcoming Appointments from Sheet",
"type": "main",
"index": 0
}
]
]
},
"Check Booking Status (Success or Error)": {
"main": [
[
{
"node": "Webhook Response: Booking Confirmed",
"type": "main",
"index": 0
}
],
[
{
"node": "Webhook Response: Booking Failed",
"type": "main",
"index": 0
}
]
]
},
"Filter Appointments Within Next 2 Hours": {
"main": [
[
{
"node": "Send SMS Reminder",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 客户支持, 人工智能
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
通过WhatsApp + GPT-4 + Google Sheets自动化产品数据收集和客户支持
通过WhatsApp、GPT-4和Google Sheets自动化产品培训和客户支持
Code
Switch
Whats App
+8
20 节点Dr. Firas
客户支持
基于AI的MIS代理
基于AI的管理信息系统代理
If
Set
Code
+29
129 节点Kumar Shivam
客户支持
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
其他
ELEVEN LABS 多智能体系统
基于ElevenLabs、OpenAI和内容生成的语音驱动营销助手
If
Set
Webhook
+16
56 节点David Olusola
人工智能
宠物店 4
🐶 宠物店预约 AI 代理
If
Set
Code
+41
187 节点Bruno Dias
人工智能
[模板] AI宠物店 v8
🐶 AI宠物店助手 - 集成GPT-4o、Google日历和WhatsApp/Instagram/Facebook
If
N8n
Set
+38
244 节点Amanda Benks
销售
工作流信息
难度等级
高级
节点数量25
分类2
节点类型14
作者
Dr. Firas
@drfirasAutomation expert and certified trainer. I create hands-on courses to master automation with n8n. Contact me to access my exclusive training and start building powerful workflows today. 🚀
外部链接
在 n8n.io 查看 →
分享此工作流