This workflow follows the Informationextractor → Google Gemini Chat recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Agendamento Instituto Ariana Borges - Corrigido",
"nodes": [
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1,
"position": [
7648,
5792
],
"id": "056cd582-4b49-4ae2-b1c5-03c1f732272a",
"name": "Google Gemini Chat Model1",
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ available: $json.available, message: $json.message, suggestedTimes: $json.suggestedTimes }) }}",
"options": {
"responseCode": 200,
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.2,
"position": [
8368,
6016
],
"id": "7cbff091-0c1c-4062-b6aa-3557dfd82174",
"name": "Responder - Disponibilidade1"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: false, message: 'N\u00e3o foi poss\u00edvel completar o agendamento. Por favor, tente novamente ou entre em contato via WhatsApp.', error: $json.message || 'Erro desconhecido' }) }}",
"options": {
"responseCode": 500,
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.2,
"position": [
8368,
5776
],
"id": "60124c6a-20ae-4503-9f48-4f00f2988982",
"name": "Responder - Erro1"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, message: 'Tudo certo! Voc\u00ea est\u00e1 agendado(a) para ' + $('Processar Resposta da IA1').item.json.interpretedDate + '. \ud83c\udf89', booking: { customer: $('Processar Resposta da IA1').item.json.customerName, service: $('Processar Resposta da IA1').item.json.serviceType, dateTime: $('Processar Resposta da IA1').item.json.interpretedDate, calendarEventId: $json.id } }) }}",
"options": {
"responseCode": 200,
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.2,
"position": [
8368,
5584
],
"id": "1579ba20-6257-4fcc-a1ac-e34e93225905",
"name": "Responder - Agendamento Confirmado1"
},
{
"parameters": {
"jsCode": "const aiResponse = $input.first().json.output;\nconst preferredTimeframe = $input.all().find(item => item.json.preferredTimeframe)?.json.preferredTimeframe || '';\nlet availabilityCheck;\n\ntry {\n // Check if aiResponse is already an object or a string\n if (typeof aiResponse === 'object') {\n availabilityCheck = aiResponse;\n } else if (typeof aiResponse === 'string') {\n const cleanJson = aiResponse.replace(/```json\\n?|```/g, '').trim();\n availabilityCheck = JSON.parse(cleanJson);\n } else {\n throw new Error('Formato de resposta inesperado');\n }\n} catch (error) {\n availabilityCheck = {\n available: true,\n requestedDateTime: new Date().toISOString(),\n message: \"Estamos verificando a disponibilidade.\",\n suggestedTimes: []\n };\n}\n\n// Formatar o hor\u00e1rio solicitado de forma leg\u00edvel\nlet requestedTimeFormatted = preferredTimeframe;\nif (availabilityCheck.requestedDateTime) {\n try {\n const dt = new Date(availabilityCheck.requestedDateTime);\n const daysOfWeek = ['Domingo', 'Segunda-feira', 'Ter\u00e7a-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'S\u00e1bado'];\n const day = daysOfWeek[dt.getDay()];\n const date = dt.getDate();\n const month = dt.getMonth() + 1;\n const hour = dt.getHours();\n requestedTimeFormatted = `${day}, ${date}/${month} \u00e0s ${hour}h`;\n } catch (e) {\n // Manter o formato original se falhar\n }\n}\n\n// Gerar hor\u00e1rios de fallback se IA n\u00e3o retornou\nif (!availabilityCheck.suggestedTimes || availabilityCheck.suggestedTimes.length === 0) {\n const now = new Date();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n \n const dayAfter = new Date(now);\n dayAfter.setDate(dayAfter.getDate() + 2);\n \n const daysOfWeek = ['Domingo', 'Segunda-feira', 'Ter\u00e7a-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'S\u00e1bado'];\n \n availabilityCheck.suggestedTimes = [\n `${daysOfWeek[tomorrow.getDay()]}, ${tomorrow.getDate()}/${tomorrow.getMonth() + 1} \u00e0s 9h`,\n `${daysOfWeek[tomorrow.getDay()]}, ${tomorrow.getDate()}/${tomorrow.getMonth() + 1} \u00e0s 14h`,\n `${daysOfWeek[dayAfter.getDay()]}, ${dayAfter.getDate()}/${dayAfter.getMonth() + 1} \u00e0s 10h`\n ];\n}\n\nconst calendarEvents = $input.all().filter(item => item.json.id).map(item => ({\n start: item.json.start?.dateTime,\n end: item.json.end?.dateTime,\n summary: item.json.summary\n}));\n\nconst requestedDateTime = availabilityCheck.requestedDateTime;\nconst hasConflict = calendarEvents.some(event => {\n if (!event.start || !requestedDateTime) return false;\n return new Date(event.start).toISOString() === new Date(requestedDateTime).toISOString();\n});\n\nlet finalMessage;\nif (hasConflict) {\n finalMessage = `\ud83d\ude14 Infelizmente ${requestedTimeFormatted} j\u00e1 est\u00e1 ocupado.`;\n if (availabilityCheck.suggestedTimes?.length > 0) {\n finalMessage += `\\n\\nHor\u00e1rios dispon\u00edveis:\\n${availabilityCheck.suggestedTimes.map(t => `\u2022 ${t}`).join('\\n')}`;\n }\n} else {\n finalMessage = `\u2705 \u2728 \u00d3tima not\u00edcia! ${requestedTimeFormatted} est\u00e1 dispon\u00edvel!`;\n if (availabilityCheck.suggestedTimes?.length > 0) {\n finalMessage += `\\n\\nOutros hor\u00e1rios dispon\u00edveis:\\n${availabilityCheck.suggestedTimes.map(t => `\u2022 ${t}`).join('\\n')}`;\n }\n}\n\nreturn {\n json: {\n available: !hasConflict,\n message: finalMessage,\n requestedDateTime: requestedDateTime,\n suggestedTimes: availabilityCheck.suggestedTimes || []\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
8144,
6016
],
"id": "bdff1360-b42c-4340-8485-70231f9a1e31",
"name": "Processar Disponibilidade1"
},
{
"parameters": {
"operation": "getAll",
"calendar": {
"__rl": true,
"value": "24ce01fc2a4267089544e584a637f9c021ad6c10ba81a0d8eaa44f66f6767d83@group.calendar.google.com",
"mode": "list",
"cachedResultName": "Site 2026"
},
"options": {
"timeZone": "America/Sao_Paulo"
}
},
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1.3,
"position": [
7920,
6016
],
"id": "56556c14-ae2b-430d-b3b4-d531219d70cc",
"name": "Google Calendar - Listar Eventos1",
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"calendar": {
"__rl": true,
"value": "24ce01fc2a4267089544e584a637f9c021ad6c10ba81a0d8eaa44f66f6767d83@group.calendar.google.com",
"mode": "list",
"cachedResultName": "Site 2026"
},
"start": "={{$json.startDateTime}}",
"end": "={{$json.endDateTime}}",
"options": {
"description": "={{$json.eventDescription}}",
"summary": "={{$json.eventSummary}}",
"attendees": [
"={{$json.customerEmail}}"
],
"sendUpdates": "all",
"timeZone": "America/Sao_Paulo"
}
},
"type": "n8n-nodes-base.googleCalendar",
"typeVersion": 1.3,
"position": [
8144,
5680
],
"id": "7d661366-eda9-4961-9fe7-6a851f9bd160",
"name": "Google Calendar - Criar Evento1",
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const aiResponse = $input.item.json.output;\n\nlet parsedDate;\ntry {\n // Check if aiResponse is already an object or a string\n if (typeof aiResponse === 'object') {\n parsedDate = aiResponse;\n } else if (typeof aiResponse === 'string') {\n const cleanJson = aiResponse.replace(/```json\\n?|```/g, '').trim();\n parsedDate = JSON.parse(cleanJson);\n } else {\n throw new Error('Formato de resposta inesperado');\n }\n} catch (error) {\n throw new Error('Erro ao parsear resposta da IA: ' + error.message);\n}\n\nif (!parsedDate.startDateTime || !parsedDate.endDateTime) {\n throw new Error('IA n\u00e3o retornou datas v\u00e1lidas');\n}\n\nreturn {\n json: {\n customerName: $input.item.json.customerName,\n customerPhone: $input.item.json.customerPhone,\n customerEmail: $input.item.json.customerEmail,\n serviceType: $input.item.json.serviceType,\n description: $input.item.json.description,\n startDateTime: parsedDate.startDateTime,\n endDateTime: parsedDate.endDateTime,\n interpretedDate: parsedDate.interpretedDate,\n eventSummary: `${$input.item.json.serviceType} - ${$input.item.json.customerName}`,\n eventDescription: `\ud83d\udccb Agendamento\\n\\n\ud83d\udc64 Cliente: ${$input.item.json.customerName}\\n\ud83d\udce7 Email: ${$input.item.json.customerEmail}\\n\ud83d\udcf1 Telefone: ${$input.item.json.customerPhone}\\n\\n\ud83c\udf1f Servi\u00e7o: ${$input.item.json.serviceType}\\n\ud83d\udcdd ${$input.item.json.description}`\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
7920,
5680
],
"id": "f14f0ca3-edb5-42e7-8653-f82e37612337",
"name": "Processar Resposta da IA1"
},
{
"parameters": {
"text": "={{ $json.preferredTimeframe }}",
"schemaType": "fromJson",
"jsonSchemaExample": "{\n \"available\": true,\n \"requestedDateTime\": \"YYYY-MM-DDTHH:mm:00-03:00\",\n \"message\": \"mensagem amig\u00e1vel sobre disponibilidade\",\n \"suggestedTimes\": [\"hor\u00e1rio1\", \"hor\u00e1rio2\", \"hor\u00e1rio3\"]\n}",
"options": {
"systemPromptTemplate": "Voc\u00ea \u00e9 um assistente que verifica disponibilidade de agenda.\n\nDATA ATUAL: {{$json.currentDate}}\nTIMEZONE: America/Sao_Paulo\nHOR\u00c1RIO COMERCIAL: 9h \u00e0s 19h (Segunda \u00e0 Quarta)\nFECHADO: Quinta, Sexta, S\u00e1bado e Domingo\n\nSua tarefa:\n1. Interpretar o hor\u00e1rio solicitado\n2. Converter para data ISO 8601 com timezone -03:00\n3. Verificar se est\u00e1 dentro do hor\u00e1rio comercial (Segunda \u00e0 Quarta, 9h \u00e0s 19h)\n4. OBRIGAT\u00d3RIO: Sugerir SEMPRE pelo menos 3 hor\u00e1rios alternativos dispon\u00edveis\n\nFormato de resposta (JSON):\n- available: boolean (true se o hor\u00e1rio est\u00e1 dentro do hor\u00e1rio comercial E \u00e9 Segunda/Ter\u00e7a/Quarta, false caso contr\u00e1rio)\n- requestedDateTime: string ISO 8601 (exemplo: 2026-01-30T14:00:00-03:00)\n- message: string com mensagem amig\u00e1vel sobre a disponibilidade\n- suggestedTimes: array de strings - OBRIGAT\u00d3RIO incluir pelo menos 3 hor\u00e1rios (exemplos: Segunda-feira \u00e0s 9h, Ter\u00e7a-feira \u00e0s 14h, Quarta-feira \u00e0s 10h)\n\nIMPORTANTE: \n- O campo suggestedTimes NUNCA pode estar vazio. Sempre sugira hor\u00e1rios pr\u00f3ximos ao solicitado.\n- S\u00f3 aceite hor\u00e1rios de Segunda \u00e0 Quarta, das 9h \u00e0s 19h\n- Rejeite qualquer hor\u00e1rio fora deste per\u00edodo\n\nRetorne APENAS o JSON sem markdown."
}
},
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
"typeVersion": 1,
"position": [
7648,
6016
],
"id": "d1a33f5c-1bb9-46b5-9d3a-ee2a4795c57c",
"name": "IA - Verificar Disponibilidade1"
},
{
"parameters": {
"text": "={{ $json.preferredTimeframe }}",
"schemaType": "fromJson",
"jsonSchemaExample": "{\n \"startDateTime\": \"YYYY-MM-DDTHH:mm:00-03:00\",\n \"endDateTime\": \"YYYY-MM-DDTHH:mm:00-03:00\",\n \"interpretedDate\": \"descri\u00e7\u00e3o leg\u00edvel\"\n}",
"options": {
"systemPromptTemplate": "Voc\u00ea \u00e9 um assistente que converte texto em datas no formato ISO 8601.\n\nDATA ATUAL DE REFER\u00caNCIA: {{$json.currentDate}}\nTIMEZONE: America/Sao_Paulo (UTC-03:00)\nHOR\u00c1RIO COMERCIAL: 9h \u00e0s 19h (Segunda \u00e0 Quarta)\nFECHADO: Quinta, Sexta, S\u00e1bado e Domingo\n\nSua tarefa:\n1. Interpretar o texto de hor\u00e1rio preferido\n2. Converter para formato ISO 8601 com timezone -03:00\n3. Dura\u00e7\u00e3o padr\u00e3o: 1 hora\n4. Se for \"manh\u00e3\": 9h, \"tarde\": 14h, \"qualquer hor\u00e1rio\": 14h\n\nFormato de resposta (JSON):\n- startDateTime: string ISO 8601 (exemplo: 2026-01-30T14:00:00-03:00)\n- endDateTime: string ISO 8601 (1 hora depois do start)\n- interpretedDate: string leg\u00edvel (exemplo: Ter\u00e7a-feira, 30 de janeiro \u00e0s 14h)\n\nRetorne APENAS o JSON sem markdown."
}
},
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
"typeVersion": 1,
"position": [
7648,
5568
],
"id": "aac6e532-5ebb-487e-ac12-ed72d8f17c4a",
"name": "IA - Converter Texto para Data1"
},
{
"parameters": {
"jsCode": "const preferredTimeframe = $input.item.json.preferred_timeframe;\nconst currentDate = new Date().toISOString();\n\nreturn {\n json: {\n preferredTimeframe,\n currentDate\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
7344,
6016
],
"id": "23e66ba8-85c8-4a22-a842-b1db88564e26",
"name": "Extrair Dados de Disponibilidade1"
},
{
"parameters": {
"jsCode": "const customerName = $input.item.json.customer_name;\nconst customerPhone = $input.item.json.customer_phone;\nconst customerEmail = $input.item.json.customer_email;\nconst serviceType = $input.item.json.service_type;\nconst description = $input.item.json.description;\nconst preferredTimeframe = $input.item.json.preferred_timeframe;\n\nreturn {\n json: {\n customerName,\n customerPhone,\n customerEmail,\n serviceType,\n description,\n preferredTimeframe,\n currentDate: new Date().toISOString()\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
7344,
5680
],
"id": "d0c753bf-8322-4088-8291-de445f49b4b2",
"name": "Extrair Dados do Booking1"
},
{
"parameters": {
"httpMethod": "POST",
"path": "book_appointment",
"responseMode": "responseNode",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
7120,
5680
],
"id": "82829b5d-965c-4d3e-a51f-a1bd2f991833",
"name": "Webhook - Agendar1"
},
{
"parameters": {
"httpMethod": "POST",
"path": "get_availability",
"responseMode": "responseNode",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
7120,
6016
],
"id": "1e27ebc3-c6cd-46d4-8896-df2c434efd3b",
"name": "Webhook - Verificar Disponibilidade1"
}
],
"connections": {
"Google Gemini Chat Model1": {
"ai_languageModel": [
[
{
"node": "IA - Verificar Disponibilidade1",
"type": "ai_languageModel",
"index": 0
},
{
"node": "IA - Converter Texto para Data1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Processar Disponibilidade1": {
"main": [
[
{
"node": "Responder - Disponibilidade1",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Listar Eventos1": {
"main": [
[
{
"node": "Processar Disponibilidade1",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar - Criar Evento1": {
"main": [
[
{
"node": "Responder - Agendamento Confirmado1",
"type": "main",
"index": 0
}
]
],
"error": [
[
{
"node": "Responder - Erro1",
"type": "main",
"index": 0
}
]
]
},
"Processar Resposta da IA1": {
"main": [
[
{
"node": "Google Calendar - Criar Evento1",
"type": "main",
"index": 0
}
]
]
},
"IA - Verificar Disponibilidade1": {
"main": [
[
{
"node": "Google Calendar - Listar Eventos1",
"type": "main",
"index": 0
}
]
]
},
"IA - Converter Texto para Data1": {
"main": [
[
{
"node": "Processar Resposta da IA1",
"type": "main",
"index": 0
}
]
]
},
"Extrair Dados de Disponibilidade1": {
"main": [
[
{
"node": "IA - Verificar Disponibilidade1",
"type": "main",
"index": 0
}
]
]
},
"Extrair Dados do Booking1": {
"main": [
[
{
"node": "IA - Converter Texto para Data1",
"type": "main",
"index": 0
}
]
]
},
"Webhook - Agendar1": {
"main": [
[
{
"node": "Extrair Dados do Booking1",
"type": "main",
"index": 0
}
]
]
},
"Webhook - Verificar Disponibilidade1": {
"main": [
[
{
"node": "Extrair Dados de Disponibilidade1",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 0,
"meta": {
"templateCredsSetupCompleted": true
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleCalendarOAuth2ApigooglePalmApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Agendamento Instituto Ariana Borges - Corrigido. Uses lmChatGoogleGemini, googleCalendar, informationExtractor. Webhook trigger; 14 nodes.
Source: https://github.com/designrique/site-ariana-borges/blob/bb6e58b46e36bdb3d7fb3d9e471c7b11bd4c21c3/guias/n8n-workflow-agendamento-corrigido.json.bak — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Who is this for? Event organizers, conference planners, and marketing teams fighting registration drop-off who want 4-field forms with LinkedIn-level attendee intelligence. What problem is this workfl
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
This n8n template automates scraping content from Skool communities using the Olostep API. It collects structured data from Skool pages and stores it in a clean format, making it easy to analyze commu
This n8n template monitors specified GitHub repositories. When a new release is published, it automatically fetches the information, uses AI (Google Gemini by default) to summarize and translate it in
It is ideal for businesses handling vendor invoices, reimbursement forms, or bulk document intake.