8
n8n 中文网amn8n.com

牙科诊所接待员

中级

这是一个Support Chatbot, Multimodal AI领域的自动化工作流,包含 14 个节点。主要使用 If, Code, Gmail, Webhook, GoogleSheets 等节点。 使用 Google Calendar、AI 助手和邮件通知自动化牙科预约

前置要求
  • Google 账号和 Gmail API 凭证
  • HTTP Webhook 端点(n8n 会自动生成)
  • Google Sheets API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "SAqkCDqXBdN0UN0F",
  "meta": {
    "instanceId": "a419abc01bb0423bd41f1b0c0b1dc4e0a3c69d0074efa38bd450d30bc82d13ad",
    "templateCredsSetupCompleted": true
  },
  "name": "Dental Clinic Receptionist",
  "tags": [],
  "nodes": [
    {
      "id": "6cb4cb42-b5e8-446d-9711-d72649c8b6cc",
      "name": "Check Availability",
      "type": "n8n-nodes-base.googleCalendarTool",
      "position": [
        624,
        928
      ],
      "parameters": {
        "options": {},
        "timeMax": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End_Time', ``, 'string') }}",
        "timeMin": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start_Time', ``, 'string') }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "c4a4d22b1eaa9e3b8eb300569a8dc61d2eb88934c04fcb471639cf42ee93f8f5@group.calendar.google.com",
          "cachedResultName": "n8n"
        },
        "resource": "calendar"
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "l0D9Uok2v5Z8pc4U",
          "name": "Google Calendar account"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8b070be5-d1b2-4f02-99a4-6278450b9fe7",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        304,
        656
      ],
      "webhookId": "f416ff3e-0410-4538-a3ab-7b52dce5b470",
      "parameters": {
        "path": "getInput",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "69b5f76a-3c63-4e0c-b4cb-d52e7dc57cbf",
      "name": "响应Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        912,
        656
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "b55f6c71-39df-46f8-8439-2f6e3e125466",
      "name": "窗口缓冲内存",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        400,
        912
      ],
      "parameters": {
        "sessionKey": "={{ $json.body.chatId }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 100
      },
      "typeVersion": 1.3
    },
    {
      "id": "d48200d0-fbf4-4cef-bcd9-f0d9a6b66579",
      "name": "OpenRouter 聊天模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        240,
        896
      ],
      "parameters": {
        "model": "openai/gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "7pnW2IfzgeEN8qVd",
          "name": "OpenRouter account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "39947ea3-452c-4c93-bdaa-9639a16a574a",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        560,
        656
      ],
      "parameters": {
        "text": "={{ $json.body.query }}",
        "options": {
          "systemMessage": "=You are a virtual assistant specializing in appointment management for Dr. Hakim. \nYour role is to manage consultations accurately, ensuring real availability while providing a smooth experience for patients.\n\nOffice Hours:\n- Monday – Friday: 9:00 AM – 8:00 PM\n- Saturday: 9:00 AM – 1:00 PM\n- Sunday: Closed\n- Consultation Duration: 1 hour\n- Break Between Patients: 15 minutes\n\nBooking Process:\n1. Collect Patient Information:\n   - Full Name\n   - Phone Number\n   - Email Address\n   - Desired Date and Time\n   If any information is missing, politely ask the patient before proceeding.\n\n2. Availability Check:\n   - Always use the \"Check Availability\" tool to verify free slots in Google Calendar.\n   - If requested time overlaps with an existing appointment, suggest the next available slot.\n   - Do not create or confirm an appointment until the user explicitly approves the slot.\n\n3. Booking Confirmation:\n   - Only create the appointment using the \"Create Event\" tool after explicit user confirmation.\n   - Do not say \"appointment booked\" unless the tool is actually used.\n   - Appointment ID format: APT-YYYYMMDD-XXXXXX (6 random alphanumeric characters).\n   - Event Title: Patient Name - Phone Number\n   - Event Description: Include full name, phone, email, appointment ID, date & time.\n\nConfirmation Message Format:\nWhen booking is complete, return only this message:\n✅ Appointment Confirmed:\n- Full Name: {full_name}\n- Phone: {phone}\n- Email: {email}\n- Date: {date}\n- Time: {time}\n- Appointment ID: {appointment_id}\n\nDo NOT include:\n- Calendar event links\n- Extra text after the appointment ID\n- Any confirmation without Create Event tool usage\n\nCancellations:\nIf asked to cancel, reply: \"Please check your booking email. I cannot cancel appointments for you.\"\n\nVerification:\nIf asked to check an appointment by ID, reply: \"Check your email we sent when you booked.\"\n\nTools Available:\n- Check Availability → Verify free slots in Google Calendar\n- Create Event → Book confirmed appointment in Google Calendar\n\nCommunication Rules:\n- Always be polite, clear, and friendly.\n- Never assume missing details—ask for them.\n- Never create or cancel without explicit confirmation.\n- Stick strictly to availability check and booking after confirmation.\n\nToday's Date: {{ $now }}"
        },
        "promptType": "=define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "cd82287b-0ea8-4e15-a8da-9e5c4bb7bcb2",
      "name": "代码",
      "type": "n8n-nodes-base.code",
      "position": [
        1248,
        1024
      ],
      "parameters": {
        "jsCode": "// Get the AI Agent output (which is a JSON string)\nconst msg = $input.first().json.output || \"\";\n\nif (!msg) {\n  throw new Error(\"AI Agent output not found.\");\n}\n\n// Parse the JSON string\nlet data;\ntry {\n  data = JSON.parse(msg);\n} catch (err) {\n  throw new Error(\"Failed to parse AI Agent output as JSON: \" + err.message);\n}\n\n// Fallback Appointment ID if missing\nif (!data.appointment_id || data.appointment_id === \"null\") {\n  const randomId = Math.random().toString(36).substring(2, 8).toUpperCase();\n  data.appointment_id = `APT-${randomId}`;\n}\n\nreturn [{ json: data }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2e634902-e4ce-4362-8ca2-5fa1bb4ebd73",
      "name": "如果",
      "type": "n8n-nodes-base.if",
      "position": [
        1456,
        1024
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f1cbfa92-a423-4baf-8ab1-f8cc8ab77038",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.patient.full_name }}",
              "rightValue": "null"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "cd01ecc0-431a-4c8b-a703-dbcef7075fcd",
      "name": "在表格中追加行",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1152,
        1232
      ],
      "parameters": {
        "columns": {
          "value": {
            "Time": "={{ $json.appointment.time }}",
            "Date ": "={{ $json.appointment.date }}",
            "Email": "={{ $json.patient.email }}",
            "Name ": "={{ $json.patient.full_name }}",
            "Phone Number": "={{ $json.patient.phone }}",
            "Appointment ID": "={{ $json.appointment_id }}"
          },
          "schema": [
            {
              "id": "Appointment ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Appointment ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name ",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date ",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/13HOoBmWcxkL8cUZtWFU1-BSY47v486qkfGCA3gE8PKw/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "13HOoBmWcxkL8cUZtWFU1-BSY47v486qkfGCA3gE8PKw",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/13HOoBmWcxkL8cUZtWFU1-BSY47v486qkfGCA3gE8PKw/edit?usp=drivesdk",
          "cachedResultName": "dr"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "5Gf7cbek4NAixfUR",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ac1a8cc3-7d80-4885-8360-0dce48b2af89",
      "name": "For Doctor",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1376,
        1232
      ],
      "webhookId": "297d8c21-35f3-4a69-ab0f-b7497a7a4d73",
      "parameters": {
        "sendTo": "mdsabirulislam8089@gmail.com",
        "message": "=Hello Dr. Hakim,\nA new appointment has been scheduled. Here are the details:  \nPatient Name: {{ $json['Name '] }}\nPhone Number: {{ $json['Phone Number'] }}\nEmail: {{ $json.Email }} \nAppointment Date: {{ $json['Date '] }} \nTime: {{ $json.Time }}\nAppointment ID:{{ $json['Appointment ID'] }} \nPlease check your Google Calendar for more details.",
        "options": {
          "appendAttribution": false
        },
        "subject": "New Appointment Scheduled",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "vDrwiQhkGDt03Qyw",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "88e1c616-7014-4d49-8d32-fe9c77f85d86",
      "name": "For User",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1632,
        1232
      ],
      "webhookId": "79c1900a-988d-400f-9d84-b867f441821f",
      "parameters": {
        "sendTo": "={{ $('Append row in sheet').item.json.Email }}",
        "message": "=Dear {{ $('Append row in sheet').item.json['Name '] }},\nYour appointment with Dr. Hakim has been successfully booked!  Here are the details:  \nName: {{ $('Append row in sheet').item.json['Name '] }}\nPhone Number: {{ $('Append row in sheet').item.json['Phone Number'] }}\nEmail: {{ $('Append row in sheet').item.json.Email }}\nAppointment Date: {{ $('Append row in sheet').item.json['Date '] }}\nTime: {{ $('Append row in sheet').item.json.Time }}\nAppointment ID:{{ $('Append row in sheet').item.json['Appointment ID'] }}\nPlease keep this Appointment ID for your reference.  If you have any questions or need to cancel your appointment, feel free to contact us. \nBest regards, \nDr. Hakim's Clinic",
        "options": {
          "appendAttribution": false
        },
        "subject": "Appointment Confirmation – Dr. Hakim",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "vDrwiQhkGDt03Qyw",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "7eec2403-de34-4163-8984-3c5f6be8070c",
      "name": "Creat event",
      "type": "n8n-nodes-base.googleCalendarTool",
      "position": [
        832,
        912
      ],
      "parameters": {
        "end": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', ``, 'string') }}",
        "start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', ``, 'string') }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "c4a4d22b1eaa9e3b8eb300569a8dc61d2eb88934c04fcb471639cf42ee93f8f5@group.calendar.google.com",
          "cachedResultName": "n8n"
        },
        "additionalFields": {}
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "l0D9Uok2v5Z8pc4U",
          "name": "Google Calendar account"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "ab252537-767c-477d-9a0b-941bd4ed8558",
      "name": "AI Agent1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1168,
        656
      ],
      "parameters": {
        "text": "={{$input.first().json.output}}",
        "options": {
          "systemMessage": "You are an Appointment Parsing Agent.\nYour job is to extract appointment details from text and return them as clean JSON.\n\n🔹 Rules\n\nAlways return data strictly in this JSON format:\n\n{\n  \"patient\": {\n    \"full_name\": \"John Doe\",\n    \"phone\": \"123456789\",\n    \"email\": \"john@example.com\"\n  },\n  \"appointment\": {\n    \"date\": \"29th August 2025\",\n    \"time\": \"5 PM\"\n  },\n  \"appointment_id\": \"APT20250831KY5T4N\"\n}\n\n\nAppointment ID:\n\nIf provided, return it exactly as-is.\n\nDo not add extra text (e.g. \"this is a unique ID for your appointment\").\n\nIf missing, generate one in this format:\n\nAPT + YYYYMMDD + 5 random alphanumeric characters\n\n\nExample: APT20250831KY5T4N\n\nAll fields must always be present in JSON:\n\npatient.full_name\n\npatient.phone\n\npatient.email\n\nappointment.date\n\nappointment.time\n\nappointment_id\n\nIf a value is missing, set it to \"null\" (string).\n\nOutput only valid JSON. No explanations, no Markdown, no extra text."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "f07a734c-618e-47a7-81d0-2a8f771f7fe1",
      "name": "OpenRouter 聊天模型1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1040,
        848
      ],
      "parameters": {
        "model": "openai/gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "7pnW2IfzgeEN8qVd",
          "name": "OpenRouter account"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "timezone": "Europe/Rome",
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1"
  },
  "versionId": "0fac2f0e-7ed9-4fbc-91c8-c318f819b03c",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Append row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "For Doctor": {
      "main": [
        [
          {
            "node": "For User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Creat event": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Check Availability": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Respond to Webhook": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet": {
      "main": [
        [
          {
            "node": "For Doctor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

中级 - 客服机器人, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
中级
节点数量14
分类2
节点类型10
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

外部链接
在 n8n.io 查看

分享此工作流