AutomationFlowsAI & RAG › Transform Meeting Notes Into Asana Tasks & Slack Summaries with Gpt-4o

Transform Meeting Notes Into Asana Tasks & Slack Summaries with Gpt-4o

ByKareem @kareem on n8n.io

This workflow uses AI to extract action items, decisions, and key details from any meeting notes format—then creates tasks in Asana and sends a formatted summary to Slack.

Event trigger★★★★☆ complexityAI-powered12 nodesForm TriggerOpenAIAsanaSlack
AI & RAG Trigger: Event Nodes: 12 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #9875 — we link there as the canonical source.

This workflow follows the Form Trigger → OpenAI 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 →

Download .json
{
  "id": "Zu92vKdhQwEYAsmb",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Meeting Notes to Asana Tasks & Slack Summary",
  "tags": [],
  "nodes": [
    {
      "id": "af232b23-64df-4939-85e8-16d9c1fdbc93",
      "name": "Meeting Notes Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        976,
        496
      ],
      "parameters": {
        "options": {
          "appendAttribution": false
        },
        "formTitle": "Meeting Notes \u2192 Tasks & Summary",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Company Name / Project Name",
              "placeholder": "Who the meeting was with / What it was about",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Paste in your meeting notes here",
              "placeholder": "AI Notetaker Summary, manual notes, shared document",
              "requiredField": true
            },
            {
              "fieldLabel": "Asana Project ID",
              "placeholder": "Your Asana Project ID",
              "requiredField": true
            },
            {
              "fieldLabel": "Slack Channel Name",
              "placeholder": "#team-updates"
            }
          ]
        },
        "formDescription": "Transform meeting notes into organized tasks and team summaries.\n\n\u2713 Extract key decisions and action items\n\u2713 Create Asana tasks with due dates\n\u2713 Send Slack summary to team\n\nWorks with AI notetaker transcripts, manual notes, or shared documents."
      },
      "typeVersion": 2.2
    },
    {
      "id": "807d3b67-42cf-459c-9682-d1dbb2789b7a",
      "name": "AI Extract Data",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1136,
        496
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a helpful, intelligent personal assistant. You extract structured data from meeting notes."
            },
            {
              "content": "=Extract the following from these meeting notes:\n\nMeeting notes:\n{{ $json[\"Paste in your meeting notes here\"] }}\n\nReturn a JSON object with these exact keys:\n{\n  \"key_decisions\": [\"decision 1\", \"decision 2\"],\n  \"action_items\": [\n    {\n      \"task\": \"task description\",\n      \"assignee\": \"person name or 'Unassigned'\",\n      \"due_date\": \"YYYY-MM-DD or null\"\n    }\n  ],\n  \"next_meeting_date\": \"YYYY-MM-DD or null\",\n  \"pain_points\": [\"pain point 1\", \"pain point 2\"],\n  \"budget_mentioned\": \"dollar amount or null\"\n}\n\nRules:\n- If no action items found, return empty array\n- If no assignee mentioned, use \"Unassigned\"\n- If no due date mentioned, use null\n- Extract dates in YYYY-MM-DD format"
            }
          ]
        },
        "jsonOutput": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "280d61e5-be6c-4e4e-adc2-fe39ffd8b197",
      "name": "Structure Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        496
      ],
      "parameters": {
        "jsCode": "// Get the AI response\nconst aiContent = $input.item.json.message.content;\n\n// Get form data\nconst formTrigger = $('Meeting Notes Form').item.json;\n\nconst formData = {\n  company_name: formTrigger[\"Company Name / Project Name\"],\n  meeting_notes: formTrigger[\"Paste in your meeting notes here\"],\n  asana_project_id: formTrigger[\"Asana Project ID\"],\n  slack_channel: formTrigger[\"Slack Channel Name\"] || \"#general\"\n};\n\n// Parse extracted data\nconst extracted = {\n  key_decisions: aiContent.key_decisions || [],\n  action_items: aiContent.action_items || [],\n  next_meeting_date: aiContent.next_meeting_date || null,\n  pain_points: aiContent.pain_points || [],\n  budget_mentioned: aiContent.budget_mentioned || null\n};\n\n// Create one item per action item with meeting context\nconst outputItems = extracted.action_items.map(item => ({\n  json: {\n    task: item.task,\n    assignee: item.assignee,\n    due_date: item.due_date,\n    company_name: formData.company_name,\n    meeting_notes: formData.meeting_notes,\n    asana_project_id: formData.asana_project_id,\n    slack_channel: formData.slack_channel,\n    key_decisions: extracted.key_decisions,\n    pain_points: extracted.pain_points,\n    next_meeting_date: extracted.next_meeting_date,\n    budget_mentioned: extracted.budget_mentioned\n  }\n}));\n\nreturn outputItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "ba7e615f-db39-430b-81d5-b2a9b5d2154a",
      "name": "Create Asana Task",
      "type": "n8n-nodes-base.asana",
      "position": [
        1632,
        496
      ],
      "parameters": {
        "name": "={{ $json.task }}",
        "authentication": "oAuth2",
        "otherProperties": {
          "notes": "=Assignee: {{ $json.assignee }}\nFrom meeting with: {{ $json.company_name }}\n\nContext from meeting notes:\n{{ $json.meeting_notes }}",
          "due_on": "={{ $json.due_date }}",
          "assignee": "=me",
          "projects": "={{ $json.asana_project_id }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "843c938b-ca76-4918-97e4-215bcc478bb8",
      "name": "Combine Tasks",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1856,
        496
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "Tasks"
      },
      "typeVersion": 1
    },
    {
      "id": "9e31494c-8999-474b-b676-6c4b611ad30b",
      "name": "Format Slack Message",
      "type": "n8n-nodes-base.code",
      "position": [
        2080,
        496
      ],
      "parameters": {
        "jsCode": "// Get aggregated tasks\nconst aggregatedData = $input.item.json;\nconst tasks = aggregatedData.Tasks || [];\n\n// Get meeting context\nconst parseData = $('Structure Data').first().json;\nconst company_name = parseData.company_name || \"Unknown Company\";\nconst slack_channel = parseData.slack_channel || \"#general\";\nconst key_decisions = parseData.key_decisions || [];\nconst pain_points = parseData.pain_points || [];\nconst next_meeting_date = parseData.next_meeting_date;\nconst budget_mentioned = parseData.budget_mentioned;\n\n// Format action items\nconst actionItems = tasks.map(task => ({\n  name: task.name,\n  assignee: task.assignee ? task.assignee.name.split('@')[0] : \"Unassigned\",\n  due_date: task.due_on,\n  url: task.permalink_url\n}));\n\n// Build Slack message\nlet message = `*\ud83d\udcdd Meeting Summary: ${company_name}*\\n\\n`;\n\nif (key_decisions.length > 0) {\n  message += `*\u2705 Key Decisions:*\\n`;\n  key_decisions.forEach(d => message += `\u2022 ${d}\\n`);\n  message += `\\n`;\n}\n\nif (actionItems.length > 0) {\n  message += `*\ud83d\udccb Action Items Created (${actionItems.length}):*\\n`;\n  actionItems.forEach(item => {\n    const dueDate = item.due_date ? ` - Due: ${item.due_date}` : \"\";\n    message += `\u2022 <${item.url}|${item.name}> - ${item.assignee}${dueDate}\\n`;\n  });\n  message += `\\n`;\n}\n\nif (pain_points.length > 0) {\n  message += `*\u26a0\ufe0f Pain Points:*\\n`;\n  pain_points.forEach(p => message += `\u2022 ${p}\\n`);\n  message += `\\n`;\n}\n\nif (budget_mentioned) {\n  message += `*\ud83d\udcb0 Budget: ${budget_mentioned}*\\n\\n`;\n}\n\nif (next_meeting_date) {\n  message += `*\ud83d\udcc5 Next Meeting: ${next_meeting_date}*\\n\\n`;\n}\n\nconst projectName = tasks[0]?.projects?.[0]?.name || \"Asana\";\nmessage += `_Project: ${projectName}_`;\n\nreturn [{ json: { channel: slack_channel, message: message } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "a3d90ce6-3745-43ef-83a5-9ae6573b55e2",
      "name": "Send to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        2304,
        496
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.channel }}"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "28aebbff-b36d-408f-a290-8f2d4e241f05",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        352
      ],
      "parameters": {
        "color": 4,
        "width": 420,
        "height": 380,
        "content": "## \ud83d\udcdd Meeting Notes to Action Items\n\n**Stop manually tracking action items from meetings.**\n\nThis workflow:\n- Uses AI to extract key info\n- Creates Asana tasks automatically\n- Sends team summary via Slack\n\n**Works with any notes format:**\n- AI notetaker transcripts\n- Manual typed notes\n- Shared documents"
      },
      "typeVersion": 1
    },
    {
      "id": "2dd7517f-5c2e-4e2c-a8a6-e3144ab611db",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        144
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "## Step 1: Submit Notes\n\nForm collects:\n- Company/Project name\n- Meeting notes\n- Asana project\n- Slack channel\n\nTip: Replace with email trigger for automation"
      },
      "typeVersion": 1
    },
    {
      "id": "d208ee40-5550-4366-96fd-43436c3cc1a9",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        720
      ],
      "parameters": {
        "width": 280,
        "height": 280,
        "content": "## Step 2: AI Extraction\n\nGPT-4o extracts:\n- \u2705 Decisions\n- \ud83d\udccb Action items\n- \ud83d\udcc5 Due dates\n- \u26a0\ufe0f Pain points\n- \ud83d\udcb0 Budget\n- \ud83d\uddd3\ufe0f Next meeting"
      },
      "typeVersion": 1
    },
    {
      "id": "ab6d8b9c-7795-480f-8d68-737715e022dd",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1600,
        192
      ],
      "parameters": {
        "color": 3,
        "height": 240,
        "content": "## Step 3: Create Tasks\n\nEach action item becomes a task with:\n- Title & assignee\n- Due date\n- Full meeting context"
      },
      "typeVersion": 1
    },
    {
      "id": "4ae29fdc-4303-4b21-87ec-cd1a6a3ed74c",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2032,
        720
      ],
      "parameters": {
        "color": 6,
        "width": 300,
        "height": 280,
        "content": "## Step 4: Slack Summary\n\nFormatted message with:\n- Key decisions\n- Clickable task links\n- Pain points\n- Budget & next meeting\n\nTeam stays aligned!"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "87c6c252-76aa-43fe-a7f8-3dd601876255",
  "connections": {
    "Combine Tasks": {
      "main": [
        [
          {
            "node": "Format Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structure Data": {
      "main": [
        [
          {
            "node": "Create Asana Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Extract Data": {
      "main": [
        [
          {
            "node": "Structure Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Asana Task": {
      "main": [
        [
          {
            "node": "Combine Tasks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Meeting Notes Form": {
      "main": [
        [
          {
            "node": "AI Extract Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Slack Message": {
      "main": [
        [
          {
            "node": "Send to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow uses AI to extract action items, decisions, and key details from any meeting notes format—then creates tasks in Asana and sends a formatted summary to Slack.

Source: https://n8n.io/workflows/9875/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow is an AI-powered lighting and look development pipeline designed for VFX production. It transforms a single lighting brief into multiple high-quality cinematic lighting references using

Form Trigger, HTTP Request, Google Drive +4
AI & RAG

Some use cases: "Speed-to-Lead" optimization, lead enrichment, automated prospect research. Ingestion: A lead submits their details (Name, Email, Website) via a form. Intelligent scraping: The workflo

Form Trigger, OpenAI, Airtable +2
AI & RAG

Marketing teams, copywriters, and agencies who need to quickly generate and iterate on ad copies for Meta and TikTok campaigns. Perfect for brands that want AI-powered copy generation with human revie

OpenAI, Form Trigger, Slack
AI & RAG

This workflow automates the "speed-to-lead" process for insurance agencies. It instantly triggers an AI voice call when a new lead comes in, qualifies their needs via conversation, and automatically g

Form Trigger, Airtable, HTTP Request +3
AI & RAG

Here is the template specification based on the provided workflow and guidelines.

Form Trigger, Google Sheets, HTTP Request +2