AutomationFlowsAI & RAG › Create Linkedin Post Drafts From Fireflies Meetings with Gpt-4o-mini, Drive…

Create Linkedin Post Drafts From Fireflies Meetings with Gpt-4o-mini, Drive…

Original n8n title: Create Linkedin Post Drafts From Fireflies Meetings with Gpt-4o-mini, Drive and Slack

ByIncrementors @incrementors on n8n.io

Connect Fireflies to this workflow once and every meeting you record becomes a LinkedIn post draft automatically. The moment Fireflies finishes transcribing a call, it fires a signal to the workflow — which fetches the full transcript, extracts real insights, and uses…

Webhook trigger★★★★☆ complexityAI-powered19 nodesHTTP RequestAgentOpenAI ChatGoogle DriveSlack
AI & RAG Trigger: Webhook Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Google Drive 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "fb351597-01ca-435e-b623-c769e8ef3867",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5008,
        -448
      ],
      "parameters": {
        "color": 4,
        "width": 556,
        "height": 1160,
        "content": "## LinkedIn Post Generator \u2014 Fireflies + GPT-4o-mini + Google Drive + Slack\n\nFor founders, consultants, and sales leaders who want to turn every client call or meeting into a LinkedIn post automatically. When Fireflies finishes transcribing a meeting, it fires a webhook to this workflow. The transcript is fetched from the Fireflies API, processed for key insights, and passed to GPT-4o-mini which writes a scroll-stopping LinkedIn post with a hook, key learnings with emojis, a closing question, and hashtags. The post is saved as a Google Doc and previewed in Slack for review before publishing.\n\n## How it works\n- **1. Webhook \u2014 Fireflies Transcript Done** receives the meetingId from Fireflies when transcription completes\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 your Fireflies API key, Drive folder ID, Slack channel, author name, title, and company\n- **6. HTTP \u2014 Fetch Transcript** calls the Fireflies GraphQL API to get the full transcript with sentences, summaries, and sentiment\n- **7. Code \u2014 Process Transcript Data** extracts conversation text, pricing and task sentences, keywords, and meeting metadata\n- **8. IF \u2014 Transcript Ready?** checks if transcript data is available \u2014 not-ready transcripts exit cleanly\n- **10. AI Agent \u2014 Write LinkedIn Post** uses GPT-4o-mini to write a 180\u2013280 word LinkedIn post from real meeting insights\n- **12. Code \u2014 Build Doc and Slack Message** assembles the full Google Doc content and Slack preview\n- **13. Google Drive \u2014 Save LinkedIn Post** saves the post as a document to your Drive folder\n- **14. Slack \u2014 Send Post Preview** posts a 350-character preview to your Slack channel for review\n\n## Set up steps\n1. In **5. Set \u2014 Config Values** \u2014 replace YOUR_FIREFLIES_API_KEY, YOUR_GOOGLE_DRIVE_FOLDER_ID, Slack channel, author name, author title, and company name\n2. Activate the workflow and copy the webhook URL from node 1\n3. In Fireflies \u2014 go to Settings, Developer Settings, Webhooks, and paste the URL\n4. In **11. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n5. In **13. Google Drive \u2014 Save LinkedIn Post** \u2014 connect your Google Drive OAuth2 credential\n6. In **14. Slack \u2014 Send Post Preview** \u2014 connect your Slack OAuth2 credential and invite the bot to your channel"
      },
      "typeVersion": 1
    },
    {
      "id": "45267bbe-2310-4e10-be3b-31afaefb25cc",
      "name": "Section \u2014 Webhook Receipt and Validation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4368,
        -384
      ],
      "parameters": {
        "color": 5,
        "width": 804,
        "height": 900,
        "content": "## Webhook Receipt and Validation\nFireflies POSTs a meetingId here when transcription completes. A Code node safely extracts the meetingId from any payload structure. The IF node validates it \u2014 invalid webhooks exit cleanly via the Set node below."
      },
      "typeVersion": 1
    },
    {
      "id": "91a1814c-02a6-4636-99b3-07fcb69dc426",
      "name": "Section \u2014 Config, Transcript Fetch, and Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3536,
        -384
      ],
      "parameters": {
        "color": 6,
        "width": 916,
        "height": 884,
        "content": "## Config, Transcript Fetch, and Processing\nConfig stores all credentials and author details. Fireflies GraphQL API fetches the complete transcript. A Code node extracts sentences, ai_filter tags, keywords, sentiment, and metadata. A second IF gates on transcript availability."
      },
      "typeVersion": 1
    },
    {
      "id": "3be446ed-9260-41fd-b47c-5242190572e4",
      "name": "Section \u2014 AI LinkedIn Post Writing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2544,
        -400
      ],
      "parameters": {
        "color": 6,
        "width": 360,
        "height": 900,
        "content": "## AI LinkedIn Post Writing\nGPT-4o-mini (temperature 0.8) writes a 180\u2013280 word LinkedIn post using real transcript content. Structure: scroll-stopping hook, specific paragraph, 3\u20135 emoji learnings, closing question or CTA, hashtags, author sign-off."
      },
      "typeVersion": 1
    },
    {
      "id": "348e8b38-5ad2-4aae-a6a3-c58f87b67ee8",
      "name": "Section \u2014 Doc Assembly and Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2112,
        -400
      ],
      "parameters": {
        "color": 4,
        "width": 644,
        "height": 900,
        "content": "## Doc Assembly and Delivery\nBuilds a complete Google Doc with the post, meeting reference, keywords, and Fireflies link. Saved to Drive and previewed in Slack simultaneously for team review before publishing."
      },
      "typeVersion": 1
    },
    {
      "id": "23f2fa98-8166-49bc-b124-1589c215c695",
      "name": "1. Webhook \u2014 Fireflies Transcript Done",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -4320,
        -48
      ],
      "parameters": {
        "path": "fireflies-transcript-done",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1.1
    },
    {
      "id": "f4753deb-a752-4b7c-b772-fe9a2fed3d9d",
      "name": "2. Code \u2014 Extract Meeting ID",
      "type": "n8n-nodes-base.code",
      "position": [
        -4064,
        -48
      ],
      "parameters": {
        "jsCode": "// Safely extract meetingId from Fireflies webhook\n// Fireflies can send payload in different structures\nconst raw = $input.first().json;\n\n// Handle all possible payload structures\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  raw.data?.eventType ||\n  'Transcription completed';\n\nif (!meetingId) {\n  return [{\n    json: {\n      isValid: false,\n      error: 'No meetingId found in webhook payload',\n      rawPayload: JSON.stringify(raw).substring(0, 200)\n    }\n  }];\n}\n\nreturn [{\n  json: {\n    isValid: true,\n    meetingId: meetingId.trim(),\n    eventType\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a89b2910-8a67-456f-bc1f-c7865e3c76e8",
      "name": "3. IF \u2014 Valid Meeting ID?",
      "type": "n8n-nodes-base.if",
      "position": [
        -3840,
        -48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-valid",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.isValid }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b6ca83bf-18df-49da-b1b5-9495e92337e7",
      "name": "4. Set \u2014 Invalid Webhook Skip",
      "type": "n8n-nodes-base.set",
      "position": [
        -3776,
        288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "skip-001",
              "name": "result",
              "type": "string",
              "value": "Invalid webhook \u2014 no meetingId. Skipped."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d1382001-9c58-49f1-928b-1be64f9d7f22",
      "name": "5. Set \u2014 Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        -3472,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "firefliesApiKey",
              "type": "string",
              "value": "YOUR_FIREFLIES_API_KEY"
            },
            {
              "id": "cfg-002",
              "name": "googleDriveFolderId",
              "type": "string",
              "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID"
            },
            {
              "id": "cfg-003",
              "name": "slackChannel",
              "type": "string",
              "value": "#content-team"
            },
            {
              "id": "cfg-004",
              "name": "authorName",
              "type": "string",
              "value": "YOUR FULL NAME"
            },
            {
              "id": "cfg-005",
              "name": "authorTitle",
              "type": "string",
              "value": "YOUR JOB TITLE"
            },
            {
              "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": "c753e123-483c-4ee8-9600-ac1d96be0dba",
      "name": "6. HTTP \u2014 Fetch Transcript",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3264,
        -80
      ],
      "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 transcript_url sentences { speaker_name text ai_filters { task pricing question } } summary { keywords action_items overview gist bullet_gist } analytics { sentiments { positive_pct negative_pct } } } }\",\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": "06d91bbf-c85a-48fa-8555-3ec0068098eb",
      "name": "7. Code \u2014 Process Transcript Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -3040,
        -80
      ],
      "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 yet ready in Fireflies'\n    }\n  }];\n}\n\n// Build full conversation text from sentences\nconst sentences = transcript.sentences || [];\nlet fullText = '';\nconst taskLines = [];\nconst pricingLines = [];\nconst questionLines = [];\n\nsentences.forEach(s => {\n  const speaker = s.speaker_name || 'Speaker';\n  const text = (s.text || '').trim();\n  if (text) {\n    fullText += `${speaker}: ${text}\\n`;\n    if (s.ai_filters?.task && text.length > 15) taskLines.push(text);\n    if (s.ai_filters?.pricing && text.length > 15) pricingLines.push(text);\n    if (s.ai_filters?.question && text.length > 15) questionLines.push(text);\n  }\n});\n\n// Limit transcript text to 5000 chars for GPT token safety\nconst transcriptExcerpt = fullText.substring(0, 5000);\n\n// Summary fields from Fireflies\nconst summary = transcript.summary || {};\nconst keywords = (summary.keywords || []).slice(0, 12).join(', ') || 'None';\nconst actionItems = (summary.action_items || []).slice(0, 5).join(' | ') || 'None';\nconst overview = (summary.overview || '').substring(0, 800);\nconst gist = summary.gist || '';\nconst bulletPoints = (summary.bullet_gist || []).slice(0, 6).join('\\n') || '';\n\n// Date formatting\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 meetingTitle = transcript.title || 'Untitled Meeting';\nconst durationMin = Math.round((transcript.duration || 0) / 60);\nconst participants = (transcript.participants || []).join(', ') || 'Not listed';\nconst transcriptUrl = transcript.transcript_url || 'Not available';\n\nconst positivePct = Math.round(transcript.analytics?.sentiments?.positive_pct || 0);\nconst negativePct = Math.round(transcript.analytics?.sentiments?.negative_pct || 0);\n\nconst logDate = new Date().toISOString().replace('T', ' ').substring(0, 16);\nconst docTitle = `LinkedIn Post \u2014 ${meetingTitle} \u2014 ${meetingDate}`;\n\nreturn [{\n  json: {\n    hasData: true,\n    meetingId: transcript.id,\n    meetingTitle,\n    meetingDate,\n    durationMin,\n    participants,\n    transcriptUrl,\n    transcriptExcerpt,\n    keywords,\n    actionItems,\n    overview,\n    gist,\n    bulletPoints,\n    taskLines: taskLines.slice(0, 3).join(' | ') || 'None',\n    pricingLines: pricingLines.slice(0, 3).join(' | ') || 'None',\n    questionLines: questionLines.slice(0, 3).join(' | ') || 'None',\n    positivePct,\n    negativePct,\n    docTitle,\n    logDate,\n    authorName: config.authorName,\n    authorTitle: config.authorTitle,\n    companyName: config.companyName,\n    googleDriveFolderId: config.googleDriveFolderId,\n    slackChannel: config.slackChannel\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f49ba821-f034-4081-9a98-57c313f378c4",
      "name": "8. IF \u2014 Transcript Ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        -2816,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-has-data",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.hasData }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c142f426-9e9d-4c90-a819-9e63511495cd",
      "name": "9. Set \u2014 Transcript Not Ready Skip",
      "type": "n8n-nodes-base.set",
      "position": [
        -2800,
        224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "skip-002",
              "name": "result",
              "type": "string",
              "value": "=Transcript not ready for meetingId: {{ $json.meetingId }}. Skipped."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "55d411ad-9219-4c4d-865a-caf9968f9411",
      "name": "10. AI Agent \u2014 Write LinkedIn Post",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -2496,
        -112
      ],
      "parameters": {
        "text": "=You are a LinkedIn ghostwriter for {{ $json.authorName }}, {{ $json.authorTitle }} at {{ $json.companyName }}.\n\nWrite a LinkedIn post based on insights from a real business meeting or client call.\n\nMEETING CONTEXT:\nMeeting Title: {{ $json.meetingTitle }}\nDate: {{ $json.meetingDate }}\nDuration: {{ $json.durationMin }} minutes\nParticipants: {{ $json.participants }}\nCall Sentiment: {{ $json.positivePct }}% positive\n\nFIREFLIES SUMMARY:\nOverview: {{ $json.overview }}\nGist: {{ $json.gist }}\n\nKEY POINTS:\n{{ $json.bulletPoints }}\n\nKEYWORDS DISCUSSED: {{ $json.keywords }}\n\nACTION ITEMS FROM CALL: {{ $json.actionItems }}\n\nQUESTIONS RAISED IN CALL: {{ $json.questionLines }}\n\nTRANSCRIPT EXCERPT:\n{{ $json.transcriptExcerpt }}\n\nWRITE THE LINKEDIN POST NOW:\n\nFollow this exact structure:\n\nLINE 1: Strong hook. Surprising insight, bold statement, or counterintuitive lesson from this meeting. Must stop the scroll. Do NOT start with the word I or We. Maximum 12 words.\n\nLINE 2: Blank line.\n\nPARAGRAPH: 2 to 3 sentences expanding on the hook. Use first person as {{ $json.authorName }}. Be specific \u2014 reference real things from this meeting. Not generic advice.\n\nLINE BREAK.\n\n3 TO 5 KEY LEARNINGS: Each on its own line. Start each with a relevant emoji. Pull from real transcript content. Be specific, not generic.\n\nLINE BREAK.\n\nCLOSING: One sentence \u2014 either a thought-provoking question for the audience OR a call to action. Keep it conversational.\n\nLINE BREAK.\n\nHASHTAGS: 4 to 5 relevant hashtags on one line.\n\nLINE BREAK.\n\nSIGN OFF: \u2014 {{ $json.authorName }}, {{ $json.authorTitle }}\n\nRULES:\n- Total length 180 to 280 words\n- Plain text only \u2014 no asterisks, no markdown\n- Tone: human, professional, conversational \u2014 not corporate\n- Do NOT mention the meeting was recorded or transcribed\n- Do NOT fabricate any facts not present in the transcript\n- Write as if this is a genuine personal reflection",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "9f0c6bce-408b-4a72-98e7-8fbe7461a86e",
      "name": "11. OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2496,
        112
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 700,
          "temperature": 0.8
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "98faeed6-9f31-48ce-852c-aa0f8a12e96e",
      "name": "12. Code \u2014 Build Doc and Slack Message",
      "type": "n8n-nodes-base.code",
      "position": [
        -2064,
        -112
      ],
      "parameters": {
        "jsCode": "// Read AI output and prepare final fields for Drive + Slack\nconst aiPost = $input.first().json.output || '';\nconst data = $('7. Code \u2014 Process Transcript Data').item.json;\n\nif (!aiPost || aiPost.length < 50) {\n  return [{\n    json: {\n      linkedinPost: 'Post generation failed. Please check OpenAI credentials.',\n      docTitle: data.docTitle,\n      folderId: data.googleDriveFolderId,\n      slackChannel: data.slackChannel,\n      slackMessage: 'LinkedIn post generation failed for: ' + data.meetingTitle,\n      meetingTitle: data.meetingTitle,\n      meetingDate: data.meetingDate,\n      transcriptUrl: data.transcriptUrl\n    }\n  }];\n}\n\n// Full document content for Google Drive\nconst docContent =\n  'LINKEDIN POST DRAFT\\n' +\n  'Meeting: ' + data.meetingTitle + '\\n' +\n  'Date: ' + data.meetingDate + '\\n' +\n  'Author: ' + data.authorName + ', ' + data.authorTitle + '\\n' +\n  'Company: ' + data.companyName + '\\n' +\n  'Generated: ' + data.logDate + '\\n' +\n  '\\n' +\n  '============================================================\\n' +\n  'LINKEDIN POST \u2014 READY TO COPY AND PASTE\\n' +\n  '============================================================\\n' +\n  '\\n' +\n  aiPost +\n  '\\n\\n' +\n  '============================================================\\n' +\n  'MEETING REFERENCE\\n' +\n  '============================================================\\n' +\n  'Title: ' + data.meetingTitle + '\\n' +\n  'Date: ' + data.meetingDate + '\\n' +\n  'Duration: ' + data.durationMin + ' minutes\\n' +\n  'Participants: ' + data.participants + '\\n' +\n  'Fireflies Link: ' + data.transcriptUrl + '\\n' +\n  'Keywords: ' + data.keywords + '\\n' +\n  'Action Items: ' + data.actionItems + '\\n' +\n  '\\n' +\n  'Auto-generated by n8n + Fireflies.ai + GPT-4o-mini';\n\n// Slack preview \u2014 first 350 chars of post\nconst preview = aiPost.length > 350 ? aiPost.substring(0, 350) + '...' : aiPost;\n\nconst slackMessage =\n  '*New LinkedIn Post Draft Ready*\\n' +\n  '\\n' +\n  '*Meeting:* ' + data.meetingTitle + '\\n' +\n  '*Date:* ' + data.meetingDate + '   *Duration:* ' + data.durationMin + ' min\\n' +\n  '*Author:* ' + data.authorName + ', ' + data.authorTitle + '\\n' +\n  '\\n' +\n  '*POST PREVIEW:*\\n' +\n  preview +\n  '\\n\\n' +\n  '_Full post saved to Google Drive_\\n' +\n  '_Fireflies transcript: ' + data.transcriptUrl + '_';\n\nreturn [{\n  json: {\n    linkedinPost: aiPost,\n    docContent,\n    docTitle: data.docTitle,\n    folderId: data.googleDriveFolderId,\n    slackChannel: data.slackChannel,\n    slackMessage,\n    meetingTitle: data.meetingTitle,\n    meetingDate: data.meetingDate\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b4a8fec2-fe2f-4389-b37f-e7db1c811415",
      "name": "13. Google Drive \u2014 Save LinkedIn Post",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1728,
        -272
      ],
      "parameters": {
        "operation": "create"
      },
      "typeVersion": 3
    },
    {
      "id": "c87dfa34-f185-43db-85e2-d135a970dc17",
      "name": "14. Slack \u2014 Send Post Preview",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1728,
        64
      ],
      "parameters": {
        "text": "={{ $json.slackMessage }}",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2.2
    }
  ],
  "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
          }
        ]
      ]
    },
    "8. IF \u2014 Transcript Ready?": {
      "main": [
        [
          {
            "node": "10. AI Agent \u2014 Write LinkedIn Post",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "9. Set \u2014 Transcript Not Ready Skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. HTTP \u2014 Fetch Transcript": {
      "main": [
        [
          {
            "node": "7. Code \u2014 Process Transcript Data",
            "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 Write LinkedIn Post",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "7. Code \u2014 Process Transcript Data": {
      "main": [
        [
          {
            "node": "8. IF \u2014 Transcript Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10. AI Agent \u2014 Write LinkedIn Post": {
      "main": [
        [
          {
            "node": "12. Code \u2014 Build Doc and Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Webhook \u2014 Fireflies Transcript Done": {
      "main": [
        [
          {
            "node": "2. Code \u2014 Extract Meeting ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "12. Code \u2014 Build Doc and Slack Message": {
      "main": [
        [
          {
            "node": "13. Google Drive \u2014 Save LinkedIn Post",
            "type": "main",
            "index": 0
          },
          {
            "node": "14. Slack \u2014 Send Post Preview",
            "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

Connect Fireflies to this workflow once and every meeting you record becomes a LinkedIn post draft automatically. The moment Fireflies finishes transcribing a call, it fires a signal to the workflow — which fetches the full transcript, extracts real insights, and uses…

Source: https://n8n.io/workflows/15040/ — 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

[](https://www.youtube.com/watch?v=NAn5BSr15Ks) &gt; This workflow connects a Slack chatbot with AI agents and Google Sheets to automate candidate resume evaluation. It extracts resume details, identi

HTTP Request, Output Parser Structured, OpenAI Chat +6
AI & RAG

This workflow automates the entire process of taking a raw user-submitted script, rewriting it into a polished HeyGen-ready narration, generating a full avatar video, handling all processing checks, r

HTTP Request, Agent, Memory Buffer Window +6
AI & RAG

🧾 An intelligent automation system that turns Google Meet recordings into structured meeting notes — integrating Fireflies.ai, OpenAI GPT-4.1-mini, Notion, Slack, Google Drive, and Gmail via n8n.

Google Drive, OpenAI Chat, Output Parser Structured +8
AI & RAG

When a meeting ends in Fireflies, the transcript is automatically retrieved and sent to OpenAI for analysis. The AI evaluates objection handling, call effectiveness, and extracts key objections raised

HTTP Request, @Firefliesai/N8N Nodes Fireflies, OpenAI Chat +4
AI & RAG

Automate multilingual voice content creation by translating an English script into multiple languages and generating natural-sounding audio files using AI. 🌍🎙️ This workflow receives a script via webh

Item Lists, Google Drive, Agent +6