{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "c716600a-7c26-4e23-b04d-ce80288e64ec",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -576,
        688
      ],
      "parameters": {
        "color": 4,
        "width": 652,
        "height": 1152,
        "content": "## Meeting Action Items to ClickUp \u2014 Fireflies + GPT-4o-mini + Telegram\n\nFor founders, project managers, and team leads who want every meeting action item to automatically appear as a ClickUp task \u2014 without manual note-taking or copy-pasting. When Fireflies finishes transcribing a meeting, this workflow extracts action items from two sources: the Fireflies NLP task detector and the AI-generated summary. GPT-4o-mini parses each item into a clean task with an owner, deadline, and priority. Every task is created in ClickUp automatically. A single Telegram message confirms the total count when all tasks are done.\n\n## How it works\n- **1. Webhook \u2014 Fireflies Transcript Done** receives the meetingId from Fireflies on transcription complete\n- **2. Code \u2014 Extract Meeting ID** safely extracts the meetingId from all possible Fireflies payload structures\n- **3. IF \u2014 Valid Meeting ID?** validates the meetingId \u2014 invalid webhooks exit cleanly\n- **5. Set \u2014 Config Values** stores Fireflies API key, ClickUp API token, ClickUp list ID, Telegram chat ID, and author details\n- **6. HTTP \u2014 Fetch Transcript** calls the Fireflies GraphQL API for sentences with ai_filters.task and summary.action_items\n- **7. Code \u2014 Process Action Items** combines both sources, deduplicates, and limits to 15 items\n- **8. IF \u2014 Action Items Found?** stops cleanly if no action items were detected\n- **10. AI Agent \u2014 Parse Action Items** uses GPT-4o-mini to parse each item into taskName, owner, deadline, and priority\n- **13. Code \u2014 Split Tasks for Loop** converts the array to one item per task and sets isLastTask on the final one\n- **14. HTTP \u2014 Create ClickUp Task** creates each task in ClickUp via API v2 with priority and due date\n- **15. IF \u2014 All Tasks Created?** checks the isLastTask flag \u2014 only the last task triggers Telegram\n- **16. Code \u2014 Build Telegram Summary** builds the notification message with meeting title and total task count\n- **17. Telegram \u2014 Send Task Summary** sends one confirmation message after all tasks are created\n\n## Set up steps\n1. Activate the workflow and copy the webhook URL from node 1\n2. In Fireflies \u2014 go to Settings, Developer Settings, Webhooks, and paste the URL\n3. In **5. Set \u2014 Config Values** \u2014 replace YOUR_FIREFLIES_API_KEY, YOUR_CLICKUP_API_TOKEN, YOUR_CLICKUP_LIST_ID, YOUR_TELEGRAM_CHAT_ID, your name, and company name\n4. In **11. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n5. In **17. Telegram \u2014 Send Task Summary** \u2014 connect your Telegram Bot API credential and send /start to your bot before testing"
      },
      "typeVersion": 1
    },
    {
      "id": "b6253aa9-c796-4d45-920e-bcf6cd7ada48",
      "name": "Section \u2014 Webhook Receipt and Validation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        848
      ],
      "parameters": {
        "color": 5,
        "width": 708,
        "height": 708,
        "content": "## Webhook Receipt and Validation\nFireflies POSTs a meetingId here on transcription complete. A Code node safely extracts the meetingId from any payload structure. Invalid webhooks exit cleanly via the Set node below."
      },
      "typeVersion": 1
    },
    {
      "id": "cde7f040-e4e0-4258-ae1c-804d61f5c341",
      "name": "Section \u2014 Config, Transcript Fetch, and Action Item Extraction",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        848
      ],
      "parameters": {
        "color": 6,
        "width": 964,
        "height": 660,
        "content": "## Config, Transcript Fetch, and Action Item Extraction\nConfig stores all credentials and author details. Fireflies GraphQL API fetches the transcript. A Code node extracts action items from two sources: NLP task-flagged sentences and the AI summary list. Combined, deduplicated, limited to 15."
      },
      "typeVersion": 1
    },
    {
      "id": "272d8cca-09f2-4203-90d4-eaf4748bb7f8",
      "name": "Section \u2014 AI Task Parsing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1968,
        848
      ],
      "parameters": {
        "color": 6,
        "width": 468,
        "height": 660,
        "content": "## AI Task Parsing\nGPT-4o-mini (temperature 0.2) parses each raw action item into four structured fields: a clean verb-first task name, the responsible owner, a deadline in YYYY-MM-DD format, and a priority from 1 to 4. Structured Output Parser enforces the array schema."
      },
      "typeVersion": 1
    },
    {
      "id": "1cdbbbd7-1dcf-41f9-adc4-83767687aba2",
      "name": "Section \u2014 ClickUp Task Creation Loop",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2480,
        928
      ],
      "parameters": {
        "color": 6,
        "width": 420,
        "height": 388,
        "content": "## ClickUp Task Creation Loop\nConverts the tasks array to one item per task. Creates each task in ClickUp via API v2 with name, description, priority, and due date. The isLastTask flag ensures Telegram fires exactly once after all tasks are created."
      },
      "typeVersion": 1
    },
    {
      "id": "ae5e1eb2-7e80-4e15-b852-03de2763849b",
      "name": "Section \u2014 Telegram Notification",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3040,
        800
      ],
      "parameters": {
        "color": 4,
        "width": 532,
        "height": 340,
        "content": "## Telegram Notification\nBuilds and sends a single confirmation message after all ClickUp tasks are created. Includes meeting title, date, and total task count."
      },
      "typeVersion": 1
    },
    {
      "id": "b264cc7a-7ea4-4323-9873-8faed829015c",
      "name": "1. Webhook \u2014 Fireflies Transcript Done",
      "type": "n8n-nodes-base.webhook",
      "position": [
        192,
        1120
      ],
      "parameters": {
        "path": "fireflies-action-items",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1.1
    },
    {
      "id": "d56b297b-0c13-4583-a740-fe00b4ee64c9",
      "name": "2. Code \u2014 Extract Meeting ID",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        1120
      ],
      "parameters": {
        "jsCode": "// Safely extract meetingId from all possible payload structures\nconst raw = $input.first().json;\n\nconst meetingId =\n  raw.meetingId ||\n  raw.body?.meetingId ||\n  raw.data?.meetingId ||\n  raw.payload?.meetingId ||\n  '';\n\nconst eventType =\n  raw.eventType ||\n  raw.body?.eventType ||\n  'Transcription completed';\n\nreturn [{\n  json: {\n    isValid: !!meetingId,\n    meetingId: meetingId.trim(),\n    eventType\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a899f7d0-9c83-4005-96e4-042d06a338c4",
      "name": "3. IF \u2014 Valid Meeting ID?",
      "type": "n8n-nodes-base.if",
      "position": [
        640,
        1120
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-001",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.isValid }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e340c7c2-8d95-4860-a4a5-4dfc2cf1a0e8",
      "name": "4. Set \u2014 Invalid Webhook Skip",
      "type": "n8n-nodes-base.set",
      "position": [
        640,
        1328
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "skip-001",
              "name": "result",
              "type": "string",
              "value": "Invalid webhook \u2014 no meetingId received."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9c683dcc-1e63-4cda-913e-29bc7380651e",
      "name": "5. Set \u2014 Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        976,
        1104
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "firefliesApiKey",
              "type": "string",
              "value": "YOUR_FIREFLIES_API_KEY"
            },
            {
              "id": "cfg-002",
              "name": "clickupApiToken",
              "type": "string",
              "value": "YOUR_CLICKUP_API_TOKEN"
            },
            {
              "id": "cfg-003",
              "name": "clickupListId",
              "type": "string",
              "value": "YOUR_CLICKUP_LIST_ID"
            },
            {
              "id": "cfg-004",
              "name": "telegramChatId",
              "type": "string",
              "value": "YOUR_TELEGRAM_CHAT_ID"
            },
            {
              "id": "cfg-005",
              "name": "hostName",
              "type": "string",
              "value": "YOUR NAME"
            },
            {
              "id": "cfg-006",
              "name": "companyName",
              "type": "string",
              "value": "YOUR COMPANY NAME"
            },
            {
              "id": "cfg-007",
              "name": "meetingId",
              "type": "string",
              "value": "={{ $('2. Code \u2014 Extract Meeting ID').item.json.meetingId }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f9e6b942-d647-4929-b71d-3b7e3fcf08e1",
      "name": "6. HTTP \u2014 Fetch Transcript",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1184,
        1104
      ],
      "parameters": {
        "url": "https://api.fireflies.ai/graphql",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"query\": \"query GetTranscript($id: String!) { transcript(id: $id) { id title date duration participants host_email sentences { speaker_name text ai_filters { task } } summary { action_items overview keywords } } }\",\n  \"variables\": {\n    \"id\": \"{{ $json.meetingId }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.firefliesApiKey }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "3d66e64a-857b-4845-9351-33676a9c9264",
      "name": "7. Code \u2014 Process Action Items",
      "type": "n8n-nodes-base.code",
      "position": [
        1408,
        1104
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst config = $('5. Set \u2014 Config Values').item.json;\n\nconst transcript = response?.data?.transcript;\n\nif (!transcript || !transcript.id) {\n  return [{\n    json: {\n      hasData: false,\n      meetingId: config.meetingId,\n      error: 'Transcript not found or not ready in Fireflies'\n    }\n  }];\n}\n\n// Collect action items from Fireflies summary\nconst rawActionItems = transcript.summary?.action_items || [];\n\n// ALSO collect sentences flagged as tasks by Fireflies NLP\nconst sentences = transcript.sentences || [];\nconst taskSentences = sentences\n  .filter(s => s.ai_filters?.task && (s.text || '').length > 10)\n  .map(s => (s.speaker_name ? s.speaker_name + ': ' + s.text : s.text))\n  .slice(0, 10);\n\n// Combine both sources\nconst allActionSources = [\n  ...rawActionItems,\n  ...taskSentences\n];\n\n// Deduplicate and clean\nconst uniqueItems = [...new Set(allActionSources)]\n  .filter(item => item && item.trim().length > 5)\n  .slice(0, 15);\n\nif (uniqueItems.length === 0) {\n  return [{\n    json: {\n      hasData: false,\n      meetingId: transcript.id,\n      error: 'No action items found in this meeting'\n    }\n  }];\n}\n\nconst meetingDate = transcript.date\n  ? new Date(transcript.date).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })\n  : new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });\n\nconst durationMin = Math.round((transcript.duration || 0) / 60);\nconst participants = (transcript.participants || []).join(', ') || 'Not listed';\nconst overview = (transcript.summary?.overview || '').substring(0, 500);\nconst keywords = (transcript.summary?.keywords || []).slice(0, 8).join(', ');\n\nreturn [{\n  json: {\n    hasData: true,\n    meetingId: transcript.id,\n    meetingTitle: transcript.title || 'Untitled Meeting',\n    meetingDate,\n    durationMin,\n    participants,\n    overview,\n    keywords,\n    actionItemsRaw: uniqueItems.join('\\n'),\n    actionItemCount: uniqueItems.length,\n    clickupApiToken: config.clickupApiToken,\n    clickupListId: config.clickupListId,\n    telegramChatId: config.telegramChatId,\n    hostName: config.hostName,\n    companyName: config.companyName\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "9f313a3f-0965-43ac-a63d-af3e37276740",
      "name": "8. IF \u2014 Action Items Found?",
      "type": "n8n-nodes-base.if",
      "position": [
        1648,
        1104
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-data",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.hasData }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a7f2b1da-d2d0-4d5d-8996-e637b10413fa",
      "name": "9. Set \u2014 No Action Items Skip",
      "type": "n8n-nodes-base.set",
      "position": [
        1648,
        1312
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "skip-002",
              "name": "result",
              "type": "string",
              "value": "=No action items found or transcript not ready for: {{ $json.meetingId }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ae6aaf0e-7066-41d2-9b17-83538356c999",
      "name": "10. AI Agent \u2014 Parse Action Items",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2016,
        1088
      ],
      "parameters": {
        "text": "=You are a project manager parsing meeting action items into structured ClickUp tasks.\n\nMEETING: {{ $json.meetingTitle }}\nDATE: {{ $json.meetingDate }}\nPARTICIPANTS: {{ $json.participants }}\nOVERVIEW: {{ $json.overview }}\n\nACTION ITEMS FROM MEETING:\n{{ $json.actionItemsRaw }}\n\nFor EACH action item above, extract the following and return a JSON array.\n\nReturn ONLY a valid JSON array. No extra text. No markdown. No backticks.\nEach element in the array must have exactly these 4 fields:\n\ntaskName \u2014 A clean, actionable task title. Start with a verb. Maximum 60 characters. Example: Send project proposal to client by Friday\n\nowner \u2014 The person responsible. Extract from the action item text if mentioned. If not mentioned, write: Unassigned\n\ndeadline \u2014 The deadline in YYYY-MM-DD format. Extract from the action item if a date or timeframe is mentioned. Examples: today = {{ $now.toFormat('yyyy-MM-dd') }}, tomorrow = {{ $now.plus({days: 1}).toFormat('yyyy-MM-dd') }}, this week = {{ $now.plus({days: 3}).toFormat('yyyy-MM-dd') }}, next week = {{ $now.plus({days: 7}).toFormat('yyyy-MM-dd') }}. If no deadline mentioned, default to {{ $now.plus({days: 2}).toFormat('yyyy-MM-dd') }}\n\npriority \u2014 A number: 1 for urgent, 2 for high, 3 for normal, 4 for low. Use context to decide. If unclear use 3.\n\nEXAMPLE OUTPUT FORMAT:\n[{\"taskName\": \"Send updated proposal to John by Friday\", \"owner\": \"Rahul\", \"deadline\": \"2026-04-12\", \"priority\": 2}, {\"taskName\": \"Schedule follow-up call with client\", \"owner\": \"Unassigned\", \"deadline\": \"2026-04-14\", \"priority\": 3}]\n\nRULES:\n- Return ONLY the JSON array. Nothing else.\n- Every item in the input must become exactly one task in the output.\n- Do not skip any action items.\n- Do not add tasks that were not in the input.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "22cf98cc-bad3-4630-b0de-af551b2780df",
      "name": "11. OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2016,
        1280
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 1200,
          "temperature": 0.2
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "8dc8f45d-5121-46f2-a5fe-eafc367d6895",
      "name": "12. Parser \u2014 Structured Task Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2160,
        1360
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"array\",\n  \"items\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"taskName\": {\n        \"type\": \"string\",\n        \"description\": \"Clean actionable task title starting with a verb. Max 60 chars.\"\n      },\n      \"owner\": {\n        \"type\": \"string\",\n        \"description\": \"Person responsible for this task. Use Unassigned if not mentioned.\"\n      },\n      \"deadline\": {\n        \"type\": \"string\",\n        \"description\": \"Deadline date in YYYY-MM-DD format\"\n      },\n      \"priority\": {\n        \"type\": \"number\",\n        \"description\": \"Priority: 1=Urgent 2=High 3=Normal 4=Low\"\n      }\n    },\n    \"required\": [\"taskName\", \"owner\", \"deadline\", \"priority\"]\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "9e247d97-30fd-4111-bdbc-590418922767",
      "name": "13. Code \u2014 Split Tasks for Loop",
      "type": "n8n-nodes-base.code",
      "position": [
        2288,
        1088
      ],
      "parameters": {
        "jsCode": "// Convert parsed tasks array into individual items for ClickUp loop\nconst aiOutput = $input.first().json.output;\nconst meetingData = $('7. Code \u2014 Process Action Items').item.json;\n\nif (!aiOutput || !Array.isArray(aiOutput) || aiOutput.length === 0) {\n  return [{\n    json: {\n      hasTasksToCreate: false,\n      error: 'No structured tasks returned from AI',\n      meetingTitle: meetingData.meetingTitle,\n      telegramChatId: meetingData.telegramChatId,\n      hostName: meetingData.hostName\n    }\n  }];\n}\n\n// Return ONE item per task\nreturn aiOutput.map((task, index) => {\n  const deadlineMs = task.deadline\n    ? new Date(task.deadline).getTime()\n    : Date.now() + (2 * 24 * 60 * 60 * 1000);\n\n  const priorityNum = parseInt(task.priority) || 3;\n  const validPriority = [1, 2, 3, 4].includes(priorityNum) ? priorityNum : 3;\n\n  return {\n    json: {\n      hasTasksToCreate: true,\n      taskName: (task.taskName || 'Untitled Task').substring(0, 100),\n      owner: task.owner || 'Unassigned',\n      deadline: task.deadline || 'Not set',\n      deadlineMs,\n      priority: validPriority,\n      taskIndex: index + 1,\n      totalTasks: aiOutput.length,\n      isLastTask: index === aiOutput.length - 1,\n      meetingTitle: meetingData.meetingTitle,\n      meetingDate: meetingData.meetingDate,\n      meetingId: meetingData.meetingId,\n      clickupApiToken: meetingData.clickupApiToken,\n      clickupListId: meetingData.clickupListId,\n      telegramChatId: meetingData.telegramChatId,\n      hostName: meetingData.hostName,\n      companyName: meetingData.companyName\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "43a4e049-7535-4281-8cbe-22f7cd9089c2",
      "name": "14. HTTP \u2014 Create ClickUp Task",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2528,
        1088
      ],
      "parameters": {
        "url": "=https://api.clickup.com/api/v2/list/{{ $json.clickupListId }}/task",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"name\": \"{{ $json.taskName }}\",\n  \"description\": \"Meeting: {{ $json.meetingTitle }}\\nDate: {{ $json.meetingDate }}\\nOwner: {{ $json.owner }}\\nDeadline: {{ $json.deadline }}\\n\\nAuto-created from meeting notes by n8n + Fireflies + GPT-4o-mini\",\n  \"priority\": {{ $json.priority }},\n  \"due_date\": {{ $json.deadlineMs }},\n  \"due_date_time\": true,\n  \"notify_all\": false,\n  \"tags\": [\"meeting-action-item\"]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ $json.clickupApiToken }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7fd2b4db-0a42-47eb-9f95-9f135aa40d17",
      "name": "15. IF \u2014 All Tasks Created?",
      "type": "n8n-nodes-base.if",
      "position": [
        2752,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-last",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $('13. Code \u2014 Split Tasks for Loop').item.json.isLastTask }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e1b7862e-3fe4-4f4e-ab22-4bbee4d8c086",
      "name": "16. Code \u2014 Build Telegram Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        3120,
        928
      ],
      "parameters": {
        "jsCode": "// Build Telegram summary message after all tasks created\nconst lastTaskData = $('13. Code \u2014 Split Tasks for Loop').item.json;\nconst totalTasks = lastTaskData.totalTasks;\nconst meetingTitle = lastTaskData.meetingTitle;\nconst meetingDate = lastTaskData.meetingDate;\nconst hostName = lastTaskData.hostName;\nconst companyName = lastTaskData.companyName;\n\nconst message =\n  'Meeting Action Items Created in ClickUp\\n' +\n  '\\n' +\n  'Meeting: ' + meetingTitle + '\\n' +\n  'Date: ' + meetingDate + '\\n' +\n  'Tasks Created: ' + totalTasks + ' tasks\\n' +\n  '\\n' +\n  'All tasks have been added to your ClickUp list automatically.\\n' +\n  'Check ClickUp to review, assign, and adjust deadlines.\\n' +\n  '\\n' +\n  'Powered by ' + companyName + ' + Fireflies.ai + GPT-4o-mini';\n\nreturn [{\n  json: {\n    telegramMessage: message,\n    telegramChatId: lastTaskData.telegramChatId\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "7b482d9e-e013-40cc-9a1e-adaeb708351e",
      "name": "17. Telegram \u2014 Send Task Summary",
      "type": "n8n-nodes-base.telegram",
      "position": [
        3328,
        928
      ],
      "parameters": {
        "text": "={{ $json.telegramMessage }}",
        "chatId": "={{ $json.telegramChatId }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "69317b16-0964-4ce5-bc28-55717c3ac52f",
      "name": "18. Set \u2014 Loop Continues",
      "type": "n8n-nodes-base.set",
      "position": [
        3104,
        1248
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "skip-loop-001",
              "name": "result",
              "type": "string",
              "value": "=Task created. Continuing loop \u2014 not last task yet."
            }
          ]
        }
      },
      "typeVersion": 3.4
    }
  ],
  "connections": {
    "5. Set \u2014 Config Values": {
      "main": [
        [
          {
            "node": "6. HTTP \u2014 Fetch Transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. IF \u2014 Valid Meeting ID?": {
      "main": [
        [
          {
            "node": "5. Set \u2014 Config Values",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "4. Set \u2014 Invalid Webhook Skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. HTTP \u2014 Fetch Transcript": {
      "main": [
        [
          {
            "node": "7. Code \u2014 Process Action Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "15. IF \u2014 All Tasks Created?": {
      "main": [
        [
          {
            "node": "16. Code \u2014 Build Telegram Summary",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "18. Set \u2014 Loop Continues",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8. IF \u2014 Action Items Found?": {
      "main": [
        [
          {
            "node": "10. AI Agent \u2014 Parse Action Items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "9. Set \u2014 No Action Items Skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Code \u2014 Extract Meeting ID": {
      "main": [
        [
          {
            "node": "3. IF \u2014 Valid Meeting ID?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "11. OpenAI \u2014 GPT-4o-mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "10. AI Agent \u2014 Parse Action Items",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "14. HTTP \u2014 Create ClickUp Task": {
      "main": [
        [
          {
            "node": "15. IF \u2014 All Tasks Created?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. Code \u2014 Process Action Items": {
      "main": [
        [
          {
            "node": "8. IF \u2014 Action Items Found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "13. Code \u2014 Split Tasks for Loop": {
      "main": [
        [
          {
            "node": "14. HTTP \u2014 Create ClickUp Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10. AI Agent \u2014 Parse Action Items": {
      "main": [
        [
          {
            "node": "13. Code \u2014 Split Tasks for Loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "16. Code \u2014 Build Telegram Summary": {
      "main": [
        [
          {
            "node": "17. Telegram \u2014 Send Task Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "12. Parser \u2014 Structured Task Output": {
      "ai_outputParser": [
        [
          {
            "node": "10. AI Agent \u2014 Parse Action Items",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "1. Webhook \u2014 Fireflies Transcript Done": {
      "main": [
        [
          {
            "node": "2. Code \u2014 Extract Meeting ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}