{
  "id": "ZGNostTBUj8ot9yp",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Extract meeting tasks from transcripts and sync with Trello",
  "tags": [],
  "nodes": [
    {
      "id": "70515f8f-edd6-4c52-947a-f79cbb7429ef",
      "name": "Get Transcription",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        480,
        0
      ],
      "parameters": {
        "options": {},
        "operation": "text",
        "binaryPropertyName": "Transcript_archive"
      },
      "typeVersion": 1
    },
    {
      "id": "203f05d3-7356-40b9-ad81-248760e72080",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        944,
        0
      ],
      "parameters": {
        "text": "=Transcript:\n\n{{ $json.data }}",
        "options": {
          "systemMessage": "=# Main Agent Instructions\n\nYou are an assistant specialized in meeting analysis.\nYour job is to (1) extract actionable tasks from a meeting transcript, (2) sync each task with Trello via the Trello Sub-Agent, and (3) produce a clear user-facing summary.\n\n## Workflow\n\n1. **Extract Tasks**\n   - Identify only clear, actionable tasks.\n   - For each task, produce:\n     - **title** \u2192 short, concise (max ~6 words).\n     - **description** \u2192 1\u20132 sentences explaining the action.\n     - **assignee** \u2192 person responsible, or `\"undefined\"`.\n     - **deadline** \u2192 date/time if mentioned, or `\"undefined\"`.\n   - **Deduplicate** (merge near-duplicates; keep one canonical task).\n\n2. **Sync with Trello (via Trello Sub-Agent)**\n   - For each task, call the **Trello Sub-Agent** with `title`, `description`, `assignee`, `deadline`.\n   - The Trello Sub-Agent will:\n     - Use **Get Trello Cards** to check for an existing card (case-insensitive, tolerant to small wording changes).\n     - If a match exists \u2192 return `{ \"status\": \"exists\", \"card_id\": \"<id>\" }`.\n     - If no match \u2192 create with **Create Trello Card** and return `{ \"status\": \"created\", \"card_id\": \"<id>\" }`.\n\n3. **User-Facing Summary**\n   - Write a brief summary (1\u20133 sentences) describing: total tasks found, how many already existed, how many were created, and any tasks without assignee or deadline.\n   - The summary **must be in the user\u2019s language** (if unknown, use English).\n   - Keep it concise and non-technical.\n\n4. **Output Format**\n   - Return a JSON object with two top-level keys: `summary` and `tasks`.\n\n### JSON Schema\n\n```json\n{\n  \"summary\": {\n    \"text\": \"string\",\n    \"metrics\": {\n      \"total_tasks\": \"number\",\n      \"existing_cards\": \"number\",\n      \"created_cards\": \"number\",\n      \"without_assignee\": \"number\",\n      \"without_deadline\": \"number\"\n    }\n  },\n  \"tasks\": [\n    {\n      \"title\": \"string (\u2264 6 words)\",\n      \"description\": \"string (1\u20132 sentences)\",\n      \"assignee\": \"string | \\\"undefined\\\"\",\n      \"deadline\": \"string | \\\"undefined\\\"\",\n      \"status\": \"exists | created\",\n      \"card_id\": \"string\"\n    }\n  ]\n}\n````\n\nIf no tasks are found, return:\n\n```json\n{\n  \"summary\": {\n    \"text\": \"No tasks were found in the transcript.\",\n    \"metrics\": {\n      \"total_tasks\": 0,\n      \"existing_cards\": 0,\n      \"created_cards\": 0,\n      \"without_assignee\": 0,\n      \"without_deadline\": 0\n    }\n  },\n  \"tasks\": []\n}\n```\n\n## Example\n\n**Transcript Excerpt**\n\n> John: I can prepare the financial report by Friday.\n> Maria: I\u2019ll schedule the client meeting.\n\n**Expected Output**\n\n```json\n{\n  \"summary\": {\n    \"text\": \"Found 2 tasks in the transcript: 1 already existed in Trello and 1 was created. None are missing an assignee; 1 has no deadline.\",\n    \"metrics\": {\n      \"total_tasks\": 2,\n      \"existing_cards\": 1,\n      \"created_cards\": 1,\n      \"without_assignee\": 0,\n      \"without_deadline\": 1\n    }\n  },\n  \"tasks\": [\n    {\n      \"title\": \"Prepare financial report\",\n      \"description\": \"John will compile and deliver the financial report by Friday.\",\n      \"assignee\": \"John\",\n      \"deadline\": \"Friday\",\n      \"status\": \"exists\",\n      \"card_id\": \"abc123\"\n    },\n    {\n      \"title\": \"Schedule client meeting\",\n      \"description\": \"Maria will arrange a meeting with the client to align next steps.\",\n      \"assignee\": \"Maria\",\n      \"deadline\": \"undefined\",\n      \"status\": \"created\",\n      \"card_id\": \"xyz789\"\n    }\n  ]\n}\n```\n\n## Sub-Agents\n\n## Trello Sync\n\nFor each extracted task:\n1. Call the **Trello Sub-Agent** with `title`, `description`, `assignee`, `deadline`.\n2. Append the sub-agent result to the task:\n   - `status`: \"exists\" | \"created\"\n   - `card_id`: string\n   - optionally `list_id` (when status = \"exists\")\n3. Use these results to build the user-facing `summary.metrics`:\n   - `total_tasks`, `existing_cards`, `created_cards`,\n   - `without_assignee`, `without_deadline`."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "50775259-4478-4445-be0b-03da0b9f796b",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1184,
        208
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"summary\": {\n    \"text\": \"Found 2 tasks in the transcript: 1 already existed in Trello and 1 was created. None are missing an assignee; 1 has no deadline.\",\n    \"metrics\": {\n      \"total_tasks\": 2,\n      \"existing_cards\": 1,\n      \"created_cards\": 1,\n      \"without_assignee\": 0,\n      \"without_deadline\": 1\n    }\n  },\n  \"tasks\": [\n    {\n      \"title\": \"Prepare financial report\",\n      \"description\": \"John will compile and deliver the financial report by Friday.\",\n      \"assignee\": \"John\",\n      \"deadline\": \"Friday\",\n      \"status\": \"exists\",\n      \"card_id\": \"abc123\"\n    },\n    {\n      \"title\": \"Schedule client meeting\",\n      \"description\": \"Maria will arrange a meeting with the client to align next steps.\",\n      \"assignee\": \"Maria\",\n      \"deadline\": \"undefined\",\n      \"status\": \"created\",\n      \"card_id\": \"xyz789\"\n    }\n  ]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d34e917d-9065-408e-a9ac-f66480118e6f",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        896,
        208
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "35a227e0-41e5-4773-8628-a3863e09165b",
      "name": "Receive Transcript file",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "options": {},
        "formTitle": "Tasks from meeting",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Transcript archive",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".txt"
            }
          ]
        },
        "responseMode": "lastNode",
        "formDescription": "Create Trello tasks from a meeting transcript"
      },
      "typeVersion": 2.3
    },
    {
      "id": "48c38412-ae7d-40cb-be25-dd6ff989938e",
      "name": "Trello Agent",
      "type": "@n8n/n8n-nodes-langchain.agentTool",
      "position": [
        1008,
        448
      ],
      "parameters": {
        "text": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Prompt__User_Message_', `Trello task`, 'string') }}",
        "options": {
          "systemMessage": "=# Trello Sub-Agent Instructions\n\nYou manage Trello syncing for tasks.\nTools available:\n- **Get many lists in Trello**\n- **Get all cards in a list in Trello**\n- **Create a card in Trello** (targets a single preconfigured default list)\n\n## Input\nTask JSON:\n- `title` (string, required)\n- `description` (string, required)\n- `assignee` (string | \"undefined\")\n- `deadline` (string | \"undefined\")\n\n## Board-wide Duplicate Check (title AND description)\n1. Call **Get many lists in Trello** and collect all `list_id`s.\n2. For each list, call **Get all cards in a list in Trello**.\n3. For each card, compare:\n   - Incoming `title` \u2194 card `name`\n   - Incoming `description` \u2194 card `desc`\n\n### Normalization\n- Lowercase, trim, collapse multiple spaces.\n- Strip punctuation and emojis.\n- Normalize common accents/diacritics.\n- Optional: drop very common stopwords (e.g., \u201cthe\u201d, \u201ca\u201d, \u201cof\u201d, \u201cpara\u201d, \u201cde\u201d).\n\n### Match Criteria (declare duplicate if ANY holds)\n- **Exact title match** (normalized) **AND** description **highly similar** (\u2265 0.80 token overlap or near-exact).\n- **High title similarity** (\u2265 0.90) **AND** **high description similarity** (\u2265 0.80).\n- **Exact description match** (normalized) **AND** title **highly similar** (\u2265 0.90).\n\n> If multiple candidates match, choose the **highest combined similarity** (title_sim * 0.6 + desc_sim * 0.4).\n\n4. If a duplicate is found **anywhere on the board**, **do not create** a card. Return:\n```json\n{ \"status\": \"exists\", \"card_id\": \"<existing_card_id>\", \"list_id\": \"<existing_list_id>\" }\n````\n\n## Create (only if NO duplicate found)\n\n* Call **Create a card in Trello** with:\n\n  * `name` = `title`\n  * `desc` = `description`\n  * Add `assignee` / `deadline` if the tool supports these fields.\n* Return:\n\n```json\n{ \"status\": \"created\", \"card_id\": \"<new_card_id>\", \"created_in_default_list\": true }\n```\n\n## Output (always one object)\n\n* Duplicate:\n\n```json\n{ \"status\": \"exists\", \"card_id\": \"<id>\", \"list_id\": \"<list_id>\" }\n```\n\n* Created:\n\n```json\n{ \"status\": \"created\", \"card_id\": \"<id>\", \"created_in_default_list\": true }\n```\n\n* Error:\n\n```json\n{ \"status\": \"error\", \"message\": \"Reason...\" }\n```\n\n## Notes\n\n* Be conservative: one card per unique task.\n* Prefer NOT creating when in doubt (high similarity)."
        },
        "hasOutputParser": true,
        "toolDescription": "Responsible for syncing tasks with Trello. It checks if a card already exists for a given task and creates one if it doesn\u2019t, ensuring no duplicates are added"
      },
      "typeVersion": 2.2
    },
    {
      "id": "40527286-8a51-4ac0-ba33-b41a6da83cf9",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1696,
        656
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"Trello Sub-Agent Output\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"status\": {\n      \"type\": \"string\",\n      \"enum\": [\"exists\", \"created\", \"error\"],\n      \"description\": \"Result of the Trello sync check.\"\n    },\n    \"card_id\": {\n      \"type\": \"string\",\n      \"description\": \"ID of the Trello card (if exists or created).\"\n    },\n    \"list_id\": {\n      \"type\": \"string\",\n      \"description\": \"ID of the list where the card already exists (only when status = 'exists').\"\n    },\n    \"created_in_default_list\": {\n      \"type\": \"boolean\",\n      \"description\": \"True if a new card was created in the default list (only when status = 'created').\"\n    },\n    \"message\": {\n      \"type\": \"string\",\n      \"description\": \"Error message if status = 'error'.\"\n    }\n  },\n  \"required\": [\"status\"],\n  \"additionalProperties\": false\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "b3f6f705-03f8-4aca-a320-e2a2d6f969a3",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        976,
        656
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4b687b0d-c314-4bed-801e-81ab8d77927c",
      "name": "Create a card in Trello",
      "type": "n8n-nodes-base.trelloTool",
      "position": [
        1136,
        656
      ],
      "parameters": {
        "name": "={{ $fromAI('taskTitle') }}",
        "listId": "Specific List ID",
        "description": "={{ $fromAI('taskDescription') }}",
        "additionalFields": {}
      },
      "credentials": {
        "trelloApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f6e13596-4b3d-4fa5-a2d7-f5bf15656e97",
      "name": "Get many lists in Trello",
      "type": "n8n-nodes-base.trelloTool",
      "position": [
        1312,
        656
      ],
      "parameters": {
        "id": "Your Board ID",
        "resource": "list",
        "operation": "getAll",
        "returnAll": true,
        "additionalFields": {}
      },
      "credentials": {
        "trelloApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e031ecda-c0d0-4668-afcc-bd2268ac65c8",
      "name": "Get all cards in a list in Trello",
      "type": "n8n-nodes-base.trelloTool",
      "position": [
        1488,
        656
      ],
      "parameters": {
        "id": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('List_ID', ``, 'string') }}",
        "resource": "list",
        "operation": "getCards",
        "returnAll": true,
        "additionalFields": {
          "fields": "name, desc"
        }
      },
      "credentials": {
        "trelloApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cd442a7c-0f53-4993-aa9c-139ccdf0d183",
      "name": "Respond to Form",
      "type": "n8n-nodes-base.form",
      "position": [
        1632,
        0
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "Graded transcripts and tasks created in Trello",
        "completionMessage": "={{ $json.output.summary.text }}"
      },
      "typeVersion": 2.3
    },
    {
      "id": "d667ead8-0892-4e2d-8662-06bd7f55e24b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -688
      ],
      "parameters": {
        "color": 6,
        "width": 1920,
        "height": 496,
        "content": "## Extract meeting tasks and sync with Trello\n\nThis workflow processes a meeting transcript (uploaded as a .txt file), extracts actionable tasks using AI, and syncs them with Trello.\n\n### What it does\n- Receive a transcript file from a form\n- Extract clear tasks with title, description, assignee, and deadline\n- Check Trello for duplicates (by title + description across all lists)\n- If duplicate exists \u2192 return existing card ID\n- If not \u2192 create a new card in the default Trello list\n- Generate a user-friendly summary of the results\n\n### Who is it for\nTeams who want to turn meeting notes into actionable Trello tasks automatically.\n\n### Requirements\n- Trello account with credentials set up\n- OpenAI (or other LLM) credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "f7c2888b-dbda-4e5a-bde0-2948016216a5",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        384,
        -144
      ],
      "parameters": {
        "width": 304,
        "height": 304,
        "content": "**Get Transcription node**\n\n> Extracts raw text from the uploaded transcript file.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6753c318-fef9-4558-bc3b-63e50dedfc17",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -144
      ],
      "parameters": {
        "width": 304,
        "height": 304,
        "content": "**Form Trigger node**\n\n> Receives the transcript file (.txt) from the user."
      },
      "typeVersion": 1
    },
    {
      "id": "6ba8dc96-1c09-4874-a8ce-d74b9f94d749",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        -144
      ],
      "parameters": {
        "color": 3,
        "width": 560,
        "height": 496,
        "content": "**AI Agent node**\n\n> Main agent that extracts tasks, checks duplicates via Trello Sub-Agent, and builds the JSON output (summary + tasks).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a63d8b4f-8077-402e-9a52-acb167af2298",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        384
      ],
      "parameters": {
        "color": 5,
        "width": 1456,
        "height": 432,
        "content": "**Trello Agent node**\n\n> Sub-agent responsible for Trello sync.\n> Uses \u201cGet many lists\u201d + \u201cGet all cards in a list\u201d to check duplicates (title + description).\n> Creates a new card only if no duplicate exists.\n\n**Create card / Get lists / Get cards nodes**\n\n> Trello API tools used by the sub-agent:\n\n* **Get many lists** \u2192 get all list IDs in the board\n* **Get all cards in a list** \u2192 fetch existing cards with `name` + `desc`\n* **Create a card** \u2192 add a task card in the preconfigured default list\n\n**Structured Output Parser nodes**\n\n> Parse the AI agent outputs into structured JSON (tasks, summary, Trello status)."
      },
      "typeVersion": 1
    },
    {
      "id": "fdb32427-0adc-4d40-a616-93b32981aae0",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1520,
        -144
      ],
      "parameters": {
        "width": 304,
        "height": 304,
        "content": "**Respond to Form node**\n\n> Returns a final confirmation message to the user with the summary (tasks created vs. already existing)."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "3bc1df01-1881-41f8-92ff-6de105bfc690",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Respond to Form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trello Agent": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Get Transcription": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Trello Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Create a card in Trello": {
      "ai_tool": [
        [
          {
            "node": "Trello Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Receive Transcript file": {
      "main": [
        [
          {
            "node": "Get Transcription",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many lists in Trello": {
      "ai_tool": [
        [
          {
            "node": "Trello Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "Trello Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Get all cards in a list in Trello": {
      "ai_tool": [
        [
          {
            "node": "Trello Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}