This workflow corresponds to n8n.io template #16334 — 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": "0bc688acd333c182",
"name": "Build an AI meeting prep brief from Google Calendar to email using OpenAI",
"tags": [
{
"name": "google-calendar"
},
{
"name": "meeting-prep"
},
{
"name": "productivity"
},
{
"name": "scheduling"
},
{
"name": "gmail"
},
{
"name": "daily-brief"
},
{
"name": "openai"
},
{
"name": "ai"
}
],
"nodes": [
{
"id": "8db86a1a-7f98-4c87-9366-e44e8c4d7551",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-320
],
"parameters": {
"width": 480,
"height": 688,
"content": "## Build an AI meeting prep brief from Google Calendar to email using OpenAI\n\n## How it works\n\n1. Triggers every morning to initiate the workflow.\n2. Fetches today's events from Google Calendar.\n3. Combines events and checks if there are any meetings.\n4. Uses OpenAI to write a preparation brief if meetings are present.\n5. Formats and sends the brief via email and optionally posts to Slack.\n\n## Setup steps\n\n- [ ] Set up Google Calendar credentials in n8n.\n- [ ] Configure OpenAI API key for LLM chain node.\n- [ ] Integrate Gmail account for sending emails.\n- [ ] Optionally configure Slack credentials for brief posting.\n\n## Customization\n\nThe workflow can be adjusted to use different email or Slack formats."
},
"typeVersion": 1
},
{
"id": "10e47d2d-d940-4328-8c53-668b6133e3ac",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-128
],
"parameters": {
"color": 7,
"width": 432,
"height": 304,
"content": "## Trigger and fetch events\n\nStarts the workflow every morning and fetches events from Google Calendar."
},
"typeVersion": 1
},
{
"id": "3a964c6e-7a6c-4a94-ab61-283e51349dba",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
-128
],
"parameters": {
"color": 7,
"width": 416,
"height": 496,
"content": "## Combine and check meetings\n\nAggregates the calendar events and checks if there are any meetings for today."
},
"typeVersion": 1
},
{
"id": "32e0db42-9ad7-41a5-bc32-1a864d09b7bf",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-192
],
"parameters": {
"color": 7,
"width": 432,
"height": 544,
"content": "## Generate and format brief\n\nUses AI to generate a meeting preparation brief and formats it for email."
},
"typeVersion": 1
},
{
"id": "e0798c0b-2ccb-4e6b-a7ef-44beced6861a",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1344,
-320
],
"parameters": {
"color": 7,
"width": 240,
"height": 528,
"content": "## Email and optional Slack post\n\nEmails the prepared brief and optionally posts it to Slack."
},
"typeVersion": 1
},
{
"id": "04d178c2-2e59-4fad-93dc-4ae3aeab31ff",
"name": "When Day Starts at 7am",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-40,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "days",
"triggerAtHour": 7
}
]
}
},
"typeVersion": 1.2
},
{
"id": "4ab6d18a-4fbf-4de6-b8ed-f5af5f5ee644",
"name": "Fetch Today's Calendar Events",
"type": "n8n-nodes-base.googleCalendar",
"position": [
200,
0
],
"parameters": {
"options": {
"orderBy": "startTime",
"timeMax": "={{ $now.endOf('day').toISO() }}",
"timeMin": "={{ $now.startOf('day').toISO() }}",
"singleEvents": true
},
"calendar": {
"__rl": true,
"mode": "list",
"value": "REPLACE_CALENDAR"
},
"operation": "getAll",
"returnAll": true
},
"typeVersion": 1.3
},
{
"id": "86ae1406-39aa-4ae2-927a-4acfcb834d26",
"name": "Aggregate Calendar Events",
"type": "n8n-nodes-base.aggregate",
"position": [
448,
0
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "321f8c95-621b-484c-8ee7-a08abab10b23",
"name": "If Meetings Exist",
"type": "n8n-nodes-base.if",
"position": [
672,
0
],
"parameters": {
"conditions": {
"options": {
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.data.length }}",
"rightValue": 1
}
]
}
},
"typeVersion": 2
},
{
"id": "8104c630-4edb-41b0-8255-2089f0bc9f1f",
"name": "Skip When No Meetings",
"type": "n8n-nodes-base.noOp",
"position": [
672,
208
],
"parameters": {},
"typeVersion": 1
},
{
"id": "788efc00-8cb1-479b-962c-7333744e1d00",
"name": "Generate Meeting Brief",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
912,
-64
],
"parameters": {
"text": "=You are an executive assistant preparing someone for their day. From today's calendar events below, write a one-line 'day at a glance', then for EACH meeting give: a clear objective, a 3-point agenda, 2-3 smart questions to ask, and what to prepare beforehand. Skip events with no attendees or that look like personal blocks.\n\nToday's events:\n{{ JSON.stringify($json.data).slice(0, 6000) }}",
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.5
},
{
"id": "f6367d0e-9ded-4c3b-a6c9-b5d876aea999",
"name": "Use GPT-4 Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
912,
208
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o",
"cachedResultName": "gpt-4o"
},
"options": {
"temperature": 0.4
}
},
"typeVersion": 1.2
},
{
"id": "9d6551e8-3297-4eef-8a2b-918a6ac778d8",
"name": "Define Output Format",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1136,
208
],
"parameters": {
"schemaType": "fromJson",
"jsonSchemaExample": "{\n \"overview\": \"You have 3 meetings today; the key one is the 2pm client review.\",\n \"meetings\": [\n {\n \"title\": \"Client review\",\n \"time\": \"14:00\",\n \"objective\": \"Agree next-quarter scope.\",\n \"agenda\": [\n \"Recap progress\",\n \"Open risks\",\n \"Next steps\"\n ],\n \"questions\": [\n \"What is your top priority for Q3?\"\n ],\n \"prepare\": [\n \"Pull the latest metrics deck.\"\n ]\n }\n ]\n}"
},
"typeVersion": 1.2
},
{
"id": "0d0bf381-fc12-4362-8304-12f2816e9619",
"name": "Set Brief Fields",
"type": "n8n-nodes-base.set",
"position": [
1152,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "04edba75-b4ac-4c57-a18b-af76da9cb1e3",
"name": "headline",
"type": "string",
"value": "=Meeting prep \u2014 {{ $now.format('yyyy-LL-dd') }}"
},
{
"id": "69c50a54-8125-4a01-92db-b40d904977f7",
"name": "overview",
"type": "string",
"value": "={{ $json.output.overview }}"
},
{
"id": "30a72a0c-0370-4083-973d-2e5f55efa2aa",
"name": "body",
"type": "string",
"value": "={{ ($json.output.meetings || []).map(m => '\u2014 ' + m.title + ' (' + m.time + ')\\nObjective: ' + m.objective + '\\nAsk: ' + (m.questions || []).join('; ') + '\\nPrep: ' + (m.prepare || []).join('; ')).join('\\n\\n') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b5e3bc53-b6d6-4191-890e-4938cd7682eb",
"name": "Send Brief via Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
1392,
-112
],
"parameters": {
"sendTo": "you@example.com",
"message": "={{ $json.overview }}\n\n{{ $json.body }}",
"options": {},
"subject": "={{ $json.headline }}"
},
"typeVersion": 2.1
},
{
"id": "d5c470ac-23ea-42a2-b1a8-793a699a34e2",
"name": "Post Brief on Slack",
"type": "n8n-nodes-base.slack",
"position": [
1392,
64
],
"parameters": {
"text": "=:calendar: {{ $json.headline }}\n{{ $json.overview }}\n\n{{ $json.body }}",
"select": "channel",
"resource": "message",
"channelId": {
"__rl": true,
"mode": "name",
"value": "#daily"
},
"operation": "post",
"otherOptions": {}
},
"typeVersion": 2.2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"Use GPT-4 Model": {
"ai_languageModel": [
[
{
"node": "Generate Meeting Brief",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Set Brief Fields": {
"main": [
[
{
"node": "Send Brief via Gmail",
"type": "main",
"index": 0
}
]
]
},
"If Meetings Exist": {
"main": [
[
{
"node": "Generate Meeting Brief",
"type": "main",
"index": 0
}
],
[
{
"node": "Skip When No Meetings",
"type": "main",
"index": 0
}
]
]
},
"Define Output Format": {
"ai_outputParser": [
[
{
"node": "Generate Meeting Brief",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Generate Meeting Brief": {
"main": [
[
{
"node": "Set Brief Fields",
"type": "main",
"index": 0
}
]
]
},
"When Day Starts at 7am": {
"main": [
[
{
"node": "Fetch Today's Calendar Events",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Calendar Events": {
"main": [
[
{
"node": "If Meetings Exist",
"type": "main",
"index": 0
}
]
]
},
"Fetch Today's Calendar Events": {
"main": [
[
{
"node": "Aggregate Calendar Events",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow accepts a URL via an n8n form, fetches and extracts the main text from the web page, uses OpenAI (GPT-4o) to generate a structured research card (summary, tags, quotes, actions, sentiment, reading time), then saves the result to Notion and logs it in Google Sheets.…
Source: https://n8n.io/workflows/16334/ — 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.
This n8n-powered workflow automates the entire lifecycle of real estate lead intake, qualification, routing, assignment, and reporting across multiple channels. It brings WhatsApp inquiries and websit
My workflow 14. Uses rssFeedRead, chainLlm, lmChatOpenAi, openWeatherMap. Scheduled trigger; 40 nodes.
This workflow builds an AI meeting assistant who sends information-dense pre-meeting notifications for a user's upcoming meetings. A scheduled trigger fires hourly and checks for upcoming meetings wit
Ensure suppliers never miss a follow-up by automating overdue purchase order tracking and scheduling. 📦⏰ This workflow checks Airtable every weekday morning for open POs older than seven days without
This workflow runs daily, pulls the latest post from an RSS feed, and uses OpenAI to repurpose it into an SEO blog rewrite, a LinkedIn post, and an X/Twitter thread, then logs the drafts to Google She