다단계 도구 실행이 가능한 AI 기반 HVAC 스케줄링 에이전트
고급
이것은Support Chatbot, AI Chatbot분야의자동화 워크플로우로, 30개의 노드를 포함합니다.주로 Wait, Gmail, Webhook, GoogleChat, Agent 등의 노드를 사용하며. AI 에이전트, Google 캘린더 및 Gmail을 통한 HVAC 서비스 스케줄링 자동화
사전 요구사항
- •Google 계정 및 Gmail API 인증 정보
- •HTTP Webhook 엔드포인트(n8n이 자동으로 생성)
- •Google Sheets API 인증 정보
- •OpenAI API Key
사용된 노드 (30)
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
"id": "TO2hDehR19idos0A",
"meta": {
"instanceId": "766c8c237f056d009bb1bd53e73633458b146427b1ae9c6ec10561694aa89152",
"templateCredsSetupCompleted": true
},
"name": "AI-Powered HVAC Scheduling Agent with Multi-Step Tool Execution",
"tags": [],
"nodes": [
{
"id": "2ccf6d62-a308-4a3e-8b82-a376de5e0b92",
"name": "webhook_trigger",
"type": "n8n-nodes-base.webhook",
"position": [
0,
112
],
"webhookId": "4fe15a31-6365-4b96-a3d5-3b02bbe3d31a",
"parameters": {
"path": "4fe15a31-6365-4b96-a3d5-3b02bbe3d31a",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"executeOnce": false,
"typeVersion": 2,
"alwaysOutputData": false
},
{
"id": "d42e76fa-26df-4be2-be3c-e2a8a88c4531",
"name": "think",
"type": "@n8n/n8n-nodes-langchain.toolThink",
"position": [
576,
224
],
"parameters": {},
"typeVersion": 1
},
{
"id": "34c5f195-f586-44f8-bf7c-1809b5095c21",
"name": "respond_to_webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1760,
112
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "dd362a16-58ab-4fa0-abee-f57c99891767",
"name": "simple-memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
448,
224
],
"parameters": {
"sessionKey": "=={{ $('webhook_trigger').item.json.headers['x-real-ip'] }}",
"sessionIdType": "customKey",
"contextWindowLength": 10
},
"typeVersion": 1.3
},
{
"id": "92934f03-f69c-48dc-9f9b-c7424656396a",
"name": "OpenAI 채팅 모델",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
288,
224
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "HlWDdupQ9GCmRi7F",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"name": "Receptionist",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
784,
0
],
"parameters": {
"text": "=## Request Data\n\n{{ JSON.stringify($json.body, null, 2)}}\n",
"options": {
"systemMessage": "=## Role\n\nYou are the AI scheduling manager for **ABC HVAC Services**. Your task is to process the request data received from the external voice agent. You must make a decision about the data you receive and make a call into the appropriate tool in order to process this request and return the appropriate data necessary.\n\n**For your accurate time context, the current date and time is: {{ $now.format('dddd, MMMM D, YYYY h:mm:ss A Z') }}.**\n\n**The next action is determined by the 'tool_request' value, which is: {{ $json.body.tool_request }}.**\n\nPay close attention to the constraints for number of times a tool is able to be used.\n\nYou have secure access to the following internal tools:\n - `think` → you MUST use this to think carefully about how to handle the provided request data. This tool must be used on every turn and tool call interaction.\n - `check_calendar` → checks the availability on the Technician Scheduling Calendar for a given **2-hour service window**.\n - If the request is for availability, you MUST call this tool multiple times to find **AT LEAST 2 available timeslots** if they exist.\n - **Matches the 'check_availability' value in the request.**\n - **`book_appointment`** → creates a **2-hour service appointment event**. This tool may only be called **ONCE (1 time)** in a given request. Do NOT use this tool multiple times. **Matches the 'book_appointment' value in the request.** If you use this tool more than once, your task will be considered a FAILURE.\n - `log_lead` → logs the provided customer details and appointment details to the central Google Sheet. This should ONLY be called and used **ONCE** per request after a booking is successful. If you use this tool more than once, your task will be considered a FAILURE.\n - `find_old_event` → searches the calendar using the 'Get Many' operation (based on the customer's email) to locate an existing appointment. The Agent MUST analyze the returned events and extract the unique **'id'** field of the correct event.\n - `reschedule_appointment` → uses the 'Update' operation to change the date and time of an existing service appointment. This tool **REQUIRES the Event ID** retrieved from `find_old_event`. **Matches the 'reschedule_appointment' value in the request.**\n - **`cancel_appointment`** → deletes an existing service appointment from the calendar. This tool **REQUIRES the Event ID** retrieved from `find_old_event`. **Matches the 'cancel_appointment' value in the request.**\n\n\n## Date and Time Handling\nThe LLM Agent (Receptionist) is responsible for ensuring all 'requested\\_date' and 'requested\\_time' parameters passed to the Google Calendar tools (`check_calendar`, **`book_appointment`**, `reschedule_appointment`) are **complete and valid ISO 8601 strings**. If the customer omits the year (e.g., \"book for December 15th\"), the Agent MUST infer the year based on the current context year (2025) and ensure the final timestamp is correctly structured.\n\n\n## CRITICAL Execution Rules\n\n### Execution Rule for Rescheduling:\n\nIf the tool\\_request value is **'reschedule_appointment'**, the Agent must execute the following sequence to **ensure the new time is available**:\n\n1. **Call `find_old_event`** to search the calendar and retrieve the event list.\n2. **Call `think`** to confirm the correct Event ID was extracted from the list.\n3. **Call `check_calendar`** to verify the availability of the proposed new date and time from the request.\n4. **Analyze Result:**\n * If **`check_calendar`** confirms the new slot is **available**, proceed to step 5.\n * If **If `check_calendar` confirms the new slot is occupied**, the Agent MUST inform the user and suggest alternative times (by calling `check_calendar` multiple times).\n5. If available, **Call `reschedule_appointment`** using the extracted Event ID and the new date/time.\n6. **Call `log_lead`** to append the updated appointment details (new date/time) to the central Google Sheet.\n\n\n### Execution Rule for Verification:\n\nIf the tool\\_request value is **'verify_booking'**, the Agent must execute the following sequence:\n\n1. **Call `find_old_event`** using the **customer's email** to search the calendar and retrieve the existing appointment event details.\n2. **Analyze Result:**\n * If a booking is found, the Agent MUST return a natural language response to the user stating the existing appointment time (e.g., \"I see your current appointment is on Monday at 2 PM.\").\n * If no booking is found, the Agent MUST inform the user and suggest starting a new booking process (using the 'check_availability' logic).\n\n\n### Execution Rule for Cancellation:\n\nIf the tool\\_request value is **'cancel_appointment'**, the Agent must execute the following sequence:\n\n1. **Call `find_old_event`** to search the calendar and retrieve the event list.\n2. **Call `think`** to confirm the correct Event ID was extracted from the list.\n3. **Call `cancel_appointment`** using the extracted Event ID.\n4. The Agent MUST return a confirmation message to the user that the appointment has been successfully cancelled.\n\n### Execution Rule for Book Appointment:\n\nIf the tool_request value is **'book_appointment'**, the Agent must execute the following sequence to **ensure the requested time is available**:\n\n1. **Call `check_calendar`** to verify the availability of the requested date and time from the request.\n2. **Analyze Result:**\n * If **`check_calendar`** confirms the requested slot is **available**, proceed to step 3.\n * If **`check_calendar`** confirms the requested slot is **occupied**, the Agent MUST inform the user and suggest alternative times (by calling `check_calendar` multiple times).\n3. If available, **Call `book_appointment`** using the customer details and the confirmed date/time.\n4. **Call `log_lead`** to append the new appointment details to the central Google Sheet.\n\n\n### Special Instructions for check_calendar Tool\n\nWhen handling availability requests:\n1. **Always aim to return 2 available timeslots** when possible.\n2. **Call check_calendar multiple times** to check different time slots on the requested date.\n3. **Appointment Duration:** Remember all appointments are **2 hours** long.\n4. **Search strategy:**\n- Start with the requested time (if provided) **({{ $json.body.requested_time }})**.\n- Check nearby times in 1-hour increments.\n- Continue checking until you find 2 available slots OR exhaust reasonable options.\n5. **Response format:** Return an array of available timeslots in ISO format (Asia/Kolkata Time Zone **IST**):\n\n```json\n\n{\n\n\"availableSlots\": [\n\n\"2025-10-15T10:00:00+05:30\",\n\n\"2025-10-15T14:00:00+05:30\"\n\n]\n\n}\n\n```\n\n6. **If fewer than 2 slots are found:** Return whatever available slots you found (even if just 1).\n7. **Business hours assumption:** Check times between **9:00 AM and 6:00 PM** unless specified otherwise.\n\n\n\nRemember: All times are in **Asia/Kolkata Time Zone (IST)**."
},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "d33ce44a-5f2b-4529-9ec9-27d7a442c334",
"name": "check_calendar",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
976,
224
],
"parameters": {
"options": {
"timezone": {
"__rl": true,
"mode": "list",
"value": "Asia/Kolkata",
"cachedResultName": "Asia/Kolkata"
}
},
"timeMax": "={{ $fromAI('End_Time', `The end time will always be the Start Time plus 2 hour.`, 'string') }}",
"timeMin": "={{ $fromAI('Start_Time', `The start timestamp for the HVAC service.`, 'string') }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "bhuvaneshx13@gmail.com",
"cachedResultName": "bhuvaneshx13@gmail.com"
},
"resource": "calendar"
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "ihLx42tSngHdiCuN",
"name": "Google Calendar account"
}
},
"typeVersion": 1.3
},
{
"id": "10dd7349-cb7e-4ac1-ba9b-fe62bc9bac39",
"name": "log_lead",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
592,
432
],
"parameters": {
"columns": {
"value": {
"Date": "={{ $now.format('yyyy-MM-dd') }}",
"Email": "={{ $json.body.customer_email }}",
"Address": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Address', `The is the customer's address to book an appointment.`, 'string') }}",
"Customer Name": "={{ $json.body.customer_name }}",
"Service Issue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Service_Issue', ``, 'string') }}",
"Call Timestamp": "={{ $now.format(\"HH':'mm\") }}",
"Appointment Date & Time": "={{ $json.body.requested_time.slice(0,5) }}, on {{ $json.body.requested_date }}"
},
"schema": [
{
"id": "Date",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Call Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Call Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Customer Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Address",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Service Issue",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Service Issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Appointment Date & Time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Appointment Date & Time",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Customer Name"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8/edit?usp=drivesdk",
"cachedResultName": "HVAC log lead"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "jBABhxE6xPp1vBwL",
"name": "Google Sheets account"
}
},
"typeVersion": 4.6
},
{
"id": "f0359235-d7c0-471d-afa7-b310ca518c1e",
"name": "log_lead_trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
400,
1584
],
"parameters": {
"event": "rowAdded",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1oirzmmRnnlpzcjO0A9-7rA8_l_K48I5d7XLp0V7d3U8/edit?usp=drivesdk",
"cachedResultName": "HVAC log lead"
}
},
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"id": "rKHEfkn9dZjqqr8h",
"name": "Google Sheets Trigger account"
}
},
"typeVersion": 1
},
{
"id": "2319722d-88c4-45af-9d43-0a9e28c574de",
"name": "find_old_event",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
832,
448
],
"parameters": {
"options": {
"query": "={{ $json.body.customer_email }}",
"orderBy": "startTime"
},
"calendar": {
"__rl": true,
"mode": "list",
"value": "bhuvaneshx13@gmail.com",
"cachedResultName": "bhuvaneshx13@gmail.com"
},
"operation": "getAll",
"returnAll": true
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "ihLx42tSngHdiCuN",
"name": "Google Calendar account"
}
},
"typeVersion": 1.3
},
{
"id": "13b5af09-dc4f-41f0-ad1d-b2a6a779def9",
"name": "reschedule_appointment",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
1312,
224
],
"parameters": {
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The event ID extracted from find_old_event. `, 'string') }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "bhuvaneshx13@gmail.com",
"cachedResultName": "bhuvaneshx13@gmail.com"
},
"operation": "update",
"updateFields": {
"end": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', `This is the end time for the HVAC appointment. This should be 2 hour AFTER the start time. This will be in the Indian Standard Time Zone (IST).`, 'string') }}",
"start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', `This is the end time for the HVAC appointment. This will be in the Indian Standard Time Zone (IST).`, 'string') }}"
}
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "ihLx42tSngHdiCuN",
"name": "Google Calendar account"
}
},
"typeVersion": 1.3
},
{
"id": "56ac1673-24cb-476b-8505-067c75dfc177",
"name": "Compose a mail",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"position": [
848,
1440
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "claude-opus-4-20250514",
"cachedResultName": "claude-opus-4-20250514"
},
"options": {},
"messages": {
"values": [
{
"content": "=Please generate the confirmation email using this booking information:\nCustomer Name: {{ $json[\"Customer Name\"] }}\nAppointment Time: {{ $json['Appointment Time'] }}\nAppointment Date: {{ $json.Date }}\nService Issue: {{ $json[\"Service Issue\"] }}"
},
{
"role": "assistant",
"content": "## Role\nYou are a highly efficient and polite administrative assistant for **ABC HVAC Services**. Your sole task is to generate the complete body of a personalized appointment confirmation email.\n\n## Constraints\n1. **Do NOT include a Subject Line, Signature Block, or any salutations/closings.** Only output the required email body content.\n2. Use a friendly and professional tone.\n3. The service time is always 2 hours.\n4. **CRITICAL:** You must convert the provided Appointment Date (YYYY-MM-DD) and Appointment Time (HH:MM) into a single, natural language string for the email (e.g., \"Thursday, October 16, 2025, at 4:00 PM IST\").\n5. Reference the provided customer data precisely.\n6. Don't mention the example output (that I gave you) in the output you generate.\n\n## Output Format (Email Template)\nGenerate the email body using the following template. Replace the bracketed placeholders with the actual data provided in the user message.\n\nHi [Customer Name],\n\nThis email confirms your service appointment with ABC HVAC Services.\n\nAppointment Details:\n1) Service Date & Time: [Formatted Date and Time]\n2) Service Duration: 2 hours\n3) Reported Issue: [Service Issue]\n\nA certified technician will arrive during the confirmed window. Please ensure there is clear access to your HVAC unit.\n\nIf you need to reschedule, please call us immediately at 555-0123.\n\nWe look forward to servicing your home!"
}
]
}
},
"credentials": {
"anthropicApi": {
"id": "CFRCoeDLcmUNPQT7",
"name": "Anthropic account"
}
},
"typeVersion": 1
},
{
"id": "80b630b7-7717-4b5f-89f1-c383e093e701",
"name": "booking_confirmation",
"type": "n8n-nodes-base.gmail",
"position": [
1200,
1440
],
"webhookId": "64196f69-bf10-40ae-9884-3c59723d896b",
"parameters": {
"sendTo": "={{ $('log_lead_trigger').item.json.Email }}",
"message": "={{ $json.content[0].text }}",
"options": {},
"subject": "re: Appointment Booked with ABC HVAC Services!",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "PJrUDp0UTEVBDOMT",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "21ca1911-48cf-454a-90a9-7066a6220575",
"name": "대기",
"type": "n8n-nodes-base.wait",
"position": [
848,
1696
],
"webhookId": "e35977e3-a248-4884-8450-2ab2d7450638",
"parameters": {
"unit": "minutes",
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "d33aaad1-0ba4-46df-9a3c-0391bb606c59",
"name": "cancel_appointment",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
1488,
224
],
"parameters": {
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The event ID extracted from find_old_event. `, 'string') }}",
"options": {},
"calendar": {
"__rl": true,
"mode": "list",
"value": "bhuvaneshx13@gmail.com",
"cachedResultName": "bhuvaneshx13@gmail.com"
},
"operation": "delete"
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "ihLx42tSngHdiCuN",
"name": "Google Calendar account"
}
},
"typeVersion": 1.3
},
{
"id": "46241300-0c37-49d3-8806-448974811dbf",
"name": "book_appointment",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
1136,
224
],
"parameters": {
"end": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', `End time for the HVAC service. This should be 2 hour AFTER the start time. This will be in the Indian Standard Time Zone (IST).`, 'string') }}",
"start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', `Start time for the HVAC appointment. This will be in the Indian Standard Time Zone (IST).`, 'string') }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "bhuvaneshx13@gmail.com",
"cachedResultName": "bhuvaneshx13@gmail.com"
},
"additionalFields": {
"summary": "=Service appointment with {{ $json.body.customer_name }}",
"attendees": [
"={{ $json.body.customer_email }}"
],
"description": "={{ $json.body.customer_issue }}"
}
},
"credentials": {
"googleCalendarOAuth2Api": {
"id": "ihLx42tSngHdiCuN",
"name": "Google Calendar account"
}
},
"typeVersion": 1.3
},
{
"id": "8ec1fc4a-f8ae-4695-ab07-93d18e31c996",
"name": "메모",
"type": "n8n-nodes-base.stickyNote",
"position": [
-784,
-400
],
"parameters": {
"width": 576,
"height": 656,
"content": "# HVAC Scheduling Agent\nThis n8n template creates an AI Scheduling Agent for ABC HVAC Services using multiple tools to manage customer appointments.\n\n## **How it works:**\n\n* A webhook\\_trigger receives a customer request, typically from an external voice or text agent.\n \n* The **Receptionist Agent** (powered by Gemini/OpenAI) uses a system prompt with strict rules to decide which tool to call: check\\_calendar, book\\_appointment, reschedule\\_appointment, cancel\\_appointment, or find\\_old\\_event.\n \n* A simple-memory node gives the agent a short-term conversational context.\n \n* The Agent outputs a response via respond\\_to\\_webhook (e.g., confirming a booking or asking a follow-up question).\n \n* **Asynchronous Logging & Confirmation:** A separate sub-workflow (triggered by log\\_lead\\_trigger) fires after a successful booking to send a confirmation email and an internal Google Chat notification.\n \n\n## **Key Constraints:**\n\n* All appointments are fixed at **2 hours**.\n \n* All times must be converted to **ISO 8601** format in the **Asia/Kolkata Time Zone (IST)**.\n \n* book\\_appointment and log\\_lead can only be called **ONCE** per request."
},
"typeVersion": 1
},
{
"id": "d108f20e-1067-41e1-8f07-1be7cfb2726d",
"name": "메모1",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
-304
],
"parameters": {
"color": 2,
"width": 1376,
"height": 688,
"content": "## AI Agent Core Logic & Tool Constraints\nThis block contains the core LLM (OpenAI Chat Model) and its memory (simple-memory) which feeds into the **Receptionist Agent**.\n\n### **CRITICAL Execution Rules:**\n\n* **Availability (check_calendar):** Must be called multiple times to find **AT LEAST 2** available 2-hour slots, if available.\n \n* **Booking Sequence (book_appointment):** → check_calendar (Verify) → book_appointment → log_lead.\n \n* **Reschedule Sequence (reschedule_appointment):** → find_old_event (Get ID) → check_calendar (Verify New Slot) → reschedule_appointment → log_lead.\n \n* **Cancellation Sequence (cancel_appointment):** → find_old_event (Get ID) → cancel_appointment."
},
"typeVersion": 1
},
{
"id": "120da344-4834-4be9-b2ed-a8360f192280",
"name": "메모2",
"type": "n8n-nodes-base.stickyNote",
"position": [
784,
416
],
"parameters": {
"color": 2,
"width": 832,
"height": 480,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Event ID Lookup (find_old_event)\nThis node searches the calendar to find an existing event using the **customer's email** ($json.body.customer\\_email).\n\n### **REQUIRED for:**\n* reschedule\\_appointment (to get the Event ID to update).\n \n* cancel\\_appointment (to get the Event ID to delete).\n \n* verify\\_booking requests (to confirm the existing time)."
},
"typeVersion": 1
},
{
"id": "fd59daab-b6ae-4535-bb74-d2e976c47443",
"name": "메모3",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
416
],
"parameters": {
"color": 2,
"width": 512,
"height": 480,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Lead Logging (log_lead)\nAppends customer and appointment details to the \"HVAC log lead\" Google Sheet.\n\n### **Critical Rule:** \nThis tool is the **ONLY** way to trigger the asynchronous post-booking confirmation workflow (Email and Chat notification). It must be called after a successful **booking** or **reschedule** and **ONLY ONCE** per request."
},
"typeVersion": 1
},
{
"id": "f895d446-0051-48e0-9483-7bc349ad9a1a",
"name": "메모4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-160,
-400
],
"parameters": {
"color": 7,
"width": 2176,
"height": 1376,
"content": "\n# STEP 1"
},
"typeVersion": 1
},
{
"id": "c1b8440b-8874-463d-893f-3555200e7b9a",
"name": "메모5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-160,
1040
],
"parameters": {
"color": 7,
"width": 2176,
"height": 1104,
"content": "\n# STEP 2"
},
"typeVersion": 1
},
{
"id": "4eb412e9-cec2-42fb-bf22-33b69bebb445",
"name": "메모6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-784,
1040
],
"parameters": {
"width": 576,
"height": 416,
"content": "# Post-Booking Confirmation Pipeline\n\nThis is an **asynchronous** workflow that runs _after_ a booking is successfully written to the Google Sheet by the log\\_lead tool.\n\n## **Sequence of Actions:**\n\n1. **log\\_lead\\_trigger**: Fires on new Google Sheet row.\n \n2. **Compose a mail**: Uses Anthropic to generate a personalized email body.\n \n3. **booking\\_confirmation**: Sends the final email to the customer.\n \n4. **Wait**: (Optional) Pause before internal notification.\n \n5. **Create a message**: Sends an internal alert to a Google Chat space."
},
"typeVersion": 1
},
{
"id": "803fa3dd-75e5-46a3-b009-c9c04243e8bc",
"name": "메모7",
"type": "n8n-nodes-base.stickyNote",
"position": [
256,
1376
],
"parameters": {
"width": 400,
"height": 512,
"content": "## **Trigger**\nThis node waits for a **'rowAdded'** event in the \"HVAC log lead\" Google Sheet.\n\n**Purpose:** It ensures the post-booking actions (Email and Chat notification) only fire **after** the log\\_lead tool in the main agent workflow has successfully logged the appointment details.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n**Data Access:** The subsequent nodes access the booking details (like Customer Name, Email, Date, Time) from this node's output: $('log\\_lead\\_trigger').item.json.Email."
},
"typeVersion": 1
},
{
"id": "c387f635-2efd-4668-9b21-e0bc36ac5018",
"name": "메모8",
"type": "n8n-nodes-base.stickyNote",
"position": [
688,
1136
],
"parameters": {
"color": 2,
"width": 928,
"height": 496,
"content": "## **Email Generation & Confirmation Send**\nThis sequence handles the customer-facing confirmation. The **Compose a mail** node uses the Anthropic LLM (claude-opus-4-20250514) to generate the email body.\n\n**Key Steps:**\n\n* The LLM prompt strictly enforces a confirmation template and handles **time formatting**, converting raw date/time into a natural language string (e.g., \"Thursday, October 16, 2025, at 4:00 PM IST\").\n \n* The **booking\\_confirmation** node sends the email via Gmail.\n \n* **Data Mapping:** It retrieves the customer's email from the trigger node ($('log\\_lead\\_trigger').item.json.Email) and uses the generated text from the previous node as the email message."
},
"typeVersion": 1
},
{
"id": "bb9dee76-f95b-435a-9a7b-3c61ce6d6737",
"name": "메모9",
"type": "n8n-nodes-base.stickyNote",
"position": [
688,
1664
],
"parameters": {
"color": 2,
"width": 928,
"height": 416,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## **Internal Alert Delay & Notification**\nThis sequence ensures internal teams are notified of the new appointment.\n\n* The **Wait** node introduces a mandatory **2-minute delay**. This is often used to ensure all customer-facing communications are complete before alerting internal teams or to account for any data sync lag.\n \n* The **message_team** node sends an internal alert to a **Google Chat space**.\n "
},
"typeVersion": 1
},
{
"id": "1c5e21d0-2e8c-4ada-8149-6d595e0fdcfa",
"name": "message_team",
"type": "n8n-nodes-base.googleChat",
"position": [
1056,
1696
],
"webhookId": "85d2c83a-f3c6-47a9-8f2b-81292ef4faf4",
"parameters": {
"spaceId": "=",
"messageUi": {
"text": "Type any message you would want to alert your team!"
},
"authentication": "oAuth2",
"additionalFields": {}
},
"credentials": {
"googleChatOAuth2Api": {
"id": "as0PGLyO7pHSKOr2",
"name": "Chat account"
}
},
"typeVersion": 1
},
{
"id": "5024afe7-0336-4113-861b-e12185794c2e",
"name": "메모10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
-64
],
"parameters": {
"width": 304,
"height": 336,
"content": "## Webhook Trigger\nThis node is the starting point for the entire workflow. It waits for an external HTTP **POST** request, typically from an external voice or conversational agent.\n"
},
"typeVersion": 1
},
{
"id": "c3636b1e-a2cf-4763-bc79-100043767eba",
"name": "메모11",
"type": "n8n-nodes-base.stickyNote",
"position": [
1648,
-64
],
"parameters": {
"width": 320,
"height": 336,
"content": "## Respond to Webhook \nThis node is the final action in the Agent's primary execution path. It sends the AI Agent's natural language response back to the original caller (e.g., the external voice agent)."
},
"typeVersion": 1
},
{
"id": "78320267-cb8b-4a66-a18e-910be28a66c9",
"name": "메모12",
"type": "n8n-nodes-base.stickyNote",
"position": [
2096,
-400
],
"parameters": {
"color": 5,
"width": 400,
"height": 368,
"content": "# Hello there!\n\n\n\n# Need support or have a workflow question? \n\n## 🔗 [Connect on LinkedIn](https://www.linkedin.com/in/bhuvaneshhhh/)"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"timezone": "Asia/Kolkata",
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1"
},
"versionId": "a8ebce93-e3e0-4b48-90c3-bbe148d31357",
"connections": {
"Wait": {
"main": [
[
{
"node": "1c5e21d0-2e8c-4ada-8149-6d595e0fdcfa",
"type": "main",
"index": 0
}
]
]
},
"d42e76fa-26df-4be2-be3c-e2a8a88c4531": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"10dd7349-cb7e-4ac1-ba9b-fe62bc9bac39": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"6792bc09-e55c-47e8-b6c0-9d58ce470023": {
"main": [
[
{
"node": "34c5f195-f586-44f8-bf7c-1809b5095c21",
"type": "main",
"index": 0
}
]
]
},
"dd362a16-58ab-4fa0-abee-f57c99891767": {
"ai_memory": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_memory",
"index": 0
}
]
]
},
"56ac1673-24cb-476b-8505-067c75dfc177": {
"main": [
[
{
"node": "80b630b7-7717-4b5f-89f1-c383e093e701",
"type": "main",
"index": 0
}
]
]
},
"d33ce44a-5f2b-4529-9ec9-27d7a442c334": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"2319722d-88c4-45af-9d43-0a9e28c574de": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"2ccf6d62-a308-4a3e-8b82-a376de5e0b92": {
"main": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "main",
"index": 0
}
]
]
},
"46241300-0c37-49d3-8806-448974811dbf": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"f0359235-d7c0-471d-afa7-b310ca518c1e": {
"main": [
[
{
"node": "56ac1673-24cb-476b-8505-067c75dfc177",
"type": "main",
"index": 0
},
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"d33aaad1-0ba4-46df-9a3c-0391bb606c59": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
},
"80b630b7-7717-4b5f-89f1-c383e093e701": {
"main": [
[]
]
},
"13b5af09-dc4f-41f0-ad1d-b2a6a779def9": {
"ai_tool": [
[
{
"node": "6792bc09-e55c-47e8-b6c0-9d58ce470023",
"type": "ai_tool",
"index": 0
}
]
]
}
}
}자주 묻는 질문
이 워크플로우를 어떻게 사용하나요?
위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.
이 워크플로우는 어떤 시나리오에 적합한가요?
고급 - 지원 챗봇, AI 챗봇
유료인가요?
이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.
관련 워크플로우 추천
시각화 참조 라이브러리에서 n8n 노드를 탐색
可视化 참조 라이브러리에서 n8n 노드를 탐색
If
Ftp
Set
+
If
Ftp
Set
113 노드I versus AI
기타
AI 추동 페이스북 페이지 지원 챗봇: 자동 응답 및 지능형 고객 처리
GPT-4.1의 Facebook 메신저 채팅 로봇을 사용하여 인공지능 업그레이드 지원
If
Set
Wait
+
If
Set
Wait
32 노드SpaGreen Creative
지원 챗봇
💥GPT-5와 ElevenLabs를 사용하여 고객 지원 AI 음성 어시스턴트 _ 비디오 구축
GPT-5, ElevenLabs과 캘린더 예약으로 고객 지원 음성 에이전트 생성
Webhook
Gmail Tool
Agent
+
Webhook
Gmail Tool
Agent
12 노드Dr. Firas
AI 챗봇
OpenAI GPT-4o-mini와 텍스트-to-voice를 사용하여 음성 어시스턴트 인터페이스 생성
사용 OpenAI GPT-4o-mini와 텍스트-to-voice로 음성 어시스턴트 인터페이스 생성
Html
Webhook
Agent
+
Html
Webhook
Agent
14 노드Anderson Adelino
지원 챗봇
살롱 예약
AI 기반 살롱 예약 시스템으로, GPT, Google 캘린더 및 이메일 확인 기능을 통합합니다.
Set
Gmail
Switch
+
Set
Gmail
Switch
20 노드Aziz B
AI 챗봇
💥 ChatGPT-5를 사용하여 첫 번째 AI 대리인을 구축하세요
GPT-5, Google 캘린더와 스프레드시트를 사용하여 지식庫와 일정 계획 AI 어시스턴트를 생성합니다.
Gmail Tool
Agent
Google Sheets Tool
+
Gmail Tool
Agent
Google Sheets Tool
14 노드Dr. Firas
기타
워크플로우 정보
난이도
고급
노드 수30
카테고리2
노드 유형14
저자
Bhuvanesh R
@bhuvaneshI partner with businesses to design AI voice agents and automation systems that enhance efficiency and drive growth. If you’re exploring AI integration or seeking guidance on automation workflows, I invite you to connect with me on LinkedIn to discuss further.
외부 링크
n8n.io에서 보기 →
이 워크플로우 공유