Pet Clinic Appointment Scheduling Agent A developer built a WhatsApp-based pet clinic appointment scheduling agent using n8n, Google Gemini, Redis, and HighLevel. The agent handles natural language conversations to book vet appointments, manage contacts, and maintain session history. | { | | | "nodes": | | | { | | | "parameters": { | | | "modelName": "models/gemini-3.1-flash-lite", | | | "options": {} | | | }, | | | "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini", | | | "typeVersion": 1.1, | | | "position": | | | 880, | | | 1200 | | | , | | | "id": "1480c8d5-d3ef-485e-85f0-6850d86d6dfb", | | | "name": "Gemini Chat Model", | | | "credentials": { | | | "googlePalmApi": { | | | "id": "TZtQePDMJ3j6PZ3M", | | | "name": "abhiram.bvb" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "sessionIdType": "customKey", | | | "sessionKey": "={{ $ 'WhatsApp Trigger' .first .json.messages 0 .from }}", | | | "sessionTTL": 500000 | | | }, | | | "type": "@n8n/n8n-nodes-langchain.memoryRedisChat", | | | "typeVersion": 1.5, | | | "position": | | | 1040, | | | 1200 | | | , | | | "id": "79105878-8e2a-4fcd-b4ab-4774d1728490", | | | "name": "Redis Chat History Memory", | | | "credentials": { | | | "redis": { | | | "id": "yvuTG5xG2g9XosHp", | | | "name": "Redis account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "descriptionType": "manual", | | | "toolDescription": "Name: Book Calendar Appointment\nDescription: Books an appointment at a specific time.\n\nStart Time: ISO 8601 datetime string e.g., \"2025-01-15T10:00:00-05:30\" \n\nContact ID: The HighLevel Contact ID. You MUST provide this ID. If the contact already existed, pull it from your initial instructions context. If you just created the contact, use the new ID returned from the creation tool.\n\n\nName: 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\" \n\nContact ID: The HighLevel Contact ID. Pull it from the initial context if the \ncontact existed, or use the ID returned from the creation tool if newly created.", | | | "resource": "calendar", | | | "calendarId": "enter-your-calender-id-here", | | | "locationId": "enter-your-location-id-here", | | | "contactId": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Contact ID', , 'string' }}", | | | "startTime": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Start Time', , 'string' }}", | | | "additionalFields": { | | | "title": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Title', , 'string' }}", | | | "toNotify": true | | | }, | | | "requestOptions": {} | | | }, | | | "type": "n8n-nodes-base.highLevelTool", | | | "typeVersion": 2, | | | "position": | | | 1184, | | | 1200 | | | , | | | "id": "63d24767-d328-44fe-b3f0-63ed4efab30e", | | | "name": "Book Calendar Appointment", | | | "credentials": { | | | "highLevelOAuth2Api": { | | | "id": "j07jOQoIY1vL4lAY", | | | "name": "HighLevel account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "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, user address & User name", | | | "email": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Email', , 'string' }}", | | | "phone": "=+{{ $ 'WhatsApp Trigger' .item.json.messages 0 .from }}", | | | "additionalFields": { | | | "address1": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Address', , 'string' }}", | | | "name": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Name', , 'string' }}" | | | }, | | | "requestOptions": {} | | | }, | | | "type": "n8n-nodes-base.highLevelTool", | | | "typeVersion": 2, | | | "position": | | | 1344, | | | 1200 | | | , | | | "id": "8ff3cc9e-acd4-4bdb-bede-a75ce9e7f91c", | | | "name": "Create or update a contact in HighLevel", | | | "credentials": { | | | "highLevelOAuth2Api": { | | | "id": "j07jOQoIY1vL4lAY", | | | "name": "HighLevel account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "operation": "send", | | | "phoneNumberId": "1083481144853090", | | | "recipientPhoneNumber": "={{ $ 'WhatsApp Trigger' .first .json.messages 0 .from }}", | | | "textBody": "={{ $json.output }}", | | | "additionalFields": {} | | | }, | | | "type": "n8n-nodes-base.whatsApp", | | | "typeVersion": 1.1, | | | "position": | | | 2208, | | | 976 | | | , | | | "id": "3767836e-22ba-4c23-9910-c07c1bd6a698", | | | "name": "Send WhatsApp Response", | | | "webhookId": "75103a52-ea18-4295-b163-7bc2b9ddba08", | | | "credentials": { | | | "whatsAppApi": { | | | "id": "KsIEVWr4quKHUlO7", | | | "name": "WhatsApp account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "conditions": { | | | "options": { | | | "caseSensitive": true, | | | "leftValue": "", | | | "typeValidation": "loose", | | | "version": 3 | | | }, | | | "conditions": | | | { | | | "id": "11bbaeec-d3f0-4e49-a323-10fb6e13a513", | | | "leftValue": "={{ $json.messages 0 .from }}", | | | "rightValue": "", | | | "operator": { | | | "type": "number", | | | "operation": "notEmpty", | | | "singleValue": true | | | } | | | }, | | | { | | | "id": "7d2bba8b-8cc6-4aa7-962e-1cd7b3b1b22a", | | | "leftValue": "={{ $json.messages 0 .type }}", | | | "rightValue": "unsupported", | | | "operator": { | | | "type": "string", | | | "operation": "notEquals" | | | } | | | } | | | , | | | "combinator": "and" | | | }, | | | "looseTypeValidation": true, | | | "options": {} | | | }, | | | "type": "n8n-nodes-base.if", | | | "typeVersion": 2.3, | | | "position": | | | 528, | | | 992 | | | , | | | "id": "ace8174d-caea-4f74-b586-f85f12af0c91", | | | "name": "If Valid Sender Exists" | | | }, | | | { | | | "parameters": { | | | "operation": "getAll", | | | "limit": 1, | | | "filters": { | | | "query": "=+{{ $json.messages 0 .from }}" | | | }, | | | "options": {}, | | | "requestOptions": {} | | | }, | | | "type": "n8n-nodes-base.highLevel", | | | "typeVersion": 2, | | | "position": | | | 752, | | | 976 | | | , | | | "id": "e250c718-e3e5-40ba-bb10-b2ee90035545", | | | "name": "Fetch GHL Contacts", | | | "alwaysOutputData": true, | | | "credentials": { | | | "highLevelOAuth2Api": { | | | "id": "j07jOQoIY1vL4lAY", | | | "name": "HighLevel account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "updates": | | | "messages" | | | , | | | "options": {} | | | }, | | | "type": "n8n-nodes-base.whatsAppTrigger", | | | "typeVersion": 1, | | | "position": | | | 304, | | | 992 | | | , | | | "id": "572e37bd-7c10-4d47-9c8e-a358e712404b", | | | "name": "WhatsApp Trigger", | | | "webhookId": "5bdae0b3-8ba4-4e13-b259-8922aa9ad77b", | | | "credentials": { | | | "whatsAppTriggerApi": { | | | "id": "iXRwfmH8WHEurWCh", | | | "name": "WhatsApp OAuth account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "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.", | | | "email": "={{$json.email }}", | | | "phone": "=+{{ $ 'WhatsApp Trigger' .item.json.messages 0 .from }}", | | | "additionalFields": { | | | "notes": "={{ / n8n-auto-generated-fromAI-override / $fromAI 'Note', you should add the issue over here in this field , 'string' }}" | | | }, | | | "requestOptions": {} | | | }, | | | "type": "n8n-nodes-base.highLevelTool", | | | "typeVersion": 2, | | | "position": | | | 1488, | | | 1200 | | | , | | | "id": "cec1988b-bcd7-4204-ae0f-7349c658b1cd", | | | "name": "Save pet issue in notes", | | | "rewireOutputLogTo": "ai tool", | | | "credentials": { | | | "highLevelOAuth2Api": { | | | "id": "j07jOQoIY1vL4lAY", | | | "name": "HighLevel account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "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\nAnd if we only got the traceid back then that means we don't have any open slots for that day/user specified time", | | | "url": "=https://services.leadconnectorhq.com/calendars/enter-your-calender-id-here/free-slots", | | | "authentication": "predefinedCredentialType", | | | "nodeCredentialType": "highLevelOAuth2Api", | | | "sendQuery": true, | | | "queryParameters": { | | | "parameters": | | | { | | | "name": "startDate", | | | "value": "={{ $fromAI 'Start Date', '', 'number' }}" | | | }, | | | { | | | "name": "endDate", | | | "value": "={{ $fromAI 'End Date', '', 'number' }}" | | | }, | | | { | | | "name": "timezone", | | | "value": "America/New York" | | | } | | | | | | }, | | | "options": {}, | | | "optimizeResponse": true | | | }, | | | "type": "n8n-nodes-base.httpRequestTool", | | | "typeVersion": 4.4, | | | "position": | | | 1632, | | | 1200 | | | , | | | "id": "a0eb8a69-df4b-4da1-8f64-4302e0fbe612", | | | "name": "Fetch Available Calendar Slots", | | | "credentials": { | | | "highLevelOAuth2Api": { | | | "id": "j07jOQoIY1vL4lAY", | | | "name": "HighLevel account" | | | } | | | } | | | }, | | | { | | | "parameters": { | | | "promptType": "define", | | | "text": "=