{
  "id": "Impnd0S5dTlxbz2u",
  "name": "Pet Clinic Appointment Scheduling Agent",
  "tags": [],
  "nodes": [
    {
      "id": "5d11a0a7-de7c-42ee-b36d-007c37a32965",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        16
      ],
      "parameters": {
        "width": 480,
        "height": 864,
        "content": "## Pet Clinic Appointment Scheduling Agent\n### How it works\n\n1. The workflow triggers when a new message is received via WhatsApp.\n2. It validates the sender and fetches their existing contact information from GoHighLevel.\n3. An AI agent powered by Gemini processes the user's intent, utilizing various tools to manage calendar appointments and update contact notes.\n4. The generated response is formatted and sent back to the user via WhatsApp.\n\n### Setup steps\n\n- [ ] Connect your WhatsApp Business API account in the trigger and response nodes.\n- [ ] Configure GoHighLevel credentials to allow fetching and updating contacts.\n- [ ] Set up Google Gemini API credentials for the conversational AI model.\n- [ ] Connect a Redis instance to maintain the conversational chat history memory.\n- [ ] Configure the HTTP request tools with the appropriate API endpoints and authentication for your calendar system.\n\n### Customization\n\nYou can customize the system prompt inside the AI Agent to adjust its persona, or add additional HTTP tools if you need integration with other systems."
      },
      "typeVersion": 1
    },
    {
      "id": "50e18d5b-7175-4201-9a13-007c7dada717",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 320,
        "content": "## Receive message & fetch contact\n\nTriggers on a new WhatsApp message, validates the sender, and fetches their corresponding GoHighLevel contact record."
      },
      "typeVersion": 1
    },
    {
      "id": "8ebf3fe4-8140-4c1f-9e48-a6eee2c40754",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        64
      ],
      "parameters": {
        "color": 7,
        "width": 1552,
        "height": 512,
        "content": "## AI scheduling agent\n\nAI agent that handles the conversation, manages appointment booking, and updates CRM notes using various tools."
      },
      "typeVersion": 1
    },
    {
      "id": "03513116-4d4e-4f39-9dea-562744eeeaaa",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2608,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 448,
        "content": "## Send WhatsApp response\n\nSends the final generated response from the AI agent back to the user via WhatsApp."
      },
      "typeVersion": 1
    },
    {
      "id": "1a8e8c01-b27c-4496-b31d-b8877611b274",
      "name": "Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1072,
        400
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "e948906c-eff8-4a01-82b9-f75a19d1a3b6",
      "name": "Redis Chat Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "position": [
        1248,
        400
      ],
      "parameters": {
        "sessionKey": "={{ $('When Message Received').first().json.messages[0].from }}",
        "sessionTTL": 500000,
        "sessionIdType": "customKey"
      },
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.5
    },
    {
      "id": "73a7ab84-2ccd-4235-b00f-763a15b61a64",
      "name": "Book Appointment Tool",
      "type": "n8n-nodes-base.highLevelTool",
      "position": [
        1424,
        400
      ],
      "parameters": {
        "resource": "calendar",
        "contactId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Contact_ID', ``, 'string') }}",
        "startTime": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start_Time', ``, 'string') }}",
        "calendarId": "enter-your-calender-id-here",
        "locationId": "enter-your-location-id-here",
        "requestOptions": {},
        "descriptionType": "manual",
        "toolDescription": "Name: Book Calendar Appointment\nDescription: Books a vet appointment at a specific time.\n\nStart_Time: ISO 8601 datetime string (e.g., \"2025-03-10T11:00:00+05:30\")\nContact_ID: The HighLevel Contact ID. You MUST provide this ID \u2014 pull it from the initial context if the contact already existed, or use the ID returned from the creation tool if it was just created.",
        "additionalFields": {
          "title": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Title', ``, 'string') }}",
          "toNotify": true
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "3c881ce5-b762-4f0b-9b12-630d1768b3d3",
      "name": "Upsert HighLevel Contact Tool",
      "type": "n8n-nodes-base.highLevelTool",
      "position": [
        1584,
        400
      ],
      "parameters": {
        "email": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Email', ``, 'string') }}",
        "phone": "=+{{ $('When Message Received').item.json.messages[0].from }}",
        "requestOptions": {},
        "descriptionType": "manual",
        "toolDescription": "Name: Create or update a contact in HighLevel\nDescription: Creates a new contact in the system. Use this when the user's Contact ID is empty. Requires the user's email address, home address, and name.",
        "additionalFields": {
          "name": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Name', ``, 'string') }}",
          "address1": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Address', ``, 'string') }}"
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "ce089976-3570-48e3-86fb-19c73f0cead2",
      "name": "Send WhatsApp Message",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        2720,
        224
      ],
      "parameters": {
        "textBody": "={{ $json.output }}",
        "operation": "send",
        "phoneNumberId": "1083481144853090",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('When Message Received').first().json.messages[0].from }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "b0d53d3b-55f3-4020-a8ec-293b52c160ec",
      "name": "Check Valid Sender",
      "type": "n8n-nodes-base.if",
      "position": [
        624,
        208
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "11bbaeec-d3f0-4e49-a323-10fb6e13a513",
              "operator": {
                "type": "number",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.messages[0].from }}",
              "rightValue": ""
            },
            {
              "id": "7d2bba8b-8cc6-4aa7-962e-1cd7b3b1b22a",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.messages[0].type }}",
              "rightValue": "unsupported"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "3f027ba8-e5e5-4095-a24f-d9a9477f164e",
      "name": "Fetch HighLevel Contacts",
      "type": "n8n-nodes-base.highLevel",
      "position": [
        848,
        192
      ],
      "parameters": {
        "limit": 1,
        "filters": {
          "query": "=+{{ $json.messages[0].from }}"
        },
        "options": {},
        "operation": "getAll",
        "requestOptions": {}
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "6ff30aa6-09b4-4fa4-978d-716fabba52ef",
      "name": "When Message Received",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "position": [
        400,
        208
      ],
      "parameters": {
        "options": {},
        "updates": [
          "messages"
        ]
      },
      "credentials": {
        "whatsAppTriggerApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8ee748fc-7152-4a7d-b3c3-e4c142ce3deb",
      "name": "Save Pet Issue Note Tool",
      "type": "n8n-nodes-base.highLevelTool",
      "position": [
        1744,
        400
      ],
      "parameters": {
        "email": "={{$json.email }}",
        "phone": "=+{{ $('When Message Received').item.json.messages[0].from }}",
        "requestOptions": {},
        "descriptionType": "manual",
        "toolDescription": "Name: Save pet issue in notes\nDescription: Saves the owner's concern about their pet to their contact profile. \nRequires the 'Note' parameter containing a brief summary including the pet's name, \nspecies, and the described health concern or reason for the visit.",
        "additionalFields": {
          "notes": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Note', `you should add the issue over here in this field`, 'string') }}"
        }
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2,
      "rewireOutputLogTo": "ai_tool"
    },
    {
      "id": "8f4ce904-457c-478c-a7a8-ec57c5e5eb36",
      "name": "Fetch Calendar Slots Tool",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        1920,
        400
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/calendars/enter-your-calender-id-here/free-slots",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "startDate",
              "value": "={{ $fromAI('Start_Date', '', 'number') }}"
            },
            {
              "name": "endDate",
              "value": "={{ $fromAI('End_Date', '', 'number') }}"
            },
            {
              "name": "timezone",
              "value": "America/New_York"
            }
          ]
        },
        "toolDescription": "Name: Fetch Available Calendar Slots\nDescription: Retrieves available appointment slots for a specific date range.\n- Start_Date: Unix timestamp in milliseconds (e.g., 1735689600000 for Jan 1, 2025)\n- End_Date: Unix timestamp in milliseconds\nReturns: List of available 30-minute time slots with their start times\n\nIf the response contains only a \"traceId\" field with no slot list, that means no slots are available for the requested day.",
        "optimizeResponse": true,
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "2c52935d-4dd6-4553-8e37-508d68e6a857",
      "name": "Appointment Scheduling Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1696,
        208
      ],
      "parameters": {
        "text": "=<context>\n    <timestamp>\n        Current date and time: {{ $now.toFormat(\"DDDD, HH:mm:ss ZZZZ\") }}\n        Use this to correctly interpret relative time requests (e.g., \"tomorrow morning,\" \"this Friday,\" \"in two hours\").\n    </timestamp>\n\n    <scheduling_rules>\n        The clinic timezone is America/New_York (US Eastern).\n        The clinic operates Monday to Friday only. Weekends (Saturday and Sunday) are closed.\n        - If the user requests a weekend date, do NOT fetch slots. Inform them the clinic is closed and suggest the next available Monday.\n        - When suggesting dates proactively, only ever suggest weekdays (Mon\u2013Fri).\n        - Use the current timestamp above to calculate which day of the week any requested date falls on.\n    </scheduling_rules>\n\n<user_details>\n    {{ $json.id ? \"Contact ID: \" + $json.id + \"\\nFirst Name: \" + $json.firstName + \"\\nLast Name: \" + $json.lastName + \"\\nEmail: \" + $json.email + \"\\nPhone Number: \" + $('When Message Received').item.json.messages[0].from : \"Contact ID: EMPTY\\nPhone Number: \" + $('When Message Received').item.json.messages[0].from + \"\\nMissing Info: Contact does not exist. You MUST ask the user for their Name and Email to create a contact profile.\" }}\n</user_details>\n</context>\n\n<persona>\n    <name>Luna</name>\n    <role>Friendly and caring pet clinic receptionist</role>\n    <company>Paws & Cliques Pet Clinic</company>\n    <tone>Warm, caring, and reassuring \u2014 especially when pets are unwell</tone>\n</persona>\n\n<instructions>\n    <task>\n        Handle pet health inquiries, collect owner and pet details, save their concerns, and book vet appointments efficiently via WhatsApp.\n    </task>\n\n    <workflow>\n        <step n=\"1\">\n            <name>Greet and Understand the Concern</name>\n            <action>\n                - Greet the pet owner warmly and ask about their pet's name, species, and the concern or reason for the visit\n                - Acknowledge their concern with empathy (especially if their pet is unwell)\n                - When they describe the issue, IMMEDIATELY use the \"Save pet issue in notes\" tool to document the pet name, species, and concern summary\n            </action>\n        </step>\n\n        <step n=\"2\">\n            <name>Check Contact Status</name>\n            <condition case=\"Contact ID is EMPTY\">\n                <priority>HIGH \u2014 Must create contact first</priority>\n                <action>\n                    Let the owner know you'll need a few quick details to set up their profile.\n\n                    Collect the following (phone number already available from WhatsApp, DO NOT ask for it):\n                    - Owner's full name\n                    - Email address\n\n                    Once collected, use the \"Create or update a contact in HighLevel\" tool with:\n                    - Name, Email, Phone\n\n                    After contact creation, proceed to booking.\n                </action>\n                <tool>Create or update a contact in HighLevel</tool>\n            </condition>\n\n            <condition case=\"Contact ID exists\">\n                <action>\n                    Address the owner by their first name warmly.\n                    Since their profile is already on file, skip information collection and move directly to scheduling.\n                    DO NOT ask for phone number \u2014 already captured from WhatsApp.\n                </action>\n            </condition>\n        </step>\n\n        <step n=\"3\">\n            <name>Fetch Available Appointment Slots</name>\n            <action>\n                Ask when they'd like to bring their pet in.\n\n                CRITICAL \u2014 ALWAYS fetch availability first using the \"Fetch Available Calendar Slots\" tool before suggesting any times.\n\nReference \u2014 today and the next 14 weekdays with correct America/New_York timestamps:\n{{ \n(function() {\n  const lines = [];\n  let date = $now.setZone('America/New_York').startOf('day');\n  let count = 0;\n  while (count < 14) {\n    const dow = date.weekday;\n    if (dow >= 1 && dow <= 5) {\n      const start = date.toMillis();\n      const end = date.endOf('day').toMillis();\n      lines.push(`- ${date.toFormat('MMMM d, yyyy')} (${date.toFormat('cccc')}) \u2192 Start: ${start} | End: ${end}`);\n      count++;\n    }\n    date = date.plus({ days: 1 });\n  }\n  return lines.join('\\n');\n})()\n}}\n\nCRITICAL: Always pick the Start and End values directly from this list based on the user's requested date. NEVER calculate timestamps yourself.\n\n                CRITICAL \u2014 Interpreting the tool response:\n                - If the response contains a list of time slots \u2192 present them to the user as bullet points\n                - If the response contains ONLY a traceId with no slots (e.g., {\"traceId\": \"...\"}) \u2192 this means NO slots are available for that date. Inform the user politely and ask them to pick a different date.\n\n                CRITICAL \u2014 Displaying slots:\n                - Slots are returned in America/New_York time (e.g., \"2026-06-29T09:00:00-04:00\")\n                - Strip the timezone offset and display only the time in 12-hour format with AM/PM\n                - Example: \"2026-06-29T09:00:00-04:00\" \u2192 display as \"9:00 AM\"\n                - Never show the raw ISO string or offset to the user\n\n                Example response when no slots available:\n                _Sorry, there are no available appointments on that day._ \ud83d\udcc5\n\n                Could you suggest another date and I'll check availability for you?\n            </action>\n            <tool>Fetch Available Calendar Slots</tool>\n        </step>\n\n        <step n=\"4\">\n            <name>Book the Appointment</name>\n            <action>\n                Once the owner confirms a time, use the \"Book Calendar Appointment\" tool.\n\n                CRITICAL \u2014 Format Start_Time correctly:\n                - Use ISO 8601 format with America/New_York offset\n                - Use -04:00 between March and November (EDT)\n                - Use -05:00 between November and March (EST)\n                - Format: \"YYYY-MM-DDTHH:mm:ss-04:00\"\n                - Example: \"2025-03-10T11:00:00-04:00\" for 11:00 AM ET on March 10, 2025\n                - Always use the exact time the user selected from the returned slots \u2014 do not modify or convert it\n\n                After booking, confirm clearly:\n                - Pet's name\n                - Date and time (in 12-hour format, e.g., Monday, March 10 at 11:00 AM)\n                - Type of visit (checkup, vaccination, grooming, etc.)\n\n                Thank the owner and let them know a vet will be ready for them at the scheduled time.\n            </action>\n            <tool>Book Calendar Appointment</tool>\n        </step>\n    </workflow>\n\n    <general_guidelines>\n        - Always ask for the pet's name early \u2014 use it throughout the conversation\n        - Be extra gentle and reassuring when the pet seems unwell or the owner seems worried\n        - NEVER book without fetching available slots first\n        - If Contact ID is EMPTY, contact creation is your FIRST PRIORITY\n        - Never ask for the phone number \u2014 it's captured automatically from WhatsApp\n        - Use WhatsApp formatting for clarity and warmth\n        - Save the pet issue to notes as soon as the concern is described\n        - All scheduling, timestamps, and displayed times must use America/New_York timezone exclusively\n\n\n<appointment_management_rules>\n        - NEVER cancel or reschedule an appointment without explicitly confirming the action with the user first.\n        - If the user asks to cancel or reschedule, first fetch their upcoming appointments, show them the details, and ask: \"Are you sure you want to cancel this?\"\n        - Only execute the cancellation or reschedule tool AFTER receiving a definitive \"yes\" from the user.\n- CRITICAL: When using the Reschedule tool, you MUST format the new startTime in strict ISO 8601 format with the America/New_York offset (e.g., \"YYYY-MM-DDTHH:mm:ss-04:00\"), exactly the same way you do for booking new appointments. Do not modify or convert the time you get from the Fetch Available Calendar Slots tool.\n    </appointment_management_rules>\n\n    </general_guidelines>\n</instructions>\n\n<user_input>\n    <message>{{ $('When Message Received').item.json.messages[0].text.body }}</message>\n</user_input>\n\n<output_format>\n    <style>WhatsApp</style>\n    <rules>\n        <rule>WhatsApp bold uses *asterisks* and italic uses _underscores_. This is correct \u2014 do NOT avoid them, they render properly for the user.</rule>\n        <rule>Use *bold* ONLY for critical info: pet names, confirmed dates, confirmed times. Maximum 2\u20133 bold items per message.</rule>\n        <rule>Use _italics_ sparingly, only for one reassuring phrase per message if needed.</rule>\n        <rule>Never bold entire sentences or greetings. Wrong: *Hi John, your appointment is booked!* Right: Your appointment is confirmed for *Monday, 10:00 AM* \ud83d\udc3e</rule>\n        <rule>Use bullet points (\u2022) only when presenting 3 or more time slot options. Not for single answers.</rule>\n        <rule>Keep each message to 3\u20135 lines max. Break into short paragraphs, never one wall of text.</rule>\n        <rule>Use emojis sparingly \u2014 max 1\u20132 per message. Only \ud83d\udc3e for pet references, \ud83d\udcc5 for scheduling, \u2705 for confirmations.</rule>\n        <rule>Never use markdown headers (##), dashes as bullets, or code blocks.</rule>\n        <rule>End every message with a single clear question or next step \u2014 never multiple questions at once.</rule>\n    </rules>\n    <example>\n        Good:\n        Got it! I've noted down *Max's* concern. \ud83d\udc3e\n\n        When would you like to bring him in?\n\n        Bad:\n        *Hello John!* I've *noted down* your concern about *Max* and I will *help you schedule* an *appointment* today! \ud83d\udcc5\ud83d\udc3e\u2705 Please let me know *when* you'd like to come in!\n    </example>\n</output_format>\n\n<constraints>\n    <fallback>\n        If asked about topics unrelated to pet care or appointment booking, politely redirect: \"I'm here to help schedule appointments at Paws & Cliques! For other inquiries, please call our front desk. Is there anything I can help you book for your furry friend today? \ud83d\udc3e\"\n    </fallback>\n</constraints>",
        "options": {},
        "promptType": "define"
      },
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "96655f9e-96ea-4829-9229-382ee7dc2efe",
      "name": "Fetch User Appointments Tool",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        2080,
        400
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Fetch HighLevel Contacts').item.json.id }}/appointments",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "calendarId",
              "value": "enter-your-calender-id-here"
            }
          ]
        },
        "toolDescription": "Use this tool to fetch the upcoming appointments of the user.",
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "optimizeResponse": true,
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "82bb63d1-e4d3-4035-b74d-0b490d24a71a",
      "name": "Cancel Appointment Tool",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        2256,
        416
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/calendars/events/{{ $fromAI('eventId') }}",
        "method": "PUT",
        "options": {},
        "sendBody": true,
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "cancelled"
            }
          ]
        },
        "queryParameters": {
          "parameters": [
            {
              "name": "locationId",
              "value": "enter-your-location-id-here"
            }
          ]
        },
        "toolDescription": "Cancels an appointment in GoHighLevel. You must provide the eventId of the appointment. You should get this eventId by first calling the \"Fetch User Appointments Tool\".",
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "022e2026-345d-4298-9e7b-78f94dbe9b1e",
      "name": "Reschedule Appointment Tool",
      "type": "n8n-nodes-base.httpRequestTool",
      "position": [
        2432,
        416
      ],
      "parameters": {
        "url": "=https://services.leadconnectorhq.com/calendars/events/{{ $fromAI('eventId') }}",
        "method": "PUT",
        "options": {},
        "sendBody": true,
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "startTime",
              "value": "={{ $fromAI('startTime', 'The new start time in strict ISO 8601 format with America/New_York offset (e.g. 2026-06-29T14:30:00-04:00)', 'string') }}"
            }
          ]
        },
        "queryParameters": {
          "parameters": [
            {
              "name": "locationId",
              "value": "enter-your-location-id-here"
            }
          ]
        },
        "toolDescription": "Reschedules an existing appointment in GoHighLevel to a new time. You must provide the eventId of the appointment. You MUST provide the new start time in strict ISO 8601 format with the correct timezone offset (e.g., 2026-06-29T09:00:00-04:00). NEVER pass conversational dates like \"tomorrow\".",
        "headerParameters": {
          "parameters": [
            {
              "name": "Version",
              "value": "2021-07-28"
            }
          ]
        },
        "nodeCredentialType": "highLevelOAuth2Api"
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "6966ecfa-1fbb-456f-8227-66da6e21ef74",
  "nodeGroups": [],
  "connections": {
    "Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Redis Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Check Valid Sender": {
      "main": [
        [
          {
            "node": "Fetch HighLevel Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Book Appointment Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "When Message Received": {
      "main": [
        [
          {
            "node": "Check Valid Sender",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cancel Appointment Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Fetch HighLevel Contacts": {
      "main": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Pet Issue Note Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Calendar Slots Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Reschedule Appointment Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Appointment Scheduling Agent": {
      "main": [
        [
          {
            "node": "Send WhatsApp Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch User Appointments Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Upsert HighLevel Contact Tool": {
      "ai_tool": [
        [
          {
            "node": "Appointment Scheduling Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}