Files
n8nworkflows.xyz/workflows/Handle Spanish-speaking vet clinic bookings with GPT-4o, Sheets, Calendar and Gmail-13864/13864-handle-spanish-speaking-vet-clinic-bookings-with-gpt-4o--sheets--calendar-and-gmail.webp
nusquama a325c2024f creation
2026-03-10 12:10:22 +08:00

1 line
19 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"meta":{"instanceId":"YOUR_INSTANCE_ID","templateCredsSetupCompleted":true},"nodes":[{"id":"","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[2272,-544],"webhookId":"","parameters":{"options":{}},"typeVersion":1.4},{"id":"eba8a2e5-9860-4f58-a5db-51c48f80eca2","name":"Normalize","type":"n8n-nodes-base.set","position":[2512,-544],"parameters":{"options":{},"assignments":{"assignments":[{"id":"563b3849-b286-4eb2-8c2c-5e4fb75c9a10","name":"message","type":"string","value":"={{ $json.chatInput }}"},{"id":"8b4f1194-7976-426a-b81a-ce77b9a391ed","name":"phone_number","type":"string","value":"YOUR_PHONE_NUMBER"},{"id":"1e5a7844-a48d-4017-8b3b-d931af534088","name":"session_id","type":"string","value":"={{ $json.sessionId }}"},{"id":"f0de03eb-540d-47d8-ad55-d77599d1b330","name":"10_days_from_now","type":"string","value":"={{ $now.plus({ days: 10 }).toFormat('yyyy-MM-dd') }}"}]}},"typeVersion":3.4},{"id":"34b16c60-0b60-4b4e-a62a-504f3d3922e6","name":"Update event","type":"n8n-nodes-base.googleCalendarTool","position":[3216,-208],"parameters":{"eventId":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The unique ID string from the search result (e.g., 5qasn...)`, 'string') }}","calendar":{"__rl":true,"mode":"list","value":"user@example.com","cachedResultName":"Calendario del Agente de Turnos"},"operation":"update","updateFields":{"end":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', `The new end date and time. This should be exactly 30 minutes after the start time.`, 'string') }}","start":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', `The new start date and time for the appointment in ISO 8601 format (e.g., 2026-02-17T16:00:00).`, 'string') }}"},"descriptionType":"manual","toolDescription":"When updating, always provide an end time 30 minutes after the start time unless specified otherwise."},"credentials":{"googleCalendarOAuth2Api":{"id":"credential-id","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"f36c8bec-06bb-4dd3-88fb-cbbe349ba666","name":"Delete event","type":"n8n-nodes-base.googleCalendarTool","position":[3344,-208],"parameters":{"eventId":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The unique ID string from the search result (e.g., 5qasn...)`, 'string') }}","options":{},"calendar":{"__rl":true,"mode":"list","value":"user@example.com","cachedResultName":"Calendario del Agente de Turnos"},"operation":"delete"},"credentials":{"googleCalendarOAuth2Api":{"id":"credential-id","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"82866b61-d6b1-4775-87b2-482004963868","name":"Create event","type":"n8n-nodes-base.googleCalendarTool","position":[3088,-208],"parameters":{"end":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', ``, 'string') }}","start":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', ``, 'string') }}","calendar":{"__rl":true,"mode":"list","value":"user@example.com","cachedResultName":"Calendario del Agente de Turnos"},"descriptionType":"manual","toolDescription":"Use this tool to create an event - Add the user's name and pet name as the title for each event.","additionalFields":{"summary":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Summary', `Title: User's full name - Pet's name`, 'string') }}","description":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Description', ``, 'string') }}"}},"credentials":{"googleCalendarOAuth2Api":{"id":"credential-id","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"888d1e0f-53b7-43f8-bda1-2b1d9ce9e74e","name":"Simple Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[2576,-192],"parameters":{"sessionKey":"={{ $json.session_id }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"051ec537-9d2d-4253-8844-cd255439d822","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[2240,-192],"parameters":{"model":"openai/gpt-4o","options":{}},"credentials":{"openRouterApi":{"id":"credential-id","name":"OpenRouter"}},"typeVersion":1},{"id":"756c9aae-094b-441e-a627-5742132c1a81","name":"Get events","type":"n8n-nodes-base.googleCalendarTool","position":[2976,-208],"parameters":{"options":{"timeZone":{"__rl":true,"mode":"list","value":"Europe/Madrid","cachedResultName":"Europe/Madrid"}},"timeMax":"={{ $json['10_days_from_now'] }}","calendar":{"__rl":true,"mode":"list","value":"user@example.com","cachedResultName":"Calendario del Agente de Turnos"},"operation":"getAll","returnAll":true,"descriptionType":"manual","toolDescription":"=Use this tool to see if a specific slot is available. If this tool returns data, it means the slot is unavailable/busy. Only look for slots after {{ $now }}."},"credentials":{"googleCalendarOAuth2Api":{"id":"credential-id","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"1d0a7dcb-d904-47e5-920c-eebe65532027","name":"New client?","type":"n8n-nodes-base.googleSheetsTool","position":[2720,-208],"parameters":{"options":{},"filtersUI":{"values":[{"lookupValue":"={{ $('Normalize').item.json.phone_number }}","lookupColumn":"Teléfono"}]},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_ID/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"YOUR_GOOGLE_SHEETS_ID","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_ID/edit?usp=drivesdk","cachedResultName":"Clientes_Veterinaria"},"descriptionType":"manual","toolDescription":"Get row(s) in sheet in Google Sheets"},"credentials":{"googleSheetsOAuth2Api":{"id":"credential-id","name":"Google Sheets account"}},"typeVersion":4.7},{"id":"da321299-e79a-4ea8-8b47-fe38ca5cfd48","name":"María","type":"@n8n/n8n-nodes-langchain.agent","position":[2736,-544],"parameters":{"text":"={{ $json.message }}","options":{"systemMessage":"=# OVERVIEW\nYou are María from \"Patitas Felices\", a virtual assistant. Your priority is to call the correct tools.\n\n# TOOLS\n- New client? - Use this tool to check if the client exists in the system\n- Add client - Use this tool to add the client details to the system\n- Get events - Use this tool to search for events or available slots in the calendar\n- Create event - Use this tool to create a new event (check chat_history for user's details)\n- Update event - Use this tool if there's an existing event that needs to be rescheduled\n- Delete event - Use this tool if there's a existing event that needs to be cancelled/deleted\n- Send a message in Gmail - Use this tool if the user is requesting anything else other than booking, rescheduling, or cancelling an appointment.\n\n# TASKS:\n1- Identify the user (mandatory every time)\n2- Check for existing appointments\n3- Book, reschedule, or delete events\n\n# INSTRUCTIONS FOR EACH TASK\n\n## IDENTIFY USER\n1. **ALWAYS** call `New client?` first to identify the user\n - If the user doesn't exist yet, ask for their full name, and pet's name and type, and then call `Add client`. Check on chat_history if the user has already provided any of those items before asking.\n - If the user exists you can continue to step 2 (Check for existing appointments)\n\n## BOOKING INSTRUCTIONS:\n- **Always** call `Get events` before replying. Send the first 2 or 3 **available** slots to the user.\n- If the user is unavailable on those slot suggestions, provide 2-3 more available slots.\n- Once the user agrees to a specific slot, call `Create event`.\n- Confirm the date/time to the user.\n\n\n## RESCHEDULE INSTRUCTIONS:\n- Call `Get events`, and search the meeting titles until you find the user's existing booking (using the user's full name and pet name). **NEVER** skip this step. If the user is rescheduling, you **must** find the user's existing meeting. The user might provide the wrong time/day, you need to find the correct information each time.\n- Based on the information from `Get events`, provide 2-3 different slots to the user. **You must provide slots that are free/available ONLY**.\n- Once the user confirms a new day/time, call `Update event` and make the changes to the date/time. **Make sure to update the correct event, double check the title to make sure it contains the user and pet names**\n\n## CANCEL/DELETE INSTRUCTIONS:\n- **DO NOT** reply to the user before calling `Get events`.\n- Call `Get events`, search for the user's existing slot using the user's full name and pet name, and once you find it call `Delete event`. Delete **ONLY** the user's existing meeting. If there's more than one, ask the user to confirm which one you need to delete.\n\n\n## OTHER REQUESTS INSTRUCTION:\n- If the user is asking for a different request (other than booking, rescheduling or cancel/deleting appointments), let them know you will inform the team, and that they will reach out soon. Don't ask them if they want you to notify the team - **always** use the `Send a message in Gmail` tool to let the team know.\n\n\n# DATE LOGIC\n- Today is {{ $now.toFormat('EEEE, MMMM d, yyyy') }} at {{ $now.toFormat('HH:mm') }}.\n- If the user asks for a day of the week (e.g., \"Thursday\"):\n 1. Calculate the specific date based on Today.\n 2. If today is Wednesday Feb 18, \"Thursday\" MUST be Feb 19.\n 3. Confirm the date (YYYY-MM-DD) before calling the `Create event` tool.\n\n## Additional info\n- Veterinary doctor's name is Doctor Doolittle.\n- Veterinary clinic address is Calle de los animales #1533\n\n\n# Examples:\n1.\nInput: Hola, tengo un turno ahora en un rato pero no llego. Me lo cambiarias para la tarde, a las 4 quizas?\nOutput: Hola Lucía, no hay problema. El turno de las 16 hs ya está ocupado, pero te puedo ofrecer cambiarlo a las 16:30 o a las 17:00. ¿Qué horario te viene mejor?\n\n2.\nOutput when an appointment has been changed: Hecho! Tu cita ya está cambiada para hoy a las 17:00. Nos vemos en un rato!\n\n3.\nInput: hola, necesito un turno\nOutput: Hola, soy María de Patitas Felices. ¡Encantada! No te encuentro en el sistema, pero no te preocupes, te registro en un segundo. ¿Me podrías decir tu nombre completo y contarme un poco de tu mascota: cómo se llama y qué animalito es?\nInput: claro, soy Antonella Diaz y mi caracol se llama Pepito\nOutput: Genial, ya estás agendada! Tengo algunos turnos libres para hoy: 11:30, 12:00 o 12:30. ¿Cuál prefieres? Y para ir preparandonos, ¿qué le anda pasando a Pepito?\n\n4.\nInput: Hola, necesito un turno\nOutput: Hola [user's name], ¿cómo estás? Tengo algunos turnos libres para hoy: [Available slots]. ¿Cuál prefieres? Y para ir preparándonos, ¿qué le anda pasando a [nombre de la mascota]?\n\n5.\nOutput: ¡Hecho! Tu cita para el chequeo anual de Muni está confirmada para hoy a las 10:30. Nos vemos pronto. 🐶 Si tienes alguna otra pregunta o necesitas algo más, aquí estoy para ayudarte.\nInput: Gracias!\nOutput: ¡Encantada, nos vemos pronto!\n\n6.\nInput: Hola, tengo una cita hoy a las 15 que me gustaria cambiar\n\nOutput: Hola [user's name], he encontrado tu cita pero no es hoy a las 15:00, está agendada a las 12:30. ¿La cambiamos igual? ¿Qué día te viene mejor?"},"promptType":"define","needsFallback":true},"retryOnFail":true,"typeVersion":3.1},{"id":"e02fc04c-1440-4494-b85c-c4cceb2e0409","name":"Add client","type":"n8n-nodes-base.googleSheetsTool","position":[2848,-208],"parameters":{"columns":{"value":{"Cliente":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Cliente', ``, 'string') }}","Teléfono":"={{ $('Normalize').item.json.phone_number }}","Tipo de animal":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tipo_de_animal', ``, 'string') }}","Nombre de la mascota":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Nombre_de_la_mascota', ``, 'string') }}"},"schema":[{"id":"Cliente","type":"string","display":true,"required":false,"displayName":"Cliente","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Nombre de la mascota","type":"string","display":true,"required":false,"displayName":"Nombre de la mascota","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Tipo de animal","type":"string","display":true,"required":false,"displayName":"Tipo de animal","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Raza","type":"string","display":true,"removed":true,"required":false,"displayName":"Raza","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Teléfono","type":"string","display":true,"removed":false,"required":false,"displayName":"Teléfono","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Teléfono"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_ID/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"YOUR_GOOGLE_SHEETS_ID","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_ID/edit?usp=drivesdk","cachedResultName":"Clientes_Veterinaria"}},"credentials":{"googleSheetsOAuth2Api":{"id":"credential-id","name":"Google Sheets account"}},"typeVersion":4.7},{"id":"3894a194-40c3-430d-9f94-b6ca86ffdc2d","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[2416,-192],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-5-mini"},"options":{},"builtInTools":{}},"credentials":{"openAiApi":{"id":"credential-id","name":"OpenAi"}},"typeVersion":1.3},{"id":"7341ca34-fe9d-497f-852f-3812f37bc524","name":"Send a message in Gmail","type":"n8n-nodes-base.gmailTool","position":[3488,-208],"webhookId":"","parameters":{"sendTo":"user@example.com","message":"=Hola,<br><br>\n\nHay una consulta en el chat que necesita tu respuesta cuanto antes!<br><br>\n\nTeléfono: {{ $json.phone_number }}<br>\nMensaje: {{ $json.message }}<br><br>\n\nSaludos,<br>\nMaría","options":{"appendAttribution":false},"subject":"Importante! Hay un chat que necesita respuesta!!","descriptionType":"manual","toolDescription":"Use this tool to send a message and notify the team when a user asks for something different than booking, rescheduling or canceling an appointment."},"credentials":{"gmailOAuth2":{"id":"credential-id","name":"Gmail"}},"typeVersion":2.2},{"id":"3cfb165e-b9c9-4ea8-a056-e806891aeab4","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1936,-992],"parameters":{"color":7,"width":592,"height":208,"content":"## AI Appointment Agent (Maria) Vet Clinic Demo (Spanish speaking)\nPURPOSE: Autonomous booking, rescheduling, and lead capture via n8n Chat.\nMODELS: GPT-4o (Primary) + GPT-4o-mini/GPT-5-mini (Fallback) via OpenRouter."},"typeVersion":1},{"id":"33c9074f-e965-41bd-bfb3-12ab34b9cb4c","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[2192,-624],"parameters":{"width":464,"height":240,"content":"## DATA INGESTION"},"typeVersion":1},{"id":"dcc0a661-6e45-4d1a-88fe-0b0e6a4e9b01","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[2704,-624],"parameters":{"color":6,"width":352,"height":240,"content":"## AI ORCHESTRATION"},"typeVersion":1},{"id":"9998ea35-831c-440c-a431-8d79c5db5cde","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[2192,-256],"parameters":{"color":6,"width":496,"height":304,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## AI ORCHESTRATION"},"typeVersion":1},{"id":"1dd2bb18-62ec-4759-bb54-dd3d65ddc502","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[2704,-256],"parameters":{"color":4,"width":256,"height":304,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## CLIENT DATABASE"},"typeVersion":1},{"id":"f6f01bde-318e-4f18-85f9-102462d9df8e","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[2976,-256],"parameters":{"color":3,"width":464,"height":304,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## APPOINTMENT MANAGEMENT"},"typeVersion":1},{"id":"0d121dcf-b76f-41a7-b2a6-e3723d14b4d9","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[3456,-256],"parameters":{"color":5,"width":352,"height":304,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## ESCALATION & FEEDBACK"},"typeVersion":1},{"id":"ffb12d17-7d33-4187-8e98-f849d1a0fa6d","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1440,-736],"parameters":{"color":7,"width":592,"height":800,"content":"## 🛠️ SETUP & CONFIGURATION (READ FIRST)\n\n1. PREREQUISITES:\n\nCredentials: You will need to connect your Google Sheets, Google Calendar, and Gmail accounts.\n\nAPI Key: An OpenRouter API Key is required for the AI Agent (Maria).\n\n2. GOOGLE SHEETS SETUP:\n\nCreate a sheet named Clientes_Veterinaria with the following columns:\n\nCliente, Nombre de la mascota, Tipo de animal, Teléfono\n\nUpdate the Google Sheets Nodes in this workflow to point to your specific Spreadsheet ID.\n\n3. GOOGLE CALENDAR SETUP:\n\nEnsure your n8n Timezone (in Workflow Settings) matches your Google Calendar timezone to avoid booking errors.\n\nConnect the Calendar Nodes to your primary business calendar.\n\n4. AI AGENT CONFIGURATION:\n\nPrimary Model: GPT-4o (configured in the OpenRouter node).\n\nMemory: The Window Buffer Memory is preset to 10 interactions to maintain context without exceeding token limits.\n\n5. TESTING:\n\nOpen the n8n Chat window on the bottom right.\n\nType: \"Hi, I want to book an appointment for my cat next Tuesday at 10 AM.\"\n\nVerify that Maria checks the sheet, adds you if you're new, and creates the calendar event."},"typeVersion":1},{"id":"27b45ecc-d59b-4056-9ef3-c7d5210878a3","name":"Workflow Error Handler","type":"n8n-nodes-base.errorTrigger","position":[2192,288],"parameters":{},"typeVersion":1},{"id":"ab9d91b8-1e16-4b71-8f4d-94e2ac176804","name":"Notify: Workflow Error","type":"n8n-nodes-base.gmail","position":[2416,288],"webhookId":"","parameters":{"sendTo":"user@example.com","message":"=<h2>🔴 Workflow Error</h2><p>The LinkedIn PDF → JobAdder Sync workflow encountered an error:</p><pre style='background:#f5f5f5;padding:12px'>{{ $json.execution.error.message }}</pre><p><strong>Last node:</strong> {{ $json.execution.lastNodeExecuted }}</p><hr><em>Check your n8n execution log for full details.</em>","options":{},"subject":"=🔴 Workflow Error: LinkedIn PDF → JobAdder Sync"},"credentials":{"gmailOAuth2":{"id":"credential-id","name":"Gmail"}},"typeVersion":2.1},{"id":"8331bde0-f7fe-4858-849d-09674e921ee0","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[2112,192],"parameters":{"width":496,"height":320,"content":"## ERROR HANDLER"},"typeVersion":1}],"pinData":{},"connections":{"María":{"main":[[]]},"Normalize":{"main":[[{"node":"María","type":"main","index":0}]]},"Add client":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"Get events":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"New client?":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"Create event":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"Delete event":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"Update event":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"Simple Memory":{"ai_memory":[[{"node":"María","type":"ai_memory","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"María","type":"ai_languageModel","index":1}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"María","type":"ai_languageModel","index":0}]]},"Workflow Error Handler":{"main":[[{"node":"Notify: Workflow Error","type":"main","index":0}]]},"Send a message in Gmail":{"ai_tool":[[{"node":"María","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"Normalize","type":"main","index":0}]]}}}