This workflow corresponds to n8n.io template #4783 — we link there as the canonical source.
This workflow follows the Agent → Emailsend 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": "81UkThrSnnFw6IJo",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Google Calendar Coming Week",
"tags": [],
"nodes": [
{
"id": "b4c54286-a4c5-4a1b-87ca-a37fa1fcb2aa",
"name": "weekly_schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-180,
-40
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtHour": 12
}
]
}
},
"typeVersion": 1.2
},
{
"id": "57a88176-a291-4d65-bfd2-868d4e50befb",
"name": "get_next_weeks_events",
"type": "n8n-nodes-base.googleCalendar",
"position": [
1300,
-40
],
"parameters": {
"options": {},
"timeMax": "={{ $json['users-current-day-1-minute-before-midnight-plus-7-days-iso'] }}",
"timeMin": "={{ $json['users-current-day-1-minute-before-midnight-iso'] }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "n8n-personal-assistant-demo"
},
"operation": "getAll",
"returnAll": true
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "ed2eacbb-453f-4e5b-be3a-0c45e3506e1b",
"name": "Google Gemini",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2840,
580
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-preview-05-20"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "20670d58-0c0a-4f17-9a89-131bb2cd2caa",
"name": "event_summary_agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2740,
-40
],
"parameters": {
"text": "={{ $json.eventdata }}",
"options": {
"systemMessage": "=You have been given a JSON array of Google Calendar events for the upcoming week (Monday to Sunday). Today is Sunday, {{ $('locale').item.json['users-current-date'] ? $('locale').item.json['users-current-date'] : $now.setZone($('locale').item.json['users-timezone'] ?? 'Australia/Sydney').setLocale($('locale').item.json['users-locale'] ?? 'en-AU').toLocaleString({ weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }) }}.\nEach event object in the array has 'summary', 'start.dateTime', 'end.dateTime', and 'description'. Your designated timezone is '{{ $('locale').item.json['users-timezone'] }}' and locale '{{ $('locale').item.json['users-locale'] }}'.\n\nThe users name is: {{ $('locale').item.json['users-name'] }}\nThe user is located in: {{ $('locale').item.json['users-home-city'] }}\n\nYour task is to create a well-formatted weekly schedule summary for an email.\n\n1. **Greeting**: Start with a friendly greeting, for example: \"Here's your schedule for the upcoming week:\"\n\n2. **Daily Schedule**:\n * Group events by day (e.g., Monday, June 9, 2025; Tuesday, June 10, 2025). Determine the correct dates for the upcoming week (Monday to Sunday) based on today's date.\n * For each day of the upcoming week, list its events chronologically.\n * Format each event as: `HH:MM AM/PM - HH:MM AM/PM: Event Summary`. For example: `09:30 AM - 10:30 AM: Team Meeting`.\n * Parse the `start.dateTime` and `end.dateTime` (which are ISO strings with timezone offsets like `+10:00`) and display them correctly for the '{{ $('locale').item.json['users-timezone'] }}' timezone.\n * If a day has no events, state \"No events scheduled for this day.\"\n\n3. **Priority Events**:\n * Review the 'summary' and 'description' fields for keywords such as \"important\", \"urgent\", \"deadline\", \"meeting\", \"critical\", \"prepare\", or similar terms that indicate significance.\n * Mark these priority events by prefixing the event line with \"IMPORTANT: \". For example: `IMPORTANT: 02:00 PM - 03:00 PM: Project Deadline Review`.\n * If the 'description' provides actionable context for a priority event (e.g., \"Preparation needed: review X document\"), you can briefly mention this context after the event summary.\n\n4. **Weekly Insight**:\n * Conclude with 1-2 sentences offering a helpful insight, observation, or piece of advice related to the week's schedule. Examples:\n * \"Thursday looks like your busiest day, so you might want to plan accordingly.\"\n * \"Remember to allocate some time to prepare for the client presentation on Wednesday.\"\n * \"This week seems to have a good balance of meetings and free time.\"\n\n5. **Input Data Structure Reminder**: The calendar events are provided as a JSON array. You need to process this entire array.\n\nPlease generate only the text content suitable for the body of an email. Do not include any preamble (like \"Okay, here is the summary...\") or sign-off beyond the requested content."
},
"promptType": "define"
},
"typeVersion": 2
},
{
"id": "99885550-0c81-4513-86f0-8e82b0d5e0fb",
"name": "send_email",
"type": "n8n-nodes-base.emailSend",
"position": [
3800,
-40
],
"parameters": {
"html": "={{ $json['email-html'] }}",
"options": {
"appendAttribution": false
},
"subject": "=Next Week Calendar Summary : {{ $now.plus({ days: 1 }).day }}-{{ $now.plus({ days: 7 }).toLocaleString(DateTime.DATE_MED) }}"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "9199043b-2255-4a29-9c76-e6edbda41cc5",
"name": "locale",
"type": "n8n-nodes-base.set",
"position": [
300,
-40
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "2fa6da62-0c1b-4abe-b1d1-45dab7c22ab0",
"name": "users-locale",
"type": "string",
"value": "en-AU"
},
{
"id": "e997127b-a7b1-4684-82b3-3e5d66be07fa",
"name": "users-timezone",
"type": "string",
"value": "Australia/Sydney"
},
{
"id": "082e8d8f-5b20-4fc0-a59e-6deb48cb1406",
"name": "users-name",
"type": "string",
"value": "Bob"
},
{
"id": "4a867353-6d0c-4bad-90f9-e739ff1da010",
"name": "users-home-city",
"type": "string",
"value": "Sydney"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b92e0c62-d83f-417d-9ed1-839b3f680edd",
"name": "simplify_evens_json",
"type": "n8n-nodes-base.code",
"position": [
1800,
-40
],
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n delete item.json.htmlLink\n delete item.json.etag\n delete item.json.iCalUID\n delete item.json.start.timeZone\n delete item.json.end.timeZone\n delete item.json.kind\n delete item.json.reminders\n delete item.json.organizer\n delete item.json.creator\n delete item.json.created\n delete item.json.updated\n delete item.json.status\n delete item.json.eventType\n delete item.json.id\n}\n\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "c3639753-7b59-40ea-b59b-32dc00769146",
"name": "aggregate_events",
"type": "n8n-nodes-base.aggregate",
"position": [
2320,
-40
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "eventdata"
},
"typeVersion": 1
},
{
"id": "bb2804c2-130e-4d53-9eac-cb4f978056d1",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-1100
],
"parameters": {
"color": 3,
"width": 960,
"height": 520,
"content": "### Workflow Overview: Google Calendar Coming Week \ud83d\uddd3\ufe0f\u27a1\ufe0f\ud83d\udce7\n\nThis n8n workflow automates the process of generating and emailing a summary of your upcoming week's Google Calendar events.\n\n**How it works:**\n1. **Triggers weekly:** Starts automatically based on a schedule.\n2. **Sets user context:** Configures your locale, timezone, name, and city.\n3. **Calculates date ranges:** Determines the start and end dates for the upcoming week.\n4. **Fetches calendar events:** Retrieves events from your specified Google Calendar for that week.\n5. **Simplifies data:** Removes unnecessary information from the event data.\n6. **Aggregates events:** Combines all events into a single list for AI processing.\n7. **Generates summary:** Uses Google Gemini AI to create a human-readable summary, highlighting important events.\n8. **Formats for email:** Converts the AI's summary from Markdown to HTML.\n9. **Sends email:** Emails the formatted summary to you.\n\n**Key User Actions:**\n* Configure the **`locale`** node with your specific details (timezone, locale, name, city).\n* Set up credentials for **Google Calendar**, **Google Gemini**, and your **SMTP (Email)** service.\n* Specify your target Google Calendar ID in the **`get_next_weeks_events`** node.\n* Update the \"To\" and \"From\" email addresses in the **`send_email`** node."
},
"typeVersion": 1
},
{
"id": "4e8a4adb-fde7-403d-968e-7d15c2fbe770",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
140,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\u2699\ufe0f **locale (Set)**\n\n* **Purpose:** Defines essential user-specific settings for personalization and correct date/time processing.\n* **\u203c\ufe0f USER ACTION REQUIRED \u203c\ufe0f:**\n * `users-locale`: (e.g., `en-AU`, `en-US`, `de-DE`) - Affects date/time/number formatting.\n * `users-timezone`: (e.g., `Australia/Sydney`, `America/New_York`) - Crucial for accurate event times.\n * `users-name`: (e.g., `Bob`) - Used in the email greeting.\n * `users-home-city`: (e.g., `Sydney`) - Provides context for the AI.\n* **Note:** These values are used by downstream nodes."
},
"typeVersion": 1
},
{
"id": "a409ad6d-56be-4b3c-a1e3-b2b3e2c00b63",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\ud83d\uddd3\ufe0f **weekly_schedule (Trigger)**\n\n* **Purpose:** Initiates the workflow automatically.\n* **Details:** By default, runs once a week at 12:00 PM.\n* **To Modify:** Adjust the \"Rule\" settings (interval, time, day) if you need a different schedule."
},
"typeVersion": 1
},
{
"id": "714b924c-4cbc-4864-b833-e80b3dcecde8",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\u23f0 **date_time (Set)**\n\n* **Purpose:** Generates various date and time strings based on the current execution time and the settings from the `locale` node.\n* **Details:** Creates values like \"users-current-date\", \"users-current-day-1-minute-before-midnight-iso\", etc., which are used to define the 7-day window for fetching calendar events.\n* **To Modify:** Usually no changes needed here; it's dynamic."
},
"typeVersion": 1
},
{
"id": "a31c71e7-98c8-4185-891e-9543ceac217d",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1140,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\ud83d\udcc5 **get_next_weeks_events (Google Calendar)**\n\n* **Purpose:** Fetches events from a specified Google Calendar.\n* **Details:** Uses `timeMin` and `timeMax` from the `date-time` node to get events for the upcoming 7 days.\n* **\u203c\ufe0f USER ACTION REQUIRED \u203c\ufe0f:**\n 1. **Credentials:** Connect your Google Calendar account.\n 2. **Calendar ID:** Change the `calendar` parameter (currently `c_4d9...group.calendar.google.com`) to *your* desired Google Calendar ID."
},
"typeVersion": 1
},
{
"id": "5e5830c6-9e43-43c7-852e-b9982f6deb6b",
"name": "date_time",
"type": "n8n-nodes-base.set",
"position": [
820,
-40
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "954044f7-3c08-48c2-af9c-59a72690ad76",
"name": "users-current-date",
"type": "string",
"value": "={{\n $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toLocaleString(DateTime.DATE_FULL)\n}}"
},
{
"id": "2c3a0a1a-cc05-4b5d-b175-20732706aefb",
"name": "users-current-time",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toLocaleString(DateTime.TIME_SIMPLE) }}"
},
{
"id": "764b3b1a-6a6e-4b92-8f41-ae49405bc72a",
"name": "users-date-time",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone']) }}"
},
{
"id": "4c2851ef-175e-4f81-95af-5671171fdf16",
"name": "users-date-time-full",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toLocaleString(DateTime.DATETIME_FULL) }}"
},
{
"id": "4ae2c38b-f93a-4b56-9078-d9675a12ec8b",
"name": "users-date-time-huge",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toFormat('cccc, MMMM d, yyyy, h:mm a') }}"
},
{
"id": "1011c2bf-d311-424d-8537-1788597065d4",
"name": "users-current-date-plus-1",
"type": "string",
"value": "={{ $now.plus({ days: 1 }).setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toLocaleString(DateTime.DATE_FULL) }}"
},
{
"id": "343ec7d5-fcb5-454d-b947-4b0f2e94f930",
"name": "users-current-date-plus-7",
"type": "string",
"value": "={{ $now.plus({ days: 7 }).setZone($('locale').item.json['users-timezone'] ?? 'UTC').setLocale($('locale').item.json['users-locale'] ?? 'en-US').toLocaleString(DateTime.DATE_FULL) }}"
},
{
"id": "ce0de19d-9cb1-4918-ade5-47f22f35f8e8",
"name": "users-current-day-1-minute-before-midnight",
"type": "string",
"value": "={{\n $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC')\n .endOf('day')\n .setLocale($('locale').item.json['users-locale'] ?? 'en-US')\n .toLocaleString(DateTime.DATETIME_FULL)\n}}"
},
{
"id": "800dff91-469d-4a2b-acb0-a0b79d0b9341",
"name": "users-current-day-1-minute-before-midnight-plus-7-days",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC') .plus({ days: 7 }) .endOf('day') .setLocale($('locale').item.json['users-locale'] ?? 'en-US') .toLocaleString(DateTime.DATETIME_FULL) }}"
},
{
"id": "d04c43fe-1f6d-4e7e-b82f-70cebb7484a6",
"name": "users-current-day-1-minute-before-midnight-iso",
"type": "string",
"value": "={{\n $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC')\n .endOf('day')\n .toISO()\n}}"
},
{
"id": "5aee9416-0ad6-43b9-936f-edce6a292cce",
"name": "users-current-day-1-minute-before-midnight-plus-7-days-iso",
"type": "string",
"value": "={{ $now.setZone($('locale').item.json['users-timezone'] ?? 'UTC') .plus({ days: 7 }) .endOf('day') .toISO() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f20a83fd-2484-4dc7-92a1-a438c2cf8e02",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1640,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\u2728 **simplify_evens_json (Code)**\n\n* **Purpose:** Cleans the raw event data from Google Calendar.\n* **Details:** Runs JavaScript to remove fields like `htmlLink`, `etag`, `iCalUID`, etc., to provide a cleaner dataset to the AI.\n* **To Modify:** Only if you need to keep or remove specific event fields not covered."
},
"typeVersion": 1
},
{
"id": "c5e40e35-8dfa-491c-ba67-21b83f71334b",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
2140,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\u2795 **aggregate_events (Aggregate)**\n\n* **Purpose:** Combines all individual simplified event items into a single JSON array.\n* **Details:** Creates a field named `eventdata` which contains the list of all events. This is necessary for the AI agent to process all events at once.\n* **To Modify:** Usually no changes needed."
},
"typeVersion": 1
},
{
"id": "db11c407-a238-48ef-9398-1842c1046340",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
2640,
220
],
"parameters": {
"color": 6,
"width": 440,
"height": 400,
"content": "\ud83e\udde0 **Google Gemini (Language Model)**\n\n* **Purpose:** Establishes the connection to the Google Gemini AI model.\n* **Details:** This node itself doesn't do the processing but provides the AI capability to the `event_summary_agent`.\n* **\u203c\ufe0f USER ACTION REQUIRED \u203c\ufe0f:**\n * **Credentials:** Set up and select your Google Gemini (PaLM) API credentials.\n * **Model Name:** Default is `models/gemini-2.5-flash-preview-05-20`. Change if needed."
},
"typeVersion": 1
},
{
"id": "692413bc-58f9-4d09-a7f7-796d50894e3b",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
3140,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\ud83d\udcc4\u27a1\ufe0f\ud83c\udf10 **markdown_to_html (Converter)**\n\n* **Purpose:** Converts the Markdown text generated by the `event_summary_agent` into HTML.\n* **Details:** Ensures the email body is well-formatted (line breaks, bolding, lists, emojis).\n* **To Modify:** Usually no changes needed. Options like `emoji` and `simpleLineBreaks` are enabled."
},
"typeVersion": 1
},
{
"id": "d2803020-1f12-4207-a9c3-678fbb472daf",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
3640,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\ud83d\udce7 **send_email (Email)**\n\n* **Purpose:** Sends the final HTML summary as an email.\n* **Details:** Uses the HTML output from the `Markdown` node as the email body. The subject is dynamically generated.\n* **\u203c\ufe0f USER ACTION REQUIRED \u203c\ufe0f:**\n 1. **Credentials:** Configure and select your SMTP (email sending) account.\n 2. `fromEmail`: Set your desired sender email address.\n 3. `toEmail`: Set the recipient email address(es).\n * **To Modify (Optional):** Customize the `subject` line format."
},
"typeVersion": 1
},
{
"id": "73c88ce5-9fa6-418f-b4cc-0b646f5708e7",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
2640,
-400
],
"parameters": {
"color": 4,
"width": 440,
"height": 400,
"content": "\ud83e\udd16 **event_summary_agent (AI Agent)**\n\n* **Purpose:** Generates a well-formatted weekly schedule summary using the AI model.\n* **Details:** Takes the `eventdata` (from `aggregate_events`) and a detailed prompt (under \"System Message\") that instructs the AI on output structure, date formatting, priority event identification, and weekly insights.\n* **To Modify:** The \"System Message\" can be tweaked to change:\n * Greeting style.\n * Date/time formats (though largely controlled by `locale`).\n * Keywords for \"IMPORTANT\" events (`urgent`, `deadline`, etc.).\n * The style or focus of the \"Weekly Insight.\""
},
"typeVersion": 1
},
{
"id": "6febb866-888c-4e72-a6b8-296a826b7e66",
"name": "markdown_to_html",
"type": "n8n-nodes-base.markdown",
"position": [
3320,
-40
],
"parameters": {
"mode": "markdownToHtml",
"options": {
"emoji": true,
"simpleLineBreaks": true
},
"markdown": "={{ $json.output }}",
"destinationKey": "email-html"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "db6385a3-bd01-4cc0-be20-cb1388b31cdc",
"connections": {
"locale": {
"main": [
[
{
"node": "date_time",
"type": "main",
"index": 0
}
]
]
},
"date_time": {
"main": [
[
{
"node": "get_next_weeks_events",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini": {
"ai_languageModel": [
[
{
"node": "event_summary_agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"weekly_schedule": {
"main": [
[
{
"node": "locale",
"type": "main",
"index": 0
}
]
]
},
"aggregate_events": {
"main": [
[
{
"node": "event_summary_agent",
"type": "main",
"index": 0
}
]
]
},
"markdown_to_html": {
"main": [
[
{
"node": "send_email",
"type": "main",
"index": 0
}
]
]
},
"event_summary_agent": {
"main": [
[
{
"node": "markdown_to_html",
"type": "main",
"index": 0
}
]
]
},
"simplify_evens_json": {
"main": [
[
{
"node": "aggregate_events",
"type": "main",
"index": 0
}
]
]
},
"get_next_weeks_events": {
"main": [
[
{
"node": "simplify_evens_json",
"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.
googleCalendarOAuth2ApigooglePalmApismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Get a personalized, AI-powered summary of your upcoming week's Google Calendar events delivered straight to your inbox! This workflow automates the entire process, from fetching events to generating an intelligent summary and emailing it to you.
Source: https://n8n.io/workflows/4783/ — 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.
An end-to-end Cyber Threat Intelligence pipeline that turns raw DNS traffic into actionable security verdicts — without manual triage, without leaking credentials, and without alert fatigue.
N8N. Uses lmChatGoogleGemini, toolCode, httpRequest, emailSend. Scheduled trigger; 27 nodes.
The CA - Tele Assistant workflow is an intelligent Telegram bot designed to help you manage your Google Calendar effortlessly through natural language and voice commands. Hands-free calendar managemen
The system uses a three-stage pipeline architecture: automated paper retrieval from ArXiv's API AI-powered relevance filtering and analysis via Google Gemini Intelligent summarization with HTML format
Early Warning Tracker. Uses agent, lmChatGoogleGemini, emailSend, slack. Scheduled trigger; 20 nodes.