This workflow corresponds to n8n.io template #5001 — we link there as the canonical source.
This workflow follows the Chainllm → Gmail 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 →
{
"id": "zQlHcVCTUpdWYRsK",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Google Calendar Interview Scheduler",
"tags": [],
"nodes": [
{
"id": "c5a1438d-dbbf-4d43-b2b5-27e5e4a63886",
"name": "Google Sheets Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
0,
0
],
"parameters": {
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU/edit#gid=0",
"cachedResultName": "Foglio1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU/edit?usp=drivesdk",
"cachedResultName": "Hiring Prospects"
}
},
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "769172ac-47bb-4da3-931c-e89b92b499a7",
"name": "Google Calendar",
"type": "n8n-nodes-base.googleCalendar",
"position": [
440,
0
],
"parameters": {
"end": "={{ $json.endSlot }}",
"start": "={{ $json.nextSlot }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"additionalFields": {}
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "659d43c2-cee0-4406-9863-bd07787cfa8d",
"name": "Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
1036,
0
],
"parameters": {
"sendTo": "={{ $('Google Sheets Trigger').item.json.EMAIL }}",
"message": "={{ $json.output.body }}",
"options": {},
"subject": "Interview Details",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "02f6765c-e880-4007-87e0-39d1fc57ab55",
"name": "Basic LLM Chain",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
660,
0
],
"parameters": {
"text": "={{ $('Google Sheets Trigger').item.json.NAME }}\n\n{{ $('Google Sheets Trigger').item.json.EDUCATIONAL}}\n\nLink for calendar: {{ $json.htmlLink }}\n\nMy name is Surya, I'm from Techdome",
"batching": {},
"messages": {
"messageValues": [
{
"message": "You are a helpful email writing assistant. You take the information I provide you with and write a personlised email to the candidate we are calling in for an interview. The goal is to send an email with Google Calendar Link. Be straight to the point. The email should start with a 15-20 word opening statement, then details to the link and then signature "
}
]
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.7
},
{
"id": "be63e6bc-0645-4e5f-aab8-abd4537b12b5",
"name": "Azure OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
688,
220
],
"parameters": {
"model": "gpt-4o",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "3ac86b4b-67a6-4224-9356-028b409240e3",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
808,
220
],
"parameters": {
"jsonSchemaExample": "{\n\t\"body\": \"\"\n}"
},
"typeVersion": 1.2
},
{
"id": "266dc8e1-f214-4b23-847c-dce9f95e1b58",
"name": "Code",
"type": "n8n-nodes-base.code",
"position": [
220,
0
],
"parameters": {
"jsCode": "// n8n expects an array of objects as output\n\nconst now = new Date();\n\n// Define the free slots: Monday, Wednesday, Friday at 3:00 PM\n// JavaScript Date: 0=Sunday, 1=Monday, ..., 5=Friday, 6=Saturday\nconst slots = [\n { day: 1, hour: 15 }, // Monday 3 PM\n { day: 3, hour: 15 }, // Wednesday 3 PM\n { day: 5, hour: 15 }, // Friday 3 PM\n];\n\n// Helper to get the next slot after 'now', always in the future (never today)\nfunction getNextSlot(now, slots) {\n let minDiff = Infinity;\n let nextSlotDate = null;\n\n for (const slot of slots) {\n let daysUntil = (slot.day - now.getDay() + 7) % 7;\n // Always skip today, even if the slot time hasn't passed\n if (daysUntil === 0) {\n daysUntil = 7;\n }\n\n const slotDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + daysUntil,\n slot.hour,\n 0,\n 0,\n 0\n );\n\n if (slotDate - now < minDiff) {\n minDiff = slotDate - now;\n nextSlotDate = slotDate;\n }\n }\n\n return nextSlotDate;\n}\n\n// Format as \"YYYY-MM-DD HH:MM:SS\"\nfunction formatDate(date) {\n const pad = (n) => n.toString().padStart(2, '0');\n return (\n date.getFullYear() +\n '-' +\n pad(date.getMonth() + 1) +\n '-' +\n pad(date.getDate()) +\n ' ' +\n pad(date.getHours()) +\n ':00:00'\n );\n}\n\nconst nextSlot = getNextSlot(now, slots);\n\n// Create the end time (1 hour after start)\nconst endSlot = new Date(nextSlot.getTime() + 60 * 60 * 1000);\n\nreturn [\n {\n json: {\n nextSlot: formatDate(nextSlot),\n endSlot: formatDate(endSlot)\n }\n }\n];\n"
},
"typeVersion": 2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "22ca5597-52e0-486b-93c0-5a57979dea68",
"connections": {
"Code": {
"main": [
[
{
"node": "Google Calendar",
"type": "main",
"index": 0
}
]
]
},
"Basic LLM Chain": {
"main": [
[
{
"node": "Gmail",
"type": "main",
"index": 0
}
]
]
},
"Google Calendar": {
"main": [
[
{
"node": "Basic LLM Chain",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets Trigger": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Azure OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Basic LLM Chain",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Basic LLM Chain",
"type": "ai_outputParser",
"index": 0
}
]
]
}
}
}
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.
azureOpenAiApigmailOAuth2googleCalendarOAuth2ApigoogleSheetsTriggerOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
SEO-Optimized Description:
Source: https://n8n.io/workflows/5001/ — 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.
Suggest Meeting Slots Using Ai. Uses gmailTrigger, lmChatOpenAi, toolWorkflow, stickyNote. Event-driven trigger; 21 nodes.
Calendar_scheduling. Uses gmailTrigger, lmChatOpenAi, toolWorkflow, stickyNote. Event-driven trigger; 21 nodes.
Calendar_scheduling. Uses gmailTrigger, lmChatOpenAi, toolWorkflow, googleCalendar. Event-driven trigger; 21 nodes.
This workflow automates voice reminders for upcoming appointments by generating a professional audio message and sending it to clients via email with the voice file attached.
The best content automation template in the market is now even better—with “deep research” on time-sensitive topics\! Unlike most n8n content automation templates that are mainly for “demo purposes,”