AutomationFlowsAI & RAG › Appointment Agent

Appointment Agent

Appointment_agent. Uses chatTrigger, lmChatOpenAi, memoryBufferWindow, httpRequestTool. Chat trigger; 19 nodes.

Chat trigger trigger★★★★☆ complexityAI-powered19 nodesChat TriggerOpenAI ChatMemory Buffer WindowHTTP Request ToolAgent
AI & RAG Trigger: Chat trigger Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Chat Trigger 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 →

Download .json
{
  "createdAt": "2025-06-02T18:06:45.989Z",
  "updatedAt": "2025-06-02T18:06:45.989Z",
  "id": "me0GuIidNow8NWzx",
  "name": "Appointment_agent",
  "active": false,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1.1,
      "position": [
        -160,
        460
      ],
      "id": "b8893de5-0441-448b-a4f5-aca6eca608f0",
      "name": "When chat message received"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4.1-mini",
          "mode": "list",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        780,
        900
      ],
      "id": "38a4536f-a62a-4597-a1c1-605ced03f7f9",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Set Details').item.json.sessionID }}",
        "contextWindowLength": 10
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        1120,
        800
      ],
      "id": "272ea0a5-59b8-4c7f-b9f6-0c47eb26b1a7",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "toolDescription": "=Use this tool when a user asks to information on their booking, this tool will also be used to get booking information when a user wants to cancel or reschedule their booking\n\nHere's the input(s) required for this tool:\n\n----\n\nattendeeEmail\nUser Query: Here's the email abcd@gmail.com\nattendeeEmail: abcd@gmail.com\n\n----",
        "url": "https://api.cal.com/v2/bookings",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "upcoming"
            },
            {
              "name": "attendeeEmail",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters1_Value', `The Email the user provided as the email the booking was made with`, 'string') }}"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ $('Set Details').item.json.calApi }}"
            },
            {
              "name": "cal-api-version",
              "value": "2024-08-13"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        1340,
        900
      ],
      "id": "2638a9be-08fd-49ff-9464-71922d66b0e9",
      "name": "Get Booking Information Tool"
    },
    {
      "parameters": {
        "toolDescription": "=Use this tool when a user asks to book an appointment, after their desired time for the appointment found to be available \n\n\nHere's the input(s) required for this tool:\n\n----\n\nemail AND name\nUser Query: Here's the email abcd@gmail.com and the name should be Mark David\nemail: abcd@gmail.com\nname: Mark David\n\n----\n\nstart\nNote: For start always take the current date and time into context then put in thsi format: \"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM\"\nUser Query: I wanna book an appointment for tomorrow by 2pm\ncurrentDate: 2025-05-07T12:06:33.690+01:00\nstart: 2025-05-08T14:00:00+01:00\n\n----\n",
        "method": "POST",
        "url": "https://api.cal.com/v2/bookings",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "cal-api-version",
              "value": "=2024-08-13"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Set Details').item.json.calApi }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"start\": \"{{ $fromAI('start', `The user desired desired time for the Appointment in this format \\\"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM\\\"`, 'string') }}\",\n  \"eventTypeId\": {{ $('Set Details').item.json.eventTypeId }},\n  \"attendee\": {\n    \"name\": \"{{ $fromAI('name', `The Name the user provided for the Booking`, 'string') }}\",\n    \"email\": \"{{ $fromAI('email', `The Email the user provided for the Booking`, 'string') }}\",\n    \"timeZone\": \"{{ $('Sets Timezone Offset').item.json.timezone }}\",\n    \"language\": \"en\"\n  },\n  \"metadata\": {}\n}\n",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        1700,
        880
      ],
      "id": "bde25a9a-e225-41c4-9ff7-dcb31002c0c4",
      "name": "Book Appointment Tool"
    },
    {
      "parameters": {
        "toolDescription": "=Use this tool when user asks for time availability, this tool will also be used to check Availability before rescheduling a booking\n\nNote: For start always take the current date and time into context then put in thsis ormat: \"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM\"\n\nIf the user asks for availability of a specific time, make the time range 1 hour \n\nIf the user asks for availability of a specicfic day, make the time range 24 hours\n\nHere's the input(s) required for this tool:\n\n----\n\nstartTime and endTime\n\nUser Query: Are you available tomorrow by 2pm\ncurrentDate: 2025-05-07T12:06:33.690+01:00\nstartTime: 2025-05-08T14:00:00+01:00\nendTime: 2025-05-08T15:00:00+01:00\n\n----\n\nstartTime and endTime\n\nUser Query: Are you available on friday\ncurrentDate: 2025-05-07T12:06:33.690+01:00\nstartTime: 2025-05-09T09:00:00+01:00\nendTime: 2025-05-09T17:00:00+01:00\n\n----\n",
        "url": "https://api.cal.com/v1/slots",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "apiKey",
              "value": "={{ $('Set Details').item.json.calApi }}"
            },
            {
              "name": "startTime",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters1_Value', `The start time of the availability check in \"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM\" format`, 'string') }}"
            },
            {
              "name": "endTime",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters2_Value', `The end time of the availability check in \"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM\" format`, 'string') }}"
            },
            {
              "name": "eventTypeId",
              "value": "={{ $('Set Details').item.json.eventTypeId }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        2080,
        900
      ],
      "id": "415e6031-6d5a-44a9-8a76-63ad28aede47",
      "name": "Check Availability Tool"
    },
    {
      "parameters": {
        "toolDescription": "=Use this tool when a user wants to cancel their booking\n\nBefore you run this tool, Run the `Get Booking Information Tool` to get the Booking UID which **Required** to run this tool\n\nGetting the Booking UID\n\nHere's an example of the a response from the `Get Booking Information Tool`\n\n{\n  \"response\": [\n    {\n      \"status\": \"success\",\n      \"data\": [\n        {\n          \"id\": 1234567,\n          \"uid\": \"dummyUID123456\",\n          \"title\": \"event between Company A and Company B\",\n          \"description\": \"This is a placeholder description.\",\n          \"hosts\": [\n            {\n              \"id\": 111111,\n              \"name\": \"Company A\",\n              \"email\": \"host@example.com\",\n              \"username\": \"company-a\",\n              \"timeZone\": \"America/New_York\"\n            }\n          ],\n          \"status\": \"scheduled\",\n          \"rescheduledFromUid\": \"previousUID123\",\n          \"start\": \"2025-05-10T10:00:00.000Z\",\n          \"end\": \"2025-05-10T10:30:00.000Z\",\n          \"duration\": 30,\n          \"eventTypeId\": 987654,\n          \"eventType\": {\n            \"id\": 987654,\n            \"slug\": \"demo-event\"\n          },\n          \"meetingUrl\": \"https://example.com/meeting-link\",\n          \"location\": \"https://example.com/meeting-link\",\n          \"absentHost\": false,\n          \"createdAt\": \"2025-05-07T08:00:00.000Z\",\n          \"updatedAt\": \"2025-05-07T08:01:00.000Z\",\n          \"metadata\": {},\n          \"rating\": null,\n          \"icsUid\": \"eventUID123@calendar.com\",\n          \"attendees\": [\n            {\n              \"name\": \"Company B\",\n              \"email\": \"attendee@example.com\",\n              \"timeZone\": \"America/New_York\",\n              \"language\": \"en\",\n              \"absent\": false\n            }\n          ],\n          \"guests\": [],\n          \"bookingFieldsResponses\": {\n            \"email\": \"attendee@example.com\",\n            \"name\": \"Company B\",\n            \"guests\": [],\n            \"location\": {\n              \"value\": \"integrations:example:video\",\n              \"optionValue\": \"\"\n            }\n          }\n        }\n      ]\n    }\n  ]\n}\n\n\nHere's how to get a Booking UID from the response\n\nresponse[0].data[0].uid\n\nwhich means the Booking UID in this example is: \"dummyUID123456\"\n",
        "method": "POST",
        "url": "=https://api.cal.com/v2/bookings/{{ $fromAI('bookingUID', `This is the Booking UID, get this ID from Get Booking Information Tool`, 'string') }}/cancel",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "cal-api-version",
              "value": "=2024-08-13"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "cancellationReason",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters0_Value', `The Reason Booking as cancelled, if there isnt a clear reason, just put: \"User requested cancellation\"`, 'string') }}"
            },
            {
              "name": "cancelSubsequentBookings",
              "value": "={{ true }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        2440,
        920
      ],
      "id": "346bf420-d356-4703-af91-37432fdab428",
      "name": "Cancel Booking Tool"
    },
    {
      "parameters": {
        "toolDescription": "=Use this tool when a user wants to reschedule their booking\n\nBefore you run this tool\n* Run the `Get Booking Information Tool` to get the Booking UID which **Required** to run this tool\n* Run the `Check Availability Tool` to verify if the user desired time for the reschedule is available before you run this tool\n\nGetting the Booking UID\n\nHere's an example of the a response from the `Get Booking Information Tool`\n\n{\n  \"response\": [\n    {\n      \"status\": \"success\",\n      \"data\": [\n        {\n          \"id\": 1234567,\n          \"uid\": \"dummyUID123456\",\n          \"title\": \"event between Company A and Company B\",\n          \"description\": \"This is a placeholder description.\",\n          \"hosts\": [\n            {\n              \"id\": 111111,\n              \"name\": \"Company A\",\n              \"email\": \"host@example.com\",\n              \"username\": \"company-a\",\n              \"timeZone\": \"America/New_York\"\n            }\n          ],\n          \"status\": \"scheduled\",\n          \"rescheduledFromUid\": \"previousUID123\",\n          \"start\": \"2025-05-10T10:00:00.000Z\",\n          \"end\": \"2025-05-10T10:30:00.000Z\",\n          \"duration\": 30,\n          \"eventTypeId\": 987654,\n          \"eventType\": {\n            \"id\": 987654,\n            \"slug\": \"demo-event\"\n          },\n          \"meetingUrl\": \"https://example.com/meeting-link\",\n          \"location\": \"https://example.com/meeting-link\",\n          \"absentHost\": false,\n          \"createdAt\": \"2025-05-07T08:00:00.000Z\",\n          \"updatedAt\": \"2025-05-07T08:01:00.000Z\",\n          \"metadata\": {},\n          \"rating\": null,\n          \"icsUid\": \"eventUID123@calendar.com\",\n          \"attendees\": [\n            {\n              \"name\": \"Company B\",\n              \"email\": \"attendee@example.com\",\n              \"timeZone\": \"America/New_York\",\n              \"language\": \"en\",\n              \"absent\": false\n            }\n          ],\n          \"guests\": [],\n          \"bookingFieldsResponses\": {\n            \"email\": \"attendee@example.com\",\n            \"name\": \"Company B\",\n            \"guests\": [],\n            \"location\": {\n              \"value\": \"integrations:example:video\",\n              \"optionValue\": \"\"\n            }\n          }\n        }\n      ]\n    }\n  ]\n}\n\n\nHere's how to get a Booking UID from the response\n\nresponse[0].data[0].uid\n\nwhich means the Booking UID in this example is: \"dummyUID123456\"",
        "method": "POST",
        "url": "=https://api.cal.com/v2/bookings/{{ $fromAI('bookingUID', `This is the Booking UID, get this ID from Get Booking Information Tool`, 'string') }}/reschedule",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "cal-api-version",
              "value": "=2024-08-13"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "start",
              "value": "={{ $fromAI('start', `The user desired desired time for the Appointment Reschudle in this format \"YYYY-MM-DDTHH:MM:SS\u00b1HH:MM \" once it has been confirmed that the time is available`, 'string') }}"
            },
            {
              "name": "reschedulingReason",
              "value": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('parameters1_Value', `The Booking was reason was rescheduled, if there isnt a clear reason, just put: \"User requested Reschdule\"`, 'string') }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequestTool",
      "typeVersion": 4.2,
      "position": [
        2840,
        920
      ],
      "id": "92fff1df-0cdc-4832-937b-49f7f40a0dfe",
      "name": "Reschedule Appointment Tool"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "d13e38c5-ed8e-4f52-b356-cc9930301ac2",
              "name": "calApi",
              "value": "",
              "type": "string"
            },
            {
              "id": "06f4dc96-bf66-423d-9e20-a40df20a981b",
              "name": "TimeZone",
              "value": "",
              "type": "string"
            },
            {
              "id": "6f454320-120e-4080-a7de-373e61951155",
              "name": "eventTypeId",
              "value": "",
              "type": "string"
            },
            {
              "id": "534825de-ca7e-4a34-abaf-7608f62414b9",
              "name": "sessionID",
              "value": "={{ $json.sessionId }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        500,
        460
      ],
      "id": "37043183-f087-4b96-ae44-e48a2bdeefca",
      "name": "Set Details"
    },
    {
      "parameters": {
        "jsCode": "const tz = $input.first().json.TimeZone;  // replace or set default\n\nconst date = new Date();\nconst formatter = new Intl.DateTimeFormat('en-US', {\n  timeZone: tz,\n  timeZoneName: 'short'\n});\nconst parts = formatter.formatToParts(date);\nconst tzName = parts.find(part => part.type === 'timeZoneName').value;\n\nconst match = tzName.match(/GMT([+-]\\d{1,2})(?::(\\d{2}))?/);\nlet offset;\nif (match) {\n  const hours = parseInt(match[1], 10);\n  const minutes = match[2] ? parseInt(match[2], 10) : 0;\n  offset = `${hours >= 0 ? '+' : '-'}${String(Math.abs(hours)).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n} else {\n  offset = \"Unable to determine offset\";\n}\n\nreturn [{ json: { timezone: tz, offset } }];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1140,
        460
      ],
      "id": "e46efd94-9bac-4b45-a859-fb81e2eeae32",
      "name": "Sets Timezone Offset"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $('When chat message received').item.json.chatInput }}",
        "options": {
          "systemMessage": "=## Identity\nYour a world class appointment booking specialist with 10+ years of experience\n\n## Role\nYou have **ONLY** 5 Roles you can fulfil and here they are\n\n1. Get Booking Information: Get the Individuals Appointment/Booking Information\n2. Book Appointment: Book the individual on an Appointment/Booking\n3. Check Availablity: Check the Availability against the Individuals requested time\n4. Cancel Booking: Cancel the Individuals Appointment/Booking\n5. Reschedule Booking: Reschedule the Individuals Appointment/Booking\n\nFor **Each Role**, you are provided a tool and a task that explains how to use the tool to conduct that particular role \n\n## Guidelines \n* Speak in a conversational tone but present your information in a structured manner\n* For context here is the current date and time: {{ DateTime.now().setZone($json[\"timezone\"]).toISO() }} Use this as contextual information to determine and figure out the user desired booking date and time in ISO format, figure out the day of the weekend using current date and time then work your way to find the user desired booking date and time\n* Your can only conduct those 5 tasks only. **THAT IS YOUR LIMIT**. If you are asked to do more than those 5, say you can only do those 5\n* Always reprompt the user again, if you don't fully understand\n* When a user just says \"Hello\": Welcome yourself as the Appointment Booking Specialists and ask them what they would like whether Get Booking Information, Book Appointment, Check Availability, Cancel Booking, Reschedule Booking then say the required things for each of them. **DO NOT SAY YOU YOUR WORLD CLASS OR HAVE 10+ YEARS OF EXPERIENCE**\n* Here are the required things for each role\n\t* **Get Booking Information**: You need their email the booking was made with\n\t*  **Book Appointment**: You need their desired date & time for the booking, once the time is available, you need their name and email\n\t*  **Check Availability**: You need their desired date & time to check its availability\n\t*  **Cancel Booking**: You need their email the booking was made with \n\t*  **Reschedule Booking**: You need their email the booking was made with \n* You dont need to be reprompting and reconfirming every step, once all the required details has been given just do it\n* You are a world class appointment booking specialist, so execute each role with top precision, as that very important for your reputation, if not you'll be cancelled\n\n## Tools\n\nHere are your 5 Tools \n\n1. `Get Booking Tool`: Use this tool when a user asks to information on their booking, this tool will also be used to get booking information when a user wants to cancel or reschedule their booking\n2. `Booking Appointment Tool`: Use this tool when a user asks to book an appointment, after their desired time for the appointment found to be available \n3. `Check Availability Tool`:  Use this tool when user asks for time availability, this tool will also be used to check Availability before rescheduling a booking\n4. `Cancel Booking Tool`: Use this tool when a user wants to cancel their booking\n5. `Reschedule Booking Tool`: Use this tool when a user wants to reschedule their booking \n\n## Tasks \n\n1. When a user wants to **GET BOOKING INFORMATION**, here's what you should do it **STEP BY STEP**:\n\t* Ask the user for the email they made the booking with\n\t\t* Validate that email has been provided, here's how you validate\n\t\t\t* Here's how a valid email is: abdcd@gmail.com - it must have @ and . domain at the end \n\t\t\t* Here's a valid email: abdcd@gmail.co.uk\n\t\t\t* Here's a non valid email: abcdhgmail.com\n\t\t* If the provided email is not valid, reprompt the user and ask them again \n\t* Once the email has been Validated Run the `Get Booking Information Tool` Tool to get the booking information and provide the user provided email as attendeeEmail\n\t* Once you get a response from the Tool, present it in a structured and consistent format.\n\n2. When a user wants to **BOOK APPOINTMENT**, here's how you should do it **STEP BY STEP**:\n\t*\tAsk the user for their desired date & time for the booking\n\t*\tValidate that either a date/day and time or date/day has been provided and times are available\n\t\t*\tIf **ONLY** day/date has been provided, run the `Check Availablity Tool` and provide the user provided day/date in ISO format by 9am as `startTime` and same day/date in ISO format by 5pm as `endTime`\n\t\t*\tIf **BOTH** day/date **AND** time has been provided, run the `Check Availablity Tool` and provide the user provided date/day and time in ISO Format as `startTime` and same day/date and time put +1 hour/1 hour ahead as `endTime`\n\t*\tOnce date and time has been found to be available and chosen, ask the user for the Name and Email they would like the book Appointment under\n\t*\tValidate that email has been provided, here's how you validate\n\t\t\t* Here's how a valid email is: abdcd@gmail.com - it must have @ and . domain at the end \n\t\t\t* Here's a valid email: abdcd@gmail.co.uk\n\t\t\t* Here's a non valid email: abcdhgmail.com\n\t\t* If the provided email is not valid, reprompt the user and ask them again \n\t*\tOnce Email has been validated run the `Book Appointment Tool` with user chosen date/day and time that been validated to be available as `start` and the user provided name as `name` and user provided email that has been validated as `email`\n\t* Once you get a response from the Tool, present it in a structured and consistent format.\n\n3. When a user wants to **CHECK AVAILABILITY**, here's how you should do it **STEP BY STEP**:\n\t*\tAsk the user for their desired date & time for the availability cheeck\n\t*\tValidate that either a date/day and time or date/day has been provided and times are available\n\t\t*\tIf **ONLY** day/date has been provided, run the `Check Availablity Tool` and provide the user provided day/date in ISO format by 9am as `startTime` and same day/date in ISO format by 5pm as `endTime`\n\t\t*\tIf **BOTH** day/date **AND** time has been provided, run the `Check Availablity Tool` and provide the user provided date/day and time in ISO Format as `startTime` and same day/date and time put +1 hour/1 hour ahead as `endTime`\n\t* Once you get response a response from the Tool, here's what you should do\n\t\t*\tIf there's no availability for the **SPECIFIC** date/day and time, re run the `Check Availability Tool` and check the other times available for the **SAME** day/date by making the `startTime` 9am and `endTime` 5pm for the**SAME** day/date\n\t\t*\tIf there's no availability for the **WHOLE** day/date, re run the `Check Availablity Tool` and check the available times for the **NEXT** day/date by making the `startTime` 9am and `endTime` 5pm for the **NEXT** day/date\n\t\t*\tIf there's no availability for the next day/date, tell the user and ask for another date and time\n\t\t*\tIf there's availability for the day/date or day/date and time, present it in a structured and consistent format, present the day with name of the day of the week and time either as am or pm like Monday by 3pm\n\n4. When a user wants to **CANCEL**, here's how you should do it **STEP BY STEP**:\n\t* Ask the user for the email they made the booking with\n\t\t* Validate that email has been provided, here's how you validate\n\t\t\t* Here's how a valid email is: abdcd@gmail.com - it must have @ and . domain at the end \n\t\t\t* Here's a valid email: abdcd@gmail.co.uk\n\t\t\t* Here's a non valid email: abcdhgmail.com\n\t\t* If the provided email is not valid, reprompt the user and ask them again \n\t* Once the email has been Validated Run the `Get Booking Information Tool` Tool to get the booking information and provide the user provided email as attendeeEmail\n\t* Once you get a response from the Tool, present it in a structured and consistent format and ask the user which of the following bookings would they like to cancel\n\t\t*\tOnce they have chosen a booking to cancel Run `Cancel Booking Tool` Tool with that particular bookings UID you got from the `Get Booking Information` tool run response you just did \n\t\t*\tOnce you get a response from tool, let the user know once their booking has been cancelled successfully or not \n\n5. When a user wants to **RESCHEDULE**, here's how you should do it **STEP BY STEP**:\n\t* Ask the user for the email they made the booking with\n\t\t* Validate that email has been provided, here's how you validate\n\t\t\t* Here's how a valid email is: abdcd@gmail.com - it must have @ and . domain at the end \n\t\t\t* Here's a valid email: abdcd@gmail.co.uk\n\t\t\t* Here's a non valid email: abcdhgmail.com\n\t\t* If the provided email is not valid, reprompt the user and ask them again \n\t* Once the email has been Validated Run the `Get Booking Information Tool` Tool to get the booking information and provide the user provided email as attendeeEmail\n\t* Once you get a response from the Tool, present it in a structured and consistent format and ask the user which of the following bookings would they like to reschedule \n\t* Once they have chosen a booking to reschedule, Ask the user for their desired date & time they would like to reschedule to \n\t*\tValidate that either a date/day and time or date/day has been provided and times are available\n\t\t*\tIf **ONLY** day/date has been provided, run the `Check Availablity Tool` and provide the user provided day/date in ISO format by 9am as `startTime` and same day/date in ISO format by 5pm as `endTime`\n\t\t*\tIf **BOTH** day/date **AND** time has been provided, run the `Check Availablity Tool` and provide the user provided date/day and time in ISO Format as `startTime` and same day/date and time put +1 hour/1 hour ahead as `endTime`\n\t* Once you get response a response from the Tool, here's what you should do\n\t\t*\tIf there's no availability for the **SPECIFIC** date/day and time, re run the `Check Availability Tool` and check the other times available for the **SAME** day/date by making the `startTime` 9am and `endTime` 5pm for the**SAME** day/date\n\t\t*\tIf there's no availability for the **WHOLE** day/date, re run the `Check Availablity Tool` and check the available times for the **NEXT** day/date by making the `startTime` 9am and `endTime` 5pm for the **NEXT** day/date\n\t\t*\tIf there's no availability for the next day/date, tell the user and ask for another date and time\n\t\t*\tIf there's availability for the day/date or day/date and time, present it in a structured and consistent format, present the day with name of the day of the week and time either as am or pm like Monday by 3pm\n\t*\tOnce date and time has been found to be available and chosen, Run `Reschedule Booking Tool` Tool with that particular bookings UID you got from the `Get Booking Information` tool run response you just did \n\t\t*\tOnce you get a response from tool, let the user know once their booking has been rescheduled successfully or not \n\n\n\n\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        1640,
        460
      ],
      "id": "7b5df7c0-f78e-47f0-abb0-f0a16eadaa19",
      "name": "Appointment Booking Agent"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Appointment Booking Agent\n\nThis Agent handles the following booking tasks:\n- **Get Booking Information**: Retrieve details about existing bookings.\n- **Book Appointment**: Schedule a new appointment.\n- **Check Availability**: Verify availability for a specified time.\n- **Cancel Booking**: Cancel an existing booking.\n- **Reschedule Booking**: Change the time or date of an existing booking.",
        "height": 360,
        "width": 660
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1420,
        240
      ],
      "id": "e8de0571-256f-4c37-8a0d-24c7634c87cb",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Get Booking Information\n\nRetrieves details about existing bookings.  \nThis information is essential for managing bookings and is used by the **Cancel Booking** and **Reschedule Booking** actions to ensure the correct appointment is modified or canceled.\n\n",
        "height": 260,
        "width": 300
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1240,
        1060
      ],
      "id": "6ec1ae6c-b73e-464e-8a7e-78687b594bc4",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Book Appointment\n\nSchedules a new appointment based on available time slots.  \nBefore booking, this action checks availability using the **Check Availability** node to ensure the time is free.\n",
        "height": 260,
        "width": 300
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1620,
        1060
      ],
      "id": "4b09dbc8-b7f1-4a23-a833-e35c407a0d4a",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Check Availability\n\nVerifies available time slots for booking or rescheduling.  \nThis action is used by the **Book Appointment** and **Reschedule Booking** actions to ensure there is availability before proceeding with a booking or reschedule.\n\n\n",
        "height": 260,
        "width": 300
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1980,
        1060
      ],
      "id": "87d011ba-a30c-47f0-879f-afaf7a19b415",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Cancel Booking\n\nCancels an existing appointment.  \nBefore canceling, this action uses the **Get Booking Information** node to fetch details about the booking you want to cancel.\n",
        "height": 260,
        "width": 300
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2360,
        1060
      ],
      "id": "01473973-d3b4-4746-9b17-f5e441ddd7e6",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Reschedule Booking\n\nChanges the date or time of an existing appointment.  \nTo reschedule, this action first retrieves the booking details using the **Get Booking Information** node and checks availability with the **Check Availability** node to ensure the new time is free.\n\nUse this node to adjust an existing appointment to a more convenient time.\n",
        "height": 260,
        "width": 300
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2740,
        1060
      ],
      "id": "442fad54-c45b-4280-9bf2-48e839cd1f09",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Agent Configuration Instructions\n\n1. **API Key**  \n   - Enter your **API Key** from your Cal.com dashboard (API settings).\n\n2. **Timezone**  \n   - Set the **Timezone** using the **tz identifier**:\n     - For AI systems, pass in the timezone based on the user's location.\n     - For individual use, set your own timezone (e.g., `America/New_York`).\n     - Find the **tz identifier** for your timezone here: [TZ Database Time Zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).\n     - You can also pass it dynamically from a voice or text agent.\n\n3. **Event Type ID**  \n   - Find the **Event Type ID** in the event URL on Cal.com.\n\n4. **Session ID**  \n   - If using in **n8n**, do not modify the **Session ID** field.\n   - If used as a **webhook**, pass in the **call/chat ID** as the **Session ID**.\n",
        "height": 660,
        "width": 660,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        220,
        -20
      ],
      "id": "075e8117-10da-4411-9adc-626367de38af",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "## \ud83d\udcdd Add OpenAI Account Credentials\n\nTo add your **OpenAI account credentials**, follow the official guide:  \n[OpenAI Account Setup Guide](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatopenai/?utm_source=n8n_app&utm_medium=node_settings_modal-credential_link&utm_campaign=%40n8n%2Fn8n-nodes-langchain.lmChatOpenAi).\n\n> **Note:** Edit the node settings and add the OpenAI credentials ",
        "height": 240,
        "width": 360,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        640,
        1040
      ],
      "id": "e4bf4115-19fa-4ef2-b0fe-9a920addaca7",
      "name": "Sticky Note7"
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [
        [
          {
            "node": "Set Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Get Booking Information Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Book Appointment Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Check Availability Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Cancel Booking Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Reschedule Appointment Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Set Details": {
      "main": [
        [
          {
            "node": "Sets Timezone Offset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sets Timezone Offset": {
      "main": [
        [
          {
            "node": "Appointment Booking Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "versionId": "a5565ae8-64bd-42ab-a967-3dada0ca875b",
  "triggerCount": 0,
  "tags": []
}

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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Appointment_agent. Uses chatTrigger, lmChatOpenAi, memoryBufferWindow, httpRequestTool. Chat trigger; 19 nodes.

Source: https://github.com/AndersonNascimentoDosSantos/n8n-workflow-backup/blob/main/appointment_agent-me0GuIidNow8NWzx.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Who is this workflow for? This workflow is designed for SEO analysts, content creators, marketing agencies, and developers who need to index a website and then interact with its content as if it were

Agent, OpenAI Chat, Memory Buffer Window +10
AI & RAG

Categories: AI Agents, Design Automation, Business Tools

Tool Workflow, HTTP Request Tool, Memory Buffer Window +7
AI & RAG

Perfect for educators, consultants, and content creators who record sessions and want to repurpose them into social media posts, videos, and images without manual work. Chat interface triggers the AI

Chat Trigger, OpenAI Chat, Memory Buffer Window +9
AI & RAG

This workflow implements an advanced AI-powered system for generating, and executing Claude Skills stored on GitHub.

Chat Trigger, Memory Buffer Window, Mcp Client Tool +9
AI & RAG

ModelRouter. Uses chatTrigger, agent, modelSelector, httpRequest. Chat trigger; 28 nodes.

Chat Trigger, Agent, Model Selector +8