diff --git a/workflows/AI-Powered WhatsApp Chatbot π€π
: Complete Booking Assistant with Gemini & Google-13984/ai-powered_whatsapp_chatbot_complete_booking_assistant_with_gemini_google.json b/workflows/AI-Powered WhatsApp Chatbot π€π
: Complete Booking Assistant with Gemini & Google-13984/ai-powered_whatsapp_chatbot_complete_booking_assistant_with_gemini_google.json
new file mode 100644
index 000000000..f8864250b
--- /dev/null
+++ b/workflows/AI-Powered WhatsApp Chatbot π€π
: Complete Booking Assistant with Gemini & Google-13984/ai-powered_whatsapp_chatbot_complete_booking_assistant_with_gemini_google.json
@@ -0,0 +1 @@
+{"id":"MdmtzLYxHXpTdOUp","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"WhatsApp Complete AI Simple Booking","tags":[],"nodes":[{"id":"fec9d00e-0a8a-4a1f-aafe-8b30055784b5","name":"Update event","type":"n8n-nodes-base.googleCalendarTool","position":[720,704],"parameters":{"eventId":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The unique ID string from the search result `, 'string') }}","calendar":{"__rl":true,"mode":"list","value":"davide.boizza@gmail.com","cachedResultName":"davide.boizza@gmail.com"},"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":"8RFK3u13g2PJEGa9","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"9f76daed-9757-4886-b3d5-890b456fcbe9","name":"Delete event","type":"n8n-nodes-base.googleCalendarTool","position":[592,704],"parameters":{"eventId":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', `The unique ID string from the search result `, 'string') }}","options":{},"calendar":{"__rl":true,"mode":"list","value":"davide.boizza@gmail.com","cachedResultName":"davide.boizza@gmail.com"},"operation":"delete"},"credentials":{"googleCalendarOAuth2Api":{"id":"8RFK3u13g2PJEGa9","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"9096fdfc-4787-4598-a6f5-a477f7ace15b","name":"Create event","type":"n8n-nodes-base.googleCalendarTool","position":[720,864],"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":"davide.boizza@gmail.com","cachedResultName":"davide.boizza@gmail.com"},"descriptionType":"manual","toolDescription":"Use this tool to create an event - Add the user's name and the service","additionalFields":{"summary":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Summary', `Title: Client's name - Service`, 'string') }}","description":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Description', ``, 'string') }}"}},"credentials":{"googleCalendarOAuth2Api":{"id":"8RFK3u13g2PJEGa9","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"f6316b89-d476-4001-9c23-f5a7e618293d","name":"Get events","type":"n8n-nodes-base.googleCalendarTool","position":[592,848],"parameters":{"options":{"timeZone":{"__rl":true,"mode":"list","value":"Europe/Madrid","cachedResultName":"Europe/Madrid"}},"timeMax":"={{ $now.plus({ days: 30 }).toFormat('yyyy-MM-dd') }}","calendar":{"__rl":true,"mode":"list","value":"davide.boizza@gmail.com","cachedResultName":"davide.boizza@gmail.com"},"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":"8RFK3u13g2PJEGa9","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"8285ba3a-5dd8-4185-ab1f-32edb374309b","name":"Add client","type":"n8n-nodes-base.googleSheetsTool","position":[448,704],"parameters":{"columns":{"value":{"Client":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Client', ``, 'string') }}","Service":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Service', ``, 'string') }}","Phone Number":"={{ $('Normalize').item.json.sessionId }}"},"schema":[{"id":"Phone Number","type":"string","display":true,"removed":false,"required":false,"displayName":"Phone Number","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Client","type":"string","display":true,"required":false,"displayName":"Client","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Service","type":"string","display":true,"required":false,"displayName":"Service","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Phone Number"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU/edit#gid=0","cachedResultName":"Foglio1"},"documentId":{"__rl":true,"mode":"list","value":"1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU/edit?usp=drivesdk","cachedResultName":"Appointments"}},"credentials":{"googleSheetsOAuth2Api":{"id":"JYR6a64Qecd6t8Hb","name":"Google Sheets account"}},"typeVersion":4.7},{"id":"25c8ddac-69ac-4ea9-90ec-65e7070154d5","name":"Workflow Error Handler","type":"n8n-nodes-base.errorTrigger","position":[-2160,112],"parameters":{},"typeVersion":1},{"id":"fc9ffa55-6a99-4ed4-af4b-d12fa4e9e277","name":"Notify: Workflow Error","type":"n8n-nodes-base.gmail","position":[-1056,112],"webhookId":"53918010-9085-4011-9e56-b71e3a13aa4d","parameters":{"sendTo":"user@example.com","message":"=
π΄ Workflow Error
The LinkedIn PDF β JobAdder Sync workflow encountered an error:
{{ $json.execution.error.message }}Last node: {{ $json.execution.lastNodeExecuted }}
Check your n8n execution log for full details.","options":{},"subject":"=π΄ Workflow Error: LinkedIn PDF β JobAdder Sync"},"credentials":{"gmailOAuth2":{"id":"nyuHvSX5HuqfMPlW","name":"Gmail account (n3w.it)"}},"typeVersion":2.1},{"id":"87cc75dc-c025-42e8-bb43-7257a7542054","name":"Virtual Assistant","type":"@n8n/n8n-nodes-langchain.agent","position":[272,432],"parameters":{"text":"={{ $json.guardrailsInput }}","options":{"systemMessage":"=# OVERVIEW\nYou are Emma from \"Cuts & Styles\", a virtual assistant. Your priority is to call the correct tools in the right order.\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 an existing event that needs to be cancelled/deleted\n- Escalation - 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 appointments\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 hair type/preferences, then call `Add client`. Check chat_history if the user has already provided any of those details before asking.\n - If the user exists, 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## RESCHEDULE INSTRUCTIONS:\n- Call `Get events` and search the appointment titles until you find the user's existing booking (using the user's full name). **NEVER** skip this step. If the user is rescheduling, you **must** find their existing appointment. The user might provide the wrong time/day β always verify the correct information.\n- Based on the information from `Get events`, provide 2-3 different available slots to the user. **Only suggest slots that are free**.\n- Once the user confirms a new day/time, call `Update event` and make the changes. **Make sure to update the correct event by double-checking the title contains the user's name.**\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 appointment using their full name, and once found call `Delete event`. Delete **ONLY** the user's appointment. If there is more than one, ask the user to confirm which one to delete.\n\n## OTHER REQUESTS INSTRUCTIONS:\n- If the user is asking for anything other than booking, rescheduling, or cancelling an appointment, let them know you will inform the team and that someone will reach out soon. Don't ask for confirmation β **always** use the `Send a message in Gmail` tool to notify the team immediately.\n\n# DATE LOGIC\n- Today is {{ $now.toFormat('dd/LL/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- Hairstylist's name is Alex Carter.\n- Salon address is 1533 Style Avenue\n\n# Examples:\n1.\nInput: Hi, I have an appointment soon but I won't make it. Can you move it to this afternoon, maybe at 4?\nOutput: Hi Sarah, no problem! The 4:00 PM slot is already taken, but I can offer you 4:30 PM or 5:00 PM instead. Which works better for you?\n\n2.\nOutput when an appointment has been changed: Done! Your appointment has been moved to today at 5:00 PM. See you soon!\n\n3.\nInput: Hi, I need an appointment\nOutput: Hi, I'm Emma from Cuts & Styles β lovely to meet you! I don't see you in our system yet, but I can get you set up in seconds. Could you share your full name and tell me a bit about your hair (length, type, any preferences)?\nInput: Sure! I'm Jessica Brown and I have long curly hair\nOutput: Perfect, you're all set! I have a few slots available today: 11:30 AM, 12:00 PM, or 12:30 PM. Which works for you? And what service are you looking for today?\n\n4.\nInput: Hi, I need an appointment\nOutput: Hi [user's name], great to hear from you! Here are a few available slots: [Available slots]. Which works for you? And what are we doing for you today β cut, color, something else?\n\n5.\nOutput: Done! Your blowout appointment is confirmed for today at 10:30 AM with Alex. See you soon! π Let me know if you need anything else.\nInput: Thanks!\nOutput: You're welcome β see you soon!\n\n6.\nInput: Hi, I have an appointment today at 3 PM that I'd like to reschedule\nOutput: Hi [user's name], I found your appointment β it's actually booked at 12:30 PM, not 3:00 PM. Would you still like to reschedule it? If so, what day works best for you?"},"promptType":"define"},"retryOnFail":true,"typeVersion":3.1},{"id":"84fa4817-92d9-4968-a4cb-9047c1f79bfa","name":"WhatsApp Trigger","type":"n8n-nodes-base.whatsAppTrigger","position":[-2176,992],"webhookId":"d3978cae-2aca-4553-8ac7-ab89068deabc","parameters":{"options":{},"updates":["messages"]},"credentials":{"whatsAppTriggerApi":{"id":"gylriO2te7NRPXxN","name":"WhatsApp OAuth account"}},"typeVersion":1},{"id":"1983a56e-4ab6-4091-b324-25a22398ef16","name":"Download Audio","type":"n8n-nodes-base.httpRequest","position":[-1504,992],"parameters":{"url":"={{ $json.url }}","options":{},"authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth"},"typeVersion":4.2},{"id":"07b0371d-57d9-4753-ad9f-8ec1b94d2a28","name":"Transcribe Audio","type":"@n8n/n8n-nodes-langchain.openAi","position":[-1280,992],"parameters":{"options":{},"resource":"audio","operation":"transcribe"},"credentials":{"openAiApi":{"id":"XJTqRiKFJpFs5MuX","name":"OpenRouter account"}},"typeVersion":1.8},{"id":"d4d264be-f8a3-4938-b1e9-30e2531b174a","name":"Fix mimeType for Audio","type":"n8n-nodes-base.code","position":[2912,64],"parameters":{"jsCode":"for (const item of $input.all()) {\n if (item.binary) {\n const binaryPropertyNames = Object.keys(item.binary);\n for (const propName of binaryPropertyNames) {\n if (item.binary[propName].mimeType === 'audio/mp3') {\n item.binary[propName].mimeType = 'audio/mpeg';\n }\n }\n }\n}\n\nreturn $input.all();"},"typeVersion":2},{"id":"9bfbcdf4-1ef4-487e-b289-5a74f790e45e","name":"Send message","type":"n8n-nodes-base.whatsApp","position":[2688,256],"webhookId":"23834751-5066-48ba-8e19-549680df2b27","parameters":{"textBody":"={{ $json.output }}","operation":"send","phoneNumberId":"470271332838881","additionalFields":{},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"2bedd51f-60a0-4a8e-96d7-e2a4c298b7b4","name":"Send audio","type":"n8n-nodes-base.whatsApp","position":[3136,64],"webhookId":"d18b2c98-84e4-43cf-a532-0c47d5161684","parameters":{"mediaPath":"useMedian8n","operation":"send","messageType":"audio","phoneNumberId":"470271332838881","additionalFields":{},"recipientPhoneNumber":"={{ $('Input type').item.json.contacts[0].wa_id }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"1c7ea9ac-90f7-4095-be8c-b0a3d9904925","name":"Audio","type":"n8n-nodes-base.set","position":[-1056,992],"parameters":{"options":{},"assignments":{"assignments":[{"id":"219577d5-b028-48fc-90be-980f4171ab68","name":"message","type":"string","value":"={{ $json.text }}"},{"id":"3eb09778-f47e-4881-bd16-48d9dbfe3132","name":"sessionId","type":"string","value":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},{"id":"94082eb6-8031-4101-9795-2423d3dc6560","name":"type","type":"string","value":"whatsapp"}]}},"typeVersion":3.4},{"id":"a4e3d012-43fe-4a0b-8b4a-c10f7f184304","name":"Not supported","type":"n8n-nodes-base.whatsApp","position":[-1728,1184],"webhookId":"23834751-5066-48ba-8e19-549680df2b27","parameters":{"textBody":"=You can only send text messages, images, audio files and PDF documents.","operation":"send","phoneNumberId":"470271332838881","additionalFields":{},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"424fe518-bc50-4b86-9c76-2715826e9248","name":"Get Audio Url","type":"n8n-nodes-base.whatsApp","position":[-1728,992],"webhookId":"87caa300-7204-47b5-959a-94f4a8fbf8cf","parameters":{"resource":"media","operation":"mediaUrlGet","mediaGetId":"={{ $('WhatsApp Trigger').item.json.messages[0].audio.id }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"f5347cd5-9c13-4f76-a857-3875d956b886","name":"Generate Audio Response","type":"@n8n/n8n-nodes-langchain.openAi","position":[2688,64],"parameters":{"input":"={{ $('AI Agent1').item.json.output }}","voice":"onyx","options":{},"resource":"audio"},"credentials":{"openAiApi":{"id":"XJTqRiKFJpFs5MuX","name":"OpenRouter account"}},"typeVersion":1.8},{"id":"61b74351-ea96-48f1-90f8-8529dd220667","name":"From audio to audio?","type":"n8n-nodes-base.if","position":[2288,176],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"b9d1d759-f585-4791-a743-b9d72951e77c","operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $('WhatsApp Trigger').item.json.messages[0].audio }}","rightValue":""}]}},"typeVersion":2.2},{"id":"7b2865c2-a532-4f99-ad5a-a1eae456f0ba","name":"Input type","type":"n8n-nodes-base.switch","position":[-1952,976],"parameters":{"rules":{"values":[{"outputKey":"Text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"08fd0c80-307e-4f45-b1de-35192ee4ec5e","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.messages[0].text.body }}","rightValue":""}]},"renameOutput":true},{"outputKey":"Voice","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"b7b64446-f1ea-4622-990c-22f3999a8269","operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $json.messages[0].audio }}","rightValue":""}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"}},"typeVersion":3.2},{"id":"d78be069-d111-4cc3-abda-8f69faebe232","name":"Calculator","type":"@n8n/n8n-nodes-langchain.toolCalculator","position":[912,896],"parameters":{},"typeVersion":1},{"id":"98bf7e36-9fd9-4e35-bdaa-90749ccfc7ff","name":"Send Email","type":"n8n-nodes-base.gmailTool","position":[1296,1152],"webhookId":"97068af0-8aeb-473b-bb22-785f457cbf8f","parameters":{"sendTo":"xxx@xxx.com","message":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}","options":{"appendAttribution":false},"subject":"Escaletion ","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":"nyuHvSX5HuqfMPlW","name":"Gmail account (n3w.it)"}},"typeVersion":2.2},{"id":"cf918a88-9029-488a-9a3d-fd28ebc45c0a","name":"Escalation","type":"n8n-nodes-base.whatsAppHitlTool","position":[1360,912],"webhookId":"6fba7666-d652-430d-954a-78a002a30e07","parameters":{"message":"=The agent wants to call {{ $tool.name }}\n\n{{ \n $tool.parameters.keys()\n .map(\n param => \n `${param}: ${$tool.parameters[param]} \\n`\n )\n .join('')\n}}","options":{},"approvalOptions":{"values":{"approvalType":"double"}},"recipientPhoneNumber":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Recipient_s_Phone_Number', ``, 'string') }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1.1},{"id":"4bfdb216-a855-4ea0-a472-d3051525d199","name":"New client","type":"n8n-nodes-base.googleSheetsTool","position":[448,848],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU/edit#gid=0","cachedResultName":"Foglio1"},"documentId":{"__rl":true,"mode":"list","value":"1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU/edit?usp=drivesdk","cachedResultName":"Appointments"},"descriptionType":"manual","toolDescription":"Get row(s) in sheet in Google Sheets"},"credentials":{"googleSheetsOAuth2Api":{"id":"JYR6a64Qecd6t8Hb","name":"Google Sheets account"}},"typeVersion":4.7},{"id":"18e664b8-032c-48ba-89a6-e57f7404b5bb","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[192,704],"parameters":{"options":{},"modelName":"models/gemini-3.1-flash-lite-preview"},"credentials":{"googlePalmApi":{"id":"0p34rXqIqy8WuoPg","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"ba2c4744-1188-4843-9998-9daf945380fd","name":"Guardrails","type":"@n8n/n8n-nodes-langchain.guardrails","position":[-464,768],"parameters":{"text":"={{ $json.message }}","guardrails":{"jailbreak":{"value":{"threshold":0.7,"customizePrompt":true}}},"customizeSystemMessage":true},"typeVersion":2},{"id":"73b085f8-a9cf-4303-b57b-cc8c330db2e5","name":"Google Gemini Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[-528,1024],"parameters":{"options":{},"modelName":"models/gemini-2.5-flash-lite"},"credentials":{"googlePalmApi":{"id":"AaNPKXAphyMzRgfA","name":"Google Gemini(PaLM) (Eure)"}},"typeVersion":1},{"id":"96c7f79b-d17b-44b7-b626-e3d917514b38","name":"Send message1","type":"n8n-nodes-base.whatsApp","position":[-176,1120],"webhookId":"23834751-5066-48ba-8e19-549680df2b27","parameters":{"textBody":"=What was communicated does not reflect our policies or is not relevant.","operation":"send","phoneNumberId":"470271332838881","additionalFields":{},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"24bc71fb-c49a-468a-8665-707aff2a08b2","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-2160,480],"webhookId":"fee41e51-51d1-48bc-a519-b314f300981b","parameters":{"options":{"responseMode":"responseNodes"}},"typeVersion":1.4},{"id":"a7f4878a-e5be-4b64-81f0-d0f9d432cca0","name":"Postgres Chat Memory","type":"@n8n/n8n-nodes-langchain.memoryPostgresChat","position":[320,704],"parameters":{"sessionKey":"={{ $('Normalize').item.json.sessionId }}","sessionIdType":"customKey"},"credentials":{"postgres":{"id":"le1HdtN9fvIpulJo","name":"Postgres Local (test_n8n)"}},"typeVersion":1.3},{"id":"e91c8d86-3fc8-406a-9c2b-fd0d2656b8bd","name":"Normalize","type":"n8n-nodes-base.set","position":[-736,768],"parameters":{"options":{},"assignments":{"assignments":[{"id":"125c9831-791b-4b6e-979b-ceda1d77ad7a","name":"message","type":"string","value":"={{ $json.message }}"},{"id":"a802bf83-f88a-4eb1-b4bd-5b253a15e2cb","name":"sessionId","type":"string","value":"={{ $json.sessionId }}"},{"id":"3014000a-962e-449c-93a9-99fe74a1a21e","name":"type","type":"string","value":"chat"}]}},"typeVersion":3.4},{"id":"24f137f3-973b-4be8-a811-ab889f516c55","name":"Switch","type":"n8n-nodes-base.switch","position":[1872,432],"parameters":{"rules":{"values":[{"outputKey":"WhatsApp","conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"05f0da8d-ac5d-4bea-b691-9f2468efa664","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $('Normalize').item.json.type }}","rightValue":"whatsapp"}]},"renameOutput":true},{"outputKey":"Chat","conditions":{"options":{"version":3,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"93f83728-df15-4304-9b95-3ca321cb1abb","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $('Normalize').item.json.type }}","rightValue":"chat"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.4},{"id":"839acb59-e122-4f64-aa6b-d24bcbb9d3d1","name":"Escalation1","type":"@n8n/n8n-nodes-langchain.chatHitlTool","position":[1088,912],"webhookId":"e839818f-2d86-432c-a7e6-55cfc64368bd","parameters":{"message":"=The agent wants to call {{ $tool.name }}\n\n{{ \n $tool.parameters.keys()\n .map(\n param => \n `${param}: ${$tool.parameters[param]} \\n`\n )\n .join('')\n}}","options":{"limitWaitTime":{"values":{"resumeUnit":"minutes","resumeAmount":45}}},"blockUserInput":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Block_User_Input', ``, 'boolean') }}","approvalOptions":{"values":{"approvalType":"double"}}},"typeVersion":1.2},{"id":"c474e2dd-44c7-477d-8b66-24d196723a4d","name":"Chat","type":"@n8n/n8n-nodes-langchain.chat","position":[2272,640],"webhookId":"83a401e2-d083-4264-95ab-e960020f28cc","parameters":{"message":"={{$json.output}}","options":{}},"typeVersion":1.2},{"id":"77313555-74a2-452e-86a5-8580627314dd","name":"Chat1","type":"@n8n/n8n-nodes-langchain.chat","position":[-176,944],"webhookId":"83a401e2-d083-4264-95ab-e960020f28cc","parameters":{"message":"=What was communicated does not reflect our policies or is not relevant.","options":{}},"typeVersion":1.2},{"id":"ba8be3a0-deb5-4452-9c04-5cabbdcaacc2","name":"Message","type":"n8n-nodes-base.set","position":[-1056,800],"parameters":{"options":{},"assignments":{"assignments":[{"id":"c53cd9f9-77c1-4331-98ff-bfc9bdf95a3c","name":"message","type":"string","value":"={{ $('WhatsApp Trigger').item.json.messages[0].text.body }}"},{"id":"87dbdb41-66ba-4c02-a441-a6b44777dcbd","name":"sessionId","type":"string","value":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},{"id":"6e097caf-b3d4-4a17-8f63-57aa735e12ac","name":"type","type":"string","value":"whatsapp"}]}},"typeVersion":3.4},{"id":"47783407-0d84-4172-9e19-589f3b1e9a61","name":"From Chat","type":"n8n-nodes-base.set","position":[-1056,480],"parameters":{"options":{},"assignments":{"assignments":[{"id":"c53cd9f9-77c1-4331-98ff-bfc9bdf95a3c","name":"message","type":"string","value":"={{ $json.chatInput }}"},{"id":"e355708a-2353-46c9-9423-9e15ea731955","name":"sessionId","type":"string","value":"={{ $json.sessionId }}"}]}},"typeVersion":3.4},{"id":"f7e49b4c-5e99-424c-8429-7904e1c0520f","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-2256,320],"parameters":{"color":7,"width":1392,"height":368,"content":"## STEP 1 - Chat Input\nMessage from chatbot"},"typeVersion":1},{"id":"ec999d01-a788-43f5-92c1-58414b37697b","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-2256,720],"parameters":{"color":7,"width":1392,"height":656,"content":"## STEP 1 bis - WhatsApp Input\nMessage (text or audio with speech to text) from WhatsApp"},"typeVersion":1},{"id":"44f25d5d-3373-4007-b6e3-78c8c00f565c","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-832,320],"parameters":{"color":7,"width":880,"height":1056,"content":"## STEP 2 - Guardrails\n"},"typeVersion":1},{"id":"0c46b4c3-a6b6-4127-8163-3b8fec3d6bc1","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[96,320],"parameters":{"color":7,"width":944,"height":1056,"content":"## STEP 3 - AI Agent\n[Clone this sheet](https://docs.google.com/spreadsheets/d/1DM24yhANppmCu92D3St6GpMh2He7L2feizajN0aLDrU/edit?usp=sharing) for example of simple database"},"typeVersion":1},{"id":"d59bae7b-3ead-4218-808b-c20ae85cb857","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1072,784],"parameters":{"color":7,"width":592,"height":592,"content":"## STEP 3 bis - Escalation\nEscalation with Chatbot or WhatsApp (select one)"},"typeVersion":1},{"id":"a4e9a4c5-197c-4162-a3c4-af42e5fbadac","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[2144,-16],"parameters":{"color":7,"width":1264,"height":496,"content":"## STEP 4 - WhatsApp Response"},"typeVersion":1},{"id":"5ec9105b-012c-4dfa-a04c-7296691f97ec","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[2144,512],"parameters":{"color":7,"width":1264,"height":336,"content":"## STEP 4 bis - Chatbot Response\n"},"typeVersion":1},{"id":"d096f221-ab1c-41bb-b287-4d192eb77d7b","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-2256,-656],"parameters":{"width":1392,"height":560,"content":"## AI-Powered WhatsApp Chatbot\nThis workflow implements an **AI-powered WhatsApp booking assistant** for a hair salon. The system allows customers to **book, reschedule, or cancel appointments automatically via text or voice messages on WhatsApp**.\n\nThe workflow supports **both text and voice messages**. \n\n### How it works\n\nThis workflow acts as an **AI-powered WhatsApp booking assistant** that processes both **text and voice messages**. Incoming messages from WhatsApp or a chat interface are captured, and voice notes are automatically downloaded and transcribed using **OpenAI Whisper**. The message then passes through a **Guardrails layer (Google Gemini)** that filters unsafe or policy-violating inputs before reaching the AI agent.\n\nThe **AI Agent (βEmmaβ)** interprets the userβs intent and decides which tools to call. It checks or creates clients in **Google Sheets**, manages appointments in **Google Calendar** (check availability, create, update, cancel), and escalates unsupported requests via **Gmail or human-in-the-loop channels**. Conversation history is stored in **PostgreSQL** for context. Responses are sent back through WhatsApp as **text or synthesized voice (TTS)** depending on the original message type.\n\n### Setup steps\n\nTo deploy the workflow, configure integrations and update key resources used by the automation. First, connect required **credentials** including Google Calendar, Google Sheets, Gmail, WhatsApp Business API, OpenAI/OpenRouter for transcription and TTS, Google Gemini for AI processing and guardrails, and a **Postgres database** for conversation memory.\n\nNext, prepare **Google Sheets** as a lightweight CRM by creating a sheet with columns such as *Phone Number*, *Client*, and *Service*, then insert its **Document ID** in the relevant nodes. Verify the correct **Google Calendar ID** for appointment management. Configure the **WhatsApp Trigger and messaging nodes** with your Phone Number ID, update the escalation **email recipient**, and review the **AI prompts** to customize salon details, assistant behavior, and guardrail thresholds before activating the workflow.\n"},"typeVersion":1},{"id":"d8b42d4f-0e37-4b7d-98e1-87af9d4a4be1","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-2256,-48],"parameters":{"color":7,"width":1392,"height":336,"content":"## STEP 5 - Error"},"typeVersion":1},{"id":"fabd4439-a9b1-4d7c-9242-30486c2c1363","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-816,-656],"parameters":{"color":7,"width":736,"height":736,"content":"## MY NEW YOUTUBE CHANNEL\nπ [Subscribe to my new **YouTube channel**](https://youtube.com/@n3witalia). Here Iβll share videos and Shorts with practical tutorials and **FREE templates for n8n**.\n\n[](https://youtube.com/@n3witalia)"},"typeVersion":1}],"active":false,"pinData":{},"settings":{"binaryMode":"separate","availableInMCP":false,"executionOrder":"v1"},"versionId":"30e3114d-dee1-43cb-bf17-5c20f8d09a5a","connections":{"Audio":{"main":[[{"node":"Normalize","type":"main","index":0}]]},"Switch":{"main":[[{"node":"From audio to audio?","type":"main","index":0}],[{"node":"Chat","type":"main","index":0}]]},"Message":{"main":[[{"node":"Normalize","type":"main","index":0}]]},"From Chat":{"main":[[{"node":"Normalize","type":"main","index":0}]]},"Normalize":{"main":[[{"node":"Guardrails","type":"main","index":0}]]},"Add client":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Calculator":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Escalation":{"ai_tool":[[]]},"Get events":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Guardrails":{"main":[[{"node":"Virtual Assistant","type":"main","index":0}],[{"node":"Chat1","type":"main","index":0}]]},"Input type":{"main":[[{"node":"Message","type":"main","index":0}],[{"node":"Get Audio Url","type":"main","index":0}],[{"node":"Not supported","type":"main","index":0}]]},"New client":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Send Email":{"ai_tool":[[{"node":"Escalation","type":"ai_tool","index":0},{"node":"Escalation1","type":"ai_tool","index":0}]]},"Escalation1":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Create event":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Delete event":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Update event":{"ai_tool":[[{"node":"Virtual Assistant","type":"ai_tool","index":0}]]},"Get Audio Url":{"main":[[{"node":"Download Audio","type":"main","index":0}]]},"Download Audio":{"main":[[{"node":"Transcribe Audio","type":"main","index":0}]]},"Transcribe Audio":{"main":[[{"node":"Audio","type":"main","index":0}]]},"WhatsApp Trigger":{"main":[[{"node":"Input type","type":"main","index":0}]]},"Virtual Assistant":{"main":[[{"node":"Switch","type":"main","index":0}]]},"From audio to audio?":{"main":[[{"node":"Generate Audio Response","type":"main","index":0}],[{"node":"Send message","type":"main","index":0}]]},"Postgres Chat Memory":{"ai_memory":[[{"node":"Virtual Assistant","type":"ai_memory","index":0}]]},"Fix mimeType for Audio":{"main":[[{"node":"Send audio","type":"main","index":0}]]},"Workflow Error Handler":{"main":[[{"node":"Notify: Workflow Error","type":"main","index":0}]]},"Generate Audio Response":{"main":[[{"node":"Fix mimeType for Audio","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Virtual Assistant","type":"ai_languageModel","index":0}]]},"Google Gemini Chat Model1":{"ai_languageModel":[[{"node":"Guardrails","type":"ai_languageModel","index":0}]]},"When chat message received":{"main":[[{"node":"From Chat","type":"main","index":0}]]}}}
\ No newline at end of file