This workflow corresponds to n8n.io template #13309 — we link there as the canonical source.
This workflow follows the Agent → Google Calendar 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": "gt1NQI8XexIKUkI0",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "MyScheduling_Assistant",
"tags": [],
"nodes": [
{
"id": "ef68173e-6bff-42ab-9729-6ee4947d4ef7",
"name": "Receive Bot Messages",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-624,
-96
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "181e856b-f7d2-44b9-990d-0161b33845a7",
"name": "AI Agent for Google Calendar",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
416,
-96
],
"parameters": {
"text": "=# Google Calendar AI Agent Instructions\n\n## Role\n\nYou are an AI assistant designed to manage calendar events for the user using Google Calendar.\n\nYour goal is to help the user:\n- Save time \n- Avoid scheduling conflicts \n- Maintain a clean, organized calendar system \n\n---\n\n## Core Responsibilities\n\nYou are responsible for:\n\n- Creating new calendar events \n- Updating existing events \n- Deleting events \n- Checking availability for specific dates and time ranges \n- Rescheduling meetings \n- Adding descriptions, locations, and Google Meet links \n- Setting reminders and notifications \n- Managing recurring events \n\n---\n\n## Google Calendar Integration Rules\n\nYou must:\n\n1. Use **Google Calendar as the single source of truth**.\n2. Always check for **time conflicts before creating events**.\n3. Confirm the **time zone** if not explicitly specified.\n4. Format all dates and times in **ISO 8601 format** when interacting with APIs.\n5. Include:\n - Event title \n - Start time \n - End time \n - Description (if provided) \n - Attendees (if provided) \n\nIf required information is missing, ask clarifying questions before taking action.\n\n---\n\n## Event Creation Logic\n\nWhen the user requests to create an event:\n\n### Step 1: Extract\n- Title \n- Date \n- Start time \n- End time or duration \n- Time zone \n- Attendees \n- Description \n\n### Step 2: Validate\n- Check availability for the requested time.\n- Detect conflicts.\n\n### Step 3: Resolve\n- If a conflict exists \u2192 Suggest 2\u20133 alternative available time slots.\n- If no conflict exists \u2192 Create the event.\n\n### Step 4: Confirm\nProvide full confirmation including:\n- Title \n- Date \n- Start and end time \n- Time zone \n- Attendees \n- Meeting link (if applicable) \n\n---\n\n## Updating or Rescheduling Logic\n\nWhen modifying events:\n\n1. Identify the event using:\n - Title \n - Date \n - Event ID \n\n2. Retrieve the current event details.\n\n3. Apply requested changes.\n\n4. Re-check availability if the time is changed.\n\n5. Confirm the successful update.\n\n---\n\n## Communication Style\n\n- Be concise and clear.\n- Always confirm actions taken.\n- Ask targeted clarifying questions when needed.\n- Never assume missing information.\n\n---\n\n## Error Handling\n\nIf:\n\n- Authentication fails \u2192 Request reauthorization.\n- Event is not found \u2192 Ask for additional identifying details.\n- API error occurs \u2192 Retry once, then inform the user clearly.\n\n---\n\n## Important Guidelines\n\n1. Always provide a name for the event when creating one. \n - An event must never be created without a clear, descriptive title.\n\n2. To update or delete an event, you must first retrieve the event ID using the `\"get event\"` tool. \n - Without the event ID, you cannot successfully edit or delete events. \n - Always perform a retrieval step before attempting modifications.\n\n3. Current time reference: `{\n \"currentTimeUAE\": \"{{ DateTime.now().setZone('Asia/Dubai').toISO() }}\"\n}\n` \n - Use this value when resolving relative time expressions such as:\n - \"tomorrow\"\n - \"next Monday\"\n - \"in 2 hours\"\n - All time calculations must be based on this reference.\n\n---\n\n### User Input:\n{{ $json.content.parts[0].text }}\n{{ $json.message.text }}",
"options": {},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "fd3db6e0-fda5-4b43-868f-007f4171838f",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
32,
160
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5-nano",
"cachedResultName": "gpt-5-nano"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "15dacb7b-3c6f-4b51-b137-63eccdc204fd",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
144,
160
],
"parameters": {
"sessionKey": "5883770591",
"sessionIdType": "customKey",
"contextWindowLength": 10
},
"typeVersion": 1.3
},
{
"id": "3be01909-94d8-4e68-8e4b-0a7f91ddec28",
"name": "Create an event in Google Calendar",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
400,
128
],
"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": "user@example.com"
},
"additionalFields": {
"summary": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Summary', ``, 'string') }}"
},
"useDefaultReminders": false
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "1a92252e-5500-4ae1-bdaa-20f8824f84a6",
"name": "Get many events in Google Calendar",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
576,
144
],
"parameters": {
"limit": 10,
"options": {
"fields": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Fields', ``, 'string') }}"
},
"timeMax": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Before', ``, 'string') }}",
"timeMin": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('After', ``, 'string') }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "getAll"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "90ffc379-8691-4b4d-ad8a-c4f29ee76ac5",
"name": "Delete an event in Google Calendar",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
752,
144
],
"parameters": {
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', ``, 'string') }}",
"options": {},
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "delete"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "c724ee7b-d331-4ec6-b2a8-a88a42ddade3",
"name": "Update an event in Google Calendar",
"type": "n8n-nodes-base.googleCalendarTool",
"position": [
912,
144
],
"parameters": {
"eventId": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Event_ID', ``, 'string') }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "update",
"updateFields": {
"end": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', ``, 'string') }}",
"start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', ``, 'string') }}",
"summary": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Summary', ``, 'string') }}"
},
"useDefaultReminders": false
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "cd044b3f-2b6c-4f9f-8120-59b612e84535",
"name": "Send a summary action message",
"type": "n8n-nodes-base.telegram",
"position": [
1120,
-96
],
"parameters": {
"text": "={{ $json.output }}",
"chatId": "={{ $('Receive Bot Messages').item.json.message.chat.id }}",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "a8e3b4bc-ec39-4664-b77e-8369a1d31913",
"name": "Voice Note or Text?",
"type": "n8n-nodes-base.switch",
"position": [
-400,
-96
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Voice",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b11ad12e-f449-456a-913d-40498da8cc46",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.message.voice.file_id }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "Text",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "acb5e7b0-be18-4bf0-b555-0b40a0671697",
"operator": {
"type": "string",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{ $json.message.voice.file_id }}",
"rightValue": ""
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "b80b2751-e60e-43c3-ac28-e156e924741c",
"name": "Transcribe a recording",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
48,
-256
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-2.0-flash",
"cachedResultName": "models/gemini-2.0-flash"
},
"options": {},
"resource": "audio",
"inputType": "binary"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "ddbf3d7f-fe65-4116-98ac-876676b5c5be",
"name": "Scheduled Everyday 8 AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-592,
640
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 11
}
]
}
},
"typeVersion": 1.3
},
{
"id": "061a9164-ce27-4a3a-837e-3aa9ec138d72",
"name": "Retrive all meeting/event that you have",
"type": "n8n-nodes-base.googleCalendar",
"position": [
-384,
640
],
"parameters": {
"limit": 20,
"options": {},
"timeMax": "={{ DateTime.now().setZone('Asia/Dubai').endOf('day').toISO() }}",
"timeMin": "={{ DateTime.now().setZone('Asia/Dubai').startOf('day').toISO() }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"operation": "getAll"
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3,
"alwaysOutputData": true
},
{
"id": "d885429d-6095-4fdc-be42-a5249cac713d",
"name": "Daily Analytics Engine",
"type": "n8n-nodes-base.code",
"position": [
-128,
640
],
"parameters": {
"jsCode": "let totalMinutes = 0;\nlet meetings = [];\nlet busyBlocks = [];\n\nconst UAE_OFFSET = 4; // UTC+4\n\nfunction toUAE(dateString) {\n const date = new Date(dateString);\n date.setHours(date.getUTCHours() + UAE_OFFSET);\n return date;\n}\n\nfunction formatTime(date) {\n return date.toLocaleTimeString(\"en-AE\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: true\n });\n}\n\nconst now = new Date();\nconst todayStart = new Date(now);\ntodayStart.setHours(8 - UAE_OFFSET, 0, 0, 0);\n\nconst todayEnd = new Date(now);\ntodayEnd.setHours(18 - UAE_OFFSET, 0, 0, 0);\n\nfor (const item of items) {\n\n const startRaw = item.json.start?.dateTime || item.json.start?.date;\n const endRaw = item.json.end?.dateTime || item.json.end?.date;\n\n if (!startRaw || !endRaw) continue;\n\n const start = toUAE(startRaw);\n const end = toUAE(endRaw);\n\n if (isNaN(start) || isNaN(end)) continue;\n\n const duration = (end - start) / 60000;\n totalMinutes += duration;\n\n meetings.push({ start, end });\n busyBlocks.push([start, end]);\n}\n\nbusyBlocks.sort((a, b) => a[0] - b[0]);\n\nlet freeWindows = [];\nlet cursor = todayStart;\n\nfor (const block of busyBlocks) {\n if (block[0] > cursor) {\n freeWindows.push(\n `${formatTime(cursor)} - ${formatTime(block[0])}`\n );\n }\n cursor = block[1] > cursor ? block[1] : cursor;\n}\n\nif (cursor < todayEnd) {\n freeWindows.push(\n `${formatTime(cursor)} - ${formatTime(todayEnd)}`\n );\n}\n\nif (meetings.length === 0) {\n freeWindows = [\"08:00 AM - 06:00 PM\"];\n}\n\nreturn [{\n json: {\n totalHours: (totalMinutes / 60).toFixed(1),\n meetingCount: meetings.length,\n freeWindows,\n overloaded: meetings.length > 4\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "956ac590-4e8f-4515-837f-9873ceef90db",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1344,
-432
],
"parameters": {
"width": 640,
"height": 880,
"content": "## AI Calendar Assistant + Daily Executive Briefing\n\n### This workflow turns your Google Calendar into an intelligent scheduling system powered by Telegram and AI. You can create, update, delete, or reschedule meetings using natural language or voice messages. The assistant validates availability, prevents conflicts, and keeps your calendar structured automatically.\n\n### In addition, a daily scheduled analytics engine reviews your calendar and sends a productivity briefing to Telegram. It calculates total meeting hours, identifies deep work windows, and flags overloaded days. This transforms your calendar from passive storage into an active decision-support system.\n\n---\n\n### How it works\n1. Telegram receives text or voice messages. \n2. Voice notes are transcribed automatically. \n3. AI interprets intent and extracts event details. \n4. Google Calendar executes validated actions. \n5. Every morning, the system analyzes today's schedule and sends a briefing summary.\n\n---\n\n### Setup steps\n1. Connect Google Calendar OAuth. \n2. Add Telegram Bot credentials. \n3. Insert OpenAI API key. \n4. Add Google Gemini API for transcription. \n5. Confirm timezone is set to Asia/Dubai.\n\n---\n\n### Customization\n- Adjust work hours inside the analytics code node. \n- Modify overload threshold (default: 4 meetings). \n- Add CRM tagging for revenue meetings.\n"
},
"typeVersion": 1
},
{
"id": "12afaf9a-7447-4fe1-8cc9-4dbd92c093ae",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-368
],
"parameters": {
"color": 6,
"width": 352,
"height": 352,
"content": "## AI Scheduling Layer\n\nHandles Telegram input, transcription, AI intent parsing, and Google Calendar execution.\n"
},
"typeVersion": 1
},
{
"id": "82ed31ec-a833-4408-b5ea-64f7b1e2869a",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-192,
-416
],
"parameters": {
"color": 4,
"width": 352,
"height": 256,
"content": "## Voice Processing\n\nRetrieves Telegram voice notes and transcribes them before AI interpretation.\n"
},
"typeVersion": 1
},
{
"id": "8fef7301-e37e-4621-9c15-ed41ae63fab7",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
304
],
"parameters": {
"color": 2,
"width": 656,
"content": "## Google Calendar Actions\n\nCreates, updates, retrieves, and deletes events with validation.\n"
},
"typeVersion": 1
},
{
"id": "008508c2-544a-44f8-ab8c-f642ddf5ba88",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-624,
496
],
"parameters": {
"width": 896,
"content": "## Daily Executive Briefing\n\nScheduled analysis of today\u2019s events with deep work and overload detection.\n"
},
"typeVersion": 1
},
{
"id": "a24091b2-73ba-4213-9932-322264ea6509",
"name": "Send Summary over Telegram",
"type": "n8n-nodes-base.telegram",
"position": [
112,
640
],
"parameters": {
"text": "=\ud83d\udcc5 Daily Briefing\n\nMeetings Today: {{$json.meetingCount}}\nTotal Meeting Time: {{$json.totalHours}} hrs\n\n\ud83e\udde0 Deep Work Windows:\n{{$json.freeWindows.join('\\n')}}\n\n{{$json.overloaded ? \"\u26a0 More than 4 meetings today.\" : \"\u2705 Balanced schedule.\"}}\n",
"chatId": "123456789",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "504a254e-d671-4f65-866c-7fb76fe11547",
"name": "Transform Audio to mp3 format",
"type": "n8n-nodes-base.telegram",
"position": [
-176,
-256
],
"parameters": {
"fileId": "={{ $('Receive Bot Messages').item.json.message.voice.file_id }}",
"resource": "file",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "1510b618-1380-4b5d-9f26-9c6dcf8c6045",
"connections": {
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_memory",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Voice Note or Text?": {
"main": [
[
{
"node": "Transform Audio to mp3 format",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent for Google Calendar",
"type": "main",
"index": 0
}
]
]
},
"Receive Bot Messages": {
"main": [
[
{
"node": "Voice Note or Text?",
"type": "main",
"index": 0
}
]
]
},
"Daily Analytics Engine": {
"main": [
[
{
"node": "Send Summary over Telegram",
"type": "main",
"index": 0
}
]
]
},
"Transcribe a recording": {
"main": [
[
{
"node": "AI Agent for Google Calendar",
"type": "main",
"index": 0
}
]
]
},
"Scheduled Everyday 8 AM": {
"main": [
[
{
"node": "Retrive all meeting/event that you have",
"type": "main",
"index": 0
}
]
]
},
"AI Agent for Google Calendar": {
"main": [
[
{
"node": "Send a summary action message",
"type": "main",
"index": 0
}
]
]
},
"Transform Audio to mp3 format": {
"main": [
[
{
"node": "Transcribe a recording",
"type": "main",
"index": 0
}
]
]
},
"Create an event in Google Calendar": {
"ai_tool": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_tool",
"index": 0
}
]
]
},
"Delete an event in Google Calendar": {
"ai_tool": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_tool",
"index": 0
}
]
]
},
"Get many events in Google Calendar": {
"ai_tool": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_tool",
"index": 0
}
]
]
},
"Update an event in Google Calendar": {
"ai_tool": [
[
{
"node": "AI Agent for Google Calendar",
"type": "ai_tool",
"index": 0
}
]
]
},
"Retrive all meeting/event that you have": {
"main": [
[
{
"node": "Daily Analytics Engine",
"type": "main",
"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.
googleCalendarOAuth2ApigooglePalmApiopenAiApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Productivity Automation AI Agents Scheduling Personal Operations
Source: https://n8n.io/workflows/13309/ — 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.
Telegram Trigger receives incoming messages (text, voice, photo, document). Switch routes by message type to appropriate processors: Text → forwarded as-is. Voice → downloaded and sent to Transcribe a
Transform your Telegram messenger into a powerful, multi-modal personal or team assistant. This n8n workflow creates an intelligent agent that can understand text, voice, images, and documents, and ta
Jarvis is a powerful multi-agent productivity assistant built in n8n. It works directly from Telegram and can understand both text messages and voice notes.
Automate your personal productivity with this intelligent n8n workflow that integrates Telegram, Google Sheets, and OpenAI (GPT-4o). This system uses multiple AI agents to manage work hours, tasks, fi
This template is designed for anyone who wants to use Telegram as a personal AI assistant hub. If you often juggle tasks, emails, calendars, and expenses across multiple tools, this workflow consolida