---
title: "Build a Meeting Notes → Action Items Flow in n8n"
description: "Step-by-step: build an n8n workflow that turns a meeting transcript into action items in Notion or Trello, with AI credits included."
canonical: https://agentroost.app/en/blog/meeting-notes-action-items-n8n-ai
date: 2026-06-09T20:00:00Z
---

[Canonical URL](https://agentroost.app/en/blog/meeting-notes-action-items-n8n-ai)

After every meeting, someone has to wade through a wall of transcript text and figure out who does what by when. It takes 10–20 minutes per meeting, it's error-prone, and it's the kind of task that screams "automate this." Here is a complete n8n workflow that does exactly that — one webhook call with a raw transcript, one AI node that extracts decisions and action items, and automatic task creation in Notion or Trello.

## What the workflow does

1. Receives a meeting transcript over a secure webhook URL.
2. Passes the text to an AI/LLM node that returns a structured JSON object — summary, decisions made, and a list of action items (owner + due date + description).
3. Loops over the action items and creates one task per item in your tracker.

You own the workflow, the data never leaves your instance, and nothing is shared with other users.

---

## Step 1 — Trigger: Webhook node

Add a **Webhook** node. Set **HTTP Method** to `POST`. n8n gives you a unique HTTPS endpoint; you'll call this from your meeting bot, Zapier, or even a cURL command after a call.

Set **Response Mode** to `Last Node` if you want to return the created task IDs to the caller, or `Immediately` if you want fire-and-forget.

**Example body your caller sends:**
```json
{
  "title": "Product sync 2026-06-13",
  "transcript": "Alice: We decided to launch the beta next Friday. Bob will own the landing page copy by Wednesday. Carol will ping the QA team today..."
}
```

Map `{{ $json.transcript }}` and `{{ $json.title }}` forward to the next node.

---

## Step 2 — AI node: extract structure from the transcript

Add an **AI Agent** node (or the simpler **Basic LLM Chain** node if you just need a single prompt → response). Connect it to the Webhook.

**System prompt (paste this exactly):**
```
You are a meeting assistant. Given a raw meeting transcript, return ONLY valid JSON in this shape:
{
  "summary": "<2-3 sentence meeting summary>",
  "decisions": ["<decision 1>", "<decision 2>"],
  "action_items": [
    { "owner": "<name>", "task": "<what they will do>", "due": "<YYYY-MM-DD or 'not set'>" }
  ]
}
Do not include markdown fences or any text outside the JSON object.
```

**User message:**
```
Meeting title: {{ $json.title }}

Transcript:
{{ $json.transcript }}
```

Set **Output Parser** to **JSON** (or add a **JSON Parse** node after) so n8n materialises the array rather than keeping it as a raw string.

> **On AgentRoost** there is no API key to configure here. Your AI node credential is pre-wired to your included credits — you pick a model from the dropdown (350+ available, switch anytime) and the node works immediately.

---

## Step 3 — Set node: flatten for the loop

The AI response lands as `action_items` (an array). Add a **Set** node to explicitly expose the fields you need downstream:

| Field name | Value |
|---|---|
| `summary` | `{{ $json.summary }}` |
| `decisions` | `{{ $json.decisions.join('\n') }}` |
| `action_items` | `{{ $json.action_items }}` |
| `meeting_title` | `{{ $('Webhook').item.json.title }}` |

Keep **Include Other Fields** off to avoid carrying the entire transcript forward into every task.

---

## Step 4 — Loop Over Items

Add a **Loop Over Items** node (it replaced SplitInBatches in recent n8n versions). Connect it to the Set node. Set **Batch Size** to `1`.

This sends each action item through the next node one at a time, so you get one task per action item.

---

## Step 5A — Create tasks in Notion

Add a **Notion** node. Operation: **Create Page**. Database: your tasks database.

Map the properties:
- **Name / Title** → `{{ $json.task }}`
- **Assignee** → `{{ $json.owner }}` (text property, or map to a Person if your DB has it)
- **Due Date** → `{{ $json.due }}`
- **Status** → set to a default like `To Do`
- **Notes** → add a text block with `{{ $('Set').item.json.summary }}` so every task carries the meeting summary as context

Connect the Notion node back to the Loop node's input so it iterates.

---

## Step 5B — Create cards in Trello (alternative)

Swap the Notion node for a **Trello** node. Operation: **Create Card**.

- **List ID** → your "To Do" list ID (find it by opening the list URL in Trello)
- **Name** → `{{ $json.task }} ({{ $json.owner }})`
- **Description** → `Due: {{ $json.due }}\n\nMeeting: {{ $('Set').item.json.meeting_title }}\n\n{{ $('Set').item.json.summary }}`
- **Due Date** → `{{ $json.due }}` (Trello accepts ISO 8601)

---

## Step 6 — (Optional) Post the summary to Slack or email

After the loop finishes, add an **IF** node that checks `{{ $runIndex === 0 }}` to fire only once, then route to a **Slack** node or **Send Email** node.

Slack message body:
```
*Meeting summary: {{ $('Set').item.json.meeting_title }}*

{{ $('Set').item.json.summary }}

*Decisions:*
{{ $('Set').item.json.decisions }}

Tasks created in Notion/Trello ✓
```

This gives your team an instant Slack thread linking the decisions, without anyone having to write it up manually.

---

## Tips and common pitfalls

**AI node returns malformed JSON.** Add a **JSON Parse** node right after the AI node and wrap it in an **Error Trigger** fallback that pings you on Slack. Or tell the model explicitly in the system prompt: "Do not wrap the output in markdown code fences" — this eliminates the most common failure mode.

**Transcript is too long.** Most models handle 8k–32k tokens easily. If your standups are genuinely long, chunk the transcript with a **Code** node (JavaScript) before passing it to the AI node, then merge the partial results with a second **Aggregate** node.

**The due date says "not set".** Add an **IF** node before the task creator to skip or flag those items — or default them to `+7 days` using a **Code** node: `new Date(Date.now() + 7*24*60*60*1000).toISOString().split('T')[0]`

**Running this on a schedule.** If you use a transcription service (Otter.ai, Fireflies, Zoom cloud recordings) that can call a webhook, wire it to this flow directly. If not, swap the Webhook trigger for a **Schedule Trigger** that polls a Google Drive folder for new `.txt` or `.vtt` files, then reads them with the **Google Drive** node.

---

## Run this on your own n8n — without the server setup

The workflow above runs on a standard n8n instance. The usual route to get there: rent a VPS ($6–12/mo), install Docker, configure nginx, sort out SSL, set up a Postgres database, wire in your OpenAI key, and keep the whole stack patched. Realistic time to first workflow: several hours.

On **AgentRoost** the path is shorter:

1. **Sign up** at [agentroost.app](/en/agents/n8n) — email/password, Google, or Microsoft.
2. **Pick the n8n framework**, name your instance.
3. Your private n8n editor opens at `https://<your-id>.agentroost.app` within about two minutes.
4. Import the workflow above (paste JSON via **Import from clipboard**) or build it node by node.
5. Open the AI node credential — it is already connected to your included AI credits. Pick a model, paste your system prompt, done. No API key required.

Your webhooks get a real public HTTPS URL immediately. Your data lives on your instance; no other AgentRoost customer shares it. Plans start at **$19.99/mo all-in**, which bundles the compute, the AI credits, and the SSL/domain — and there is a 14-day money-back guarantee if it is not the right fit.

[See what's included in each plan](/en/pricing) — or go straight to [your own n8n instance](/en/agents/n8n).

---

The workflow is about 8 nodes total. Once it is live, every meeting transcript your team drops into it comes back as a clean summary, a decision log, and a set of tasks sitting in your tracker — in under 30 seconds, with no manual copy-paste.
