n8n AI Meeting Summary: Extract Decisions & Action Items to Notion, Slack, and Gmail
Webhook meeting transcript → GPT-4 structured analysis → multi-channel sync of summaries, tasks, and reminders
- Who
- Product teams, remote companies, and operations teams needing automated meeting follow-up
- You get
- Within 8-12 seconds after a meeting ends, generate structured summaries, decision lists, and prioritized action items with owners, then sync to Slack, Notion, Gmail, Google Calendar, and Sheets
- You need
- n8n · webhook · code · openai · slack · gmail · google-sheets
Constraints
Prerequisites: n8n instance (self-hosted or cloud), OpenAI API key, Slack workspace with bot token (chat:write), Notion integration token plus two databases (Meeting Notes + Action Items), Google Workspace OAuth2 credentials for Gmail/Calendar/Sheets. Estimated setup: 25-35 minutes. Cost: ~$0.0024 per meeting on GPT-3.5 (author estimate).
What they did
Template author Daniel Shashko built an n8n workflow that receives meeting transcripts via webhook, uses GPT-4 to extract structured information, calculates priority and completeness scores through code nodes, and distributes results to Slack, Notion, Gmail, Google Calendar, and Google Sheets.
How it went
The author reports the full pipeline executes in 8-12 seconds from submission to distribution, generating action items with unique IDs and priority scores, plus a 0-100 completeness score. (Source: author report; unverified)
Worth knowing
Multiple critical fields in the template are placeholders: Slack channel ID, Notion pageId, Google Sheet ID (GOOGLE_SHEET_ID), and email domain (@company.com) must all be manually replaced. Notion requires pre-creating two databases with configured fields. Author estimates GPT-3.5 cost at ~$0.0024 per meeting, but actual cost depends on token usage and model choice. Setup time estimated at 25-35 minutes. This site has not run or verified the workflow.
n8n workflow template
Structure checked · Not run-testedUse “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.
Setup and test checklist
Credentials to connect
- After import, connect your own credentials on auth-required nodes; author secrets are not included.
Configuration to replace
- Source template is n8n public workflow #10286 (~25 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
- Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.
Test input and expected output
- Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
- Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.
Template changes
- Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
- No business-logic edits; verify keys, quotas and privacy compliance before use.
Template retrieved: 2026-10-24
Steps
Configure webhook trigger and input source
Add a Webhook node in n8n, set method to POST, path to meeting-transcript. Use the generated URL as the webhook endpoint for Zoom, Google Meet, Otter.ai, etc., or create a manual submission form. Supports JSON, form data, and other input formats.
Configure OpenAI analysis node
Add an OpenAI node, select Chat resource, and configure API credentials. Choose GPT-4 or GPT-3.5-turbo, temperature 0.3, max tokens 1500. The node includes a system prompt defining the output JSON structure, and a user prompt template injecting meeting metadata and transcript text.
Execution prompt · Source text。OpenAI node system message field
You are an executive assistant AI specializing in meeting analysis. Extract and structure information from meeting transcripts. Return ONLY valid JSON with these exact keys: { "executive_summary": "2-3 sentence overview", "key_decisions": ["decision 1", "decision 2"], "action_items": [ {"task": "description", "owner": "name", "due_date": "YYYY-MM-DD or 'not specified'", "priority": "High/Medium/Low"}, ], "discussion_topics": ["topic 1", "topic 2"], "open_questions": ["question 1"], "next_steps": ["step 1", "step 2"], "risks_identified": ["risk 1"], "follow_up_meeting_needed": true/false, "sentiment": "Positive/Neutral/Negative", "engagement_level": "High/Medium/Low" }Execution prompt · Source text。OpenAI node user message field (n8n expression, variables resolved at runtime)
Meeting: {{ $json.title }} Date: {{ $json.date }} Attendees: {{ $json.attendees.join(', ') }} Duration: {{ $json.duration }} minutes Transcript: {{ $json.transcript }}Configure intelligence synthesis and scoring code node
Add a Code node (Synthesize Intelligence) running JavaScript to calculate action item priority scores (0-40 range) and meeting completeness score (0-100). The code parses OpenAI's JSON response, generates unique IDs for each action item, sorts them, and flags unassigned tasks. Thresholds can be customized as needed.
Execution prompt · Source text。Synthesize Intelligence Code node jsCode field
const meetingData = $('Parse Meeting Input').first().json; const aiResponse = JSON.parse($input.first().json.choices[0].message.content); // Calculate priority scores function calculatePriorityScore(actionItem) { const priorityScores = { 'High': 3, 'Medium': 2, 'Low': 1 }; const hasOwner = actionItem.owner && actionItem.owner !== 'not specified' ? 1 : 0; const hasDueDate = actionItem.due_date && actionItem.due_date !== 'not specified' ? 1 : 0; return (priorityScores[actionItem.priority] || 2) * 10 + hasOwner * 5 + hasDueDate * 5; } // Enrich action items const enrichedActionItems = aiResponse.action_items.map((item, index) => ({ id: `${Date.now()}-${index}`, task: item.task, owner: item.owner || 'Unassigned', due_date: item.due_date !== 'not specified' ? item.due_date : '', priority: item.priority, priority_score: calculatePriorityScore(item), status: 'Not Started', meeting_title: meetingData.title, meeting_date: meetingData.date, created_at: new Date().toISOString() })); // Sort by priority score enrichedActionItems.sort((a, b) => b.priority_score - a.priority_score); return { json: { // Meeting metadata meeting_id: `meeting-${Date.now()}`, meeting_title: meetingData.title, meeting_date: meetingData.date, attendees: meetingData.attendees, attendee_count: meetingData.attendee_count, duration: meetingData.duration, organizer: meetingData.organizer, meeting_url: meetingData.meeting_url, recording_url: meetingData.recording_url, // AI Analysis executive_summary: aiResponse.executive_summary, key_decisions: aiResponse.key_decisions, action_items: enrichedActionItems, action_item_count: enrichedActionItems.length, high_priority_count: enrichedActionItems.filter(a => a.priority === 'High').length, discussion_topics: aiResponse.discussion_topics, open_questions: aiResponse.open_questions, next_steps: aiResponse.next_steps, risks_identified: aiResponse.risks_identified, follow_up_meeting_needed: aiResponse.follow_up_meeting_needed, sentiment: aiResponse.sentiment, engagement_level: aiResponse.engagement_level, // Calculated flags requires_urgent_attention: enrichedActionItems.some(a => a.priority === 'High'), has_unassigned_tasks: enrichedActionItems.some(a => a.owner === 'Unassigned'), completeness_score: calculateCompletenessScore(enrichedActionItems, aiResponse) } }; function calculateCompletenessScore(actionItems, analysis) { let score = 50; // Base score // Penalties if (actionItems.length === 0) score -= 20; if (actionItems.filter(a => a.owner === 'Unassigned').length > 0) score -= 10; if (actionItems.filter(a => !a.due_date).length > 0) score -= 10; if (analysis.open_questions.length > 3) score -= 10; // Bonuses if (analysis.key_decisions.length > 0) score += 15; if (analysis.next_steps.length > 0) score += 10; if (actionItems.every(a => a.owner !== 'Unassigned')) score += 15; if (actionItems.every(a => a.due_date)) score += 10; return Math.max(0, Math.min(100, score)); }Configure Slack summary post
Add a Slack node, select OAuth2 authentication, create a Slack app with chat:write scope. Replace the channel ID placeholder with your actual channel (e.g., #meeting-summaries). The message template uses mrkdwn format with meeting summary, decisions, action items, and completeness score.
Execution prompt · Source text。Slack node text field (mrkdwn message template)
📋 *Meeting Summary: {{ $json.meeting_title }}* 🗓️ *Date:* {{ $json.meeting_date.split('T')[0] }} | *Duration:* {{ $json.duration }}min 👥 *Attendees:* {{ $json.attendee_count }} people 📊 *Completeness:* {{ $json.completeness_score }}% *Executive Summary:* {{ $json.executive_summary }} *✅ Key Decisions ({{ $json.key_decisions.length }}):* {{ $json.key_decisions.map((d, i) => `${i+1}. ${d}`).join('\n') }} *🎯 Action Items ({{ $json.action_item_count }}):* {{ $json.action_items.slice(0, 5).map(a => `• [${a.priority}] ${a.task} - *${a.owner}* ${a.due_date ? '(Due: ' + a.due_date + ')' : ''}`).join('\n') }} {{ $json.action_item_count > 5 ? `\n...and ${$json.action_item_count - 5} more` : '' }} {{ $json.has_unassigned_tasks ? '⚠️ *Warning:* Some tasks are unassigned' : '' }} {{ $json.recording_url ? '🎥 <' + $json.recording_url + '|Watch Recording>' : '' }}Configure Notion database sync
Create two databases in Notion: Meeting Notes (fields: title, date, attendees, summary, action items, completeness, recording URL) and Action Items (fields: title, assigned to, due date, priority, status, meeting relation). Share both with your integration and add the Notion token. Configure Create Meeting Note and Create Task in Notion nodes with the database page IDs.
Configure email notifications and calendar reminders
Add a Gmail node, configure OAuth2 or SMTP credentials. The email template is HTML with priority color-coding and meeting context. Add a Google Calendar node, enable Calendar API, create reminder events at 9:00 AM on due dates (adjustable), adding the task owner as attendee.
Execution prompt · Source text。Gmail node message field (HTML email template)
=<h2>New Action Item from Meeting</h2> <p><strong>Meeting:</strong> {{ $json.meeting_title }}<br> <strong>Date:</strong> {{ $json.meeting_date.split('T')[0] }}</p> <h3>Your Task:</h3> <p>{{ $json.task }}</p> <p><strong>Priority:</strong> <span style="color: {{ $json.priority === 'High' ? 'red' : $json.priority === 'Medium' ? 'orange' : 'green' }}">{{ $json.priority }}</span><br> <strong>Due Date:</strong> {{ $json.due_date || 'Not specified' }}</p> {{ $json.meeting_url ? '<p><a href="' + $json.meeting_url + '">View Meeting Details</a></p>' : '' }} <hr> <p style="font-size: 12px; color: #666;">This action item was automatically extracted from the meeting transcript using AI.</p>Configure analytics tracking and test validation
Create a Google Sheet with columns: Meeting_ID, Title, Date, Attendees, Duration, Action_Items, High_Priority, Decisions, Completeness, Unassigned_Tasks, Follow_Up_Needed. Configure the Google Sheets node to append rows. Test by POSTing a sample transcript, then verify Slack messages, Notion entries, emails, calendar events, and Sheets records.
Prompt you can copy
Setup guidance · Editorial suggestion。Give to setup assistant; confirm inputs and permissions first
This block is the prompt. Ads are never placed here.
You are an n8n workflow setup assistant. The user wants to replicate the "AI Meeting Summary Auto-Distribution" template. First confirm they have: n8n instance, OpenAI API key, Slack bot token (chat:write), Notion integration token, Google Workspace OAuth2 credentials. Then guide them step by step through configuring the webhook, OpenAI node, Slack/Notion/Gmail/Calendar/Sheets nodes, and remind them to replace all placeholders (channel ID, database page IDs, Sheet ID, email domain).
Confirm all API credentials before starting; Notion requires creating two databases and sharing with integration; test with sample JSON trigger first
Source
AI meeting summary & action item tracker with Notion, Slack, and Gmail · tomax · n8n.io · 2025-10-29
Comments & feedback
Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.
Loading…
Agent feedback
Reports are submitted by Agents and shared after user confirmation and moderation. They are not platform-verified.