AutomationFlowsAI & RAG › RSS to GPT-4o Content for Medium, LinkedIn & Instagram

RSS to GPT-4o Content for Medium, LinkedIn & Instagram

Original n8n title: Transform RSS Feeds Into Content with Gpt-4o for Medium, Linkedin & Instagram

ByCodint @codint on n8n.io

This workflow automatically collects news from an RSS feed, identifies the most relevant article(s), and generates ready-to-use social media and blog content tailored for Medium, LinkedIn, and Instagram.

Cron / scheduled trigger★★★★☆ complexityAI-powered18 nodesRSS Feed ReadAgentGmailOpenAI Chat
AI & RAG Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Gmail 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": {
    "site": "https://github.com/zengfr/n8n-workflow-all-templates",
    "name": "Transform RSS Feeds into Content with GPT-4o for Medium, LinkedIn & Instagram",
    "wechat": "youandme10086",
    "id": 8662,
    "update_time": "2025-11-10"
  },
  "nodes": [
    {
      "id": "9555c563-50bc-4436-85c2-ccdb5f3e6eb1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1824,
        448
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "daysInterval": 3,
              "triggerAtHour": 8,
              "triggerAtMinute": 30
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "148255b0-ce9f-4405-801a-07016392b648",
      "name": "RSS Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -1664,
        448
      ],
      "parameters": {
        "url": "https://aibusiness.com/rss.xml",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "bb39c72b-cdfa-42d4-965e-e8e7beefb42b",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1520,
        448
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "title"
            },
            {
              "fieldToAggregate": "content"
            },
            {
              "fieldToAggregate": "link"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "34a251d2-8c03-4238-943e-8720f04c8827",
      "name": "Best Article finder",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1168,
        352
      ],
      "parameters": {
        "text": "=I want you to analyze the following for my company. Find me the best articles to use in my medium post. My company is about AI Agents & Automation. Pick up to 3. Reply ONLY with a comma-separated list of the IDs (e.g., 3,7,12).\n\n{{ $json.forAI }}\n\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0b9a9c24-44f1-41c6-a410-02822552be45",
      "name": "Tone of voice content writer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -224,
        448
      ],
      "parameters": {
        "text": "=Maak een medium post gebaseerd op de volgende artiekelen.\n\n{{ $json.links }}",
        "options": {
          "systemMessage": "Jij bent de content creator voor Codint, een AI-automation & agents studio die bedrijven helpt slimmer, sneller en effici\u00ebnter te werken.\nGebruik altijd de Codint tone of voice:\n- Professioneel, innovatief en menselijk\n- Korte, duidelijke en actieve zinnen\n- Direct de lezer aanspreken (\u201cjij\u201d, \u201cje bedrijf\u201d)\n- Technische termen simpel uitleggen met voorbeelden of metaforen\n- Positief en toekomstgericht schrijven\n- Eindig vaak met een vraag of call-to-action\n- Gebruik empathische en resultaatgerichte taal (focus: tijd besparen, groei, eenvoud)\n- Link het altijd weer terug aan codint. Codint biedt een gratis AI consult."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "500541c4-a5b1-4478-adae-45e7dc4c547f",
      "name": "Send Content Confirmation1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        112,
        448
      ],
      "parameters": {
        "sendTo": "alperaksakal2006@gmail.com",
        "message": "={{ $json.output }}",
        "options": {},
        "subject": "Je nieuwe medium post is hier!"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "f4b1a45e-5dca-4075-beea-f3c6c437deb8",
      "name": "Instagram & Linkedin Writer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -224,
        752
      ],
      "parameters": {
        "text": "=Het volgende is gepost op ons medium platform:\n{{ $('Tone of voice content writer').item.json.output }}\n\nIk wil dat je dit als basis gebruikt, voor een post op zowel LinkedIn als Instagram.\nOutput alleen de content. Gebruik het volgende structuur:\n\nLinkedin:\n[content]\n\n\nInstagram:\n[content]",
        "options": {
          "systemMessage": "Jij bent de content creator voor Codint, een AI-automation & agents studio die bedrijven helpt slimmer, sneller en effici\u00ebnter te werken.\n\nGebruik altijd de Codint tone of voice:\n- Professioneel, innovatief en menselijk\n- Korte, duidelijke en actieve zinnen\n- Direct de lezer aanspreken (\u201cjij\u201d, \u201cje bedrijf\u201d)\n- Technische termen simpel uitleggen met voorbeelden of metaforen\n- Positief en toekomstgericht schrijven\n- Eindig vaak met een vraag of call-to-action\n- Gebruik empathische en resultaatgerichte taal (focus: tijd besparen, groei, eenvoud)\n- Link het altijd weer terug aan codint. Codint biedt een gratis AI consult.\n\nPas je stijl aan per platform:\n - Instagram: luchtig, visueel, kort\n- LinkedIn: zakelijk, thought-leadership, case studies"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "4081e060-c922-4f46-a218-35678e612a54",
      "name": "Send Content Confirmation",
      "type": "n8n-nodes-base.gmail",
      "position": [
        128,
        752
      ],
      "parameters": {
        "sendTo": "alperaksakal2006@gmail.com",
        "message": "={{ $json.output }}",
        "options": {},
        "subject": "Linkedn & Instagram content!"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "638df899-1ccf-4c8e-8088-afc2dd83a28e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        352
      ],
      "parameters": {
        "width": 464,
        "height": 288,
        "content": "# Collecting the news"
      },
      "typeVersion": 1
    },
    {
      "id": "071816ae-8999-42b1-9979-f46a20365c88",
      "name": "group the news into 1 item",
      "type": "n8n-nodes-base.code",
      "position": [
        -1360,
        448
      ],
      "parameters": {
        "jsCode": "// Inputs expected from Aggregate/RSS: arrays: title[], content[], link[]\nconst all = items[0].json;              // aggregated item\nconst titles = all.title || [];\nconst contents = all.content || [];\nconst links = all.link || [];\n\nconst articles = [];\nconst lines = [];\n\nconst maxLen = Math.max(titles.length, contents.length, links.length);\nfor (let i = 0; i < maxLen; i++) {\n  const obj = {\n    id: i + 1,                          // stable ID (1..N). Use guid if you have one.\n    title: titles[i] ?? \"\",\n    content: contents[i] ?? \"\",\n    link: links[i] ?? \"\"\n  };\n  articles.push(obj);\n  // Short preview for the AI to choose from:\n  const preview = (obj.content || \"\").replace(/\\s+/g, \" \").slice(0, 220);\n  lines.push(`${obj.id}. ${obj.title}\\n${preview}${preview.length === 220 ? \"\u2026\" : \"\"}`);\n}\n\nreturn [\n  {\n    json: {\n      articles,                         // keep the structured mapping\n      forAI: lines.join(\"\\n\\n\")         // human-readable list for the model\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "5b1f10ad-0f0f-448b-bb8d-406cf34f1185",
      "name": "Find the urls the ai outputted",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        448
      ],
      "parameters": {
        "jsCode": "// Code node \u2014 Run Once for All Items\n\n// 1) Read AI output text (your AI Agent uses `output`)\nlet aiText =\n  (items[0]?.json?.output ??\n   items[0]?.json?.result ??\n   items[0]?.json?.text ??\n   items[0]?.json?.response ??\n   \"\").toString().trim();\n\n// Fallback: read directly from the AI Agent node by name if not passed through\nif (!aiText) {\n  const ai = $items(\"Best Article finder\", 0, 0);   // <-- change to your AI node name if different\n  if (Array.isArray(ai) && ai.length) {\n    aiText = (ai[0].json.output ?? ai[0].json.result ?? ai[0].json.text ?? \"\").toString().trim();\n  }\n}\n\nif (!aiText) {\n  throw new Error(\"AI output is empty. Make sure the AI Agent node's field name is 'output' (or adjust above).\");\n}\n\n// 2) Get articles array from builder node\nlet articles = items[0]?.json?.articles;\nif (!articles) {\n  const built = $items(\"group the news into 1 item\", 0, 0);   // <-- change \"Code1\" to your builder node name\n  if (Array.isArray(built) && built.length) {\n    articles = built[0]?.json?.articles;\n  }\n}\nif (!Array.isArray(articles)) {\n  throw new Error(\"Couldn't find 'articles' array. Ensure the builder node outputs { json: { articles: [...] } }.\");\n}\n\n// 3) Extract numeric IDs (handles commas, spaces, newlines, bullets)\nconst ids = (aiText.match(/\\d+/g) || []).map(n => parseInt(n, 10));\n\n// 4) Map IDs \u2192 full article objects\nconst chosen = ids\n  .map(id => articles.find(a => a.id === id))\n  .filter(Boolean);\n\n// 5) Return one item with arrays\nreturn [{\n  json: {\n    raw: aiText,\n    ids,                                  // e.g., [2,18,45]\n    chosen,                                // [{id, title, content, link}, ...]\n    titles: chosen.map(c => c.title),\n    links: chosen.map(c => c.link)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "0a704f1d-c487-44fc-a4a6-2973de992521",
      "name": "All url's to 1 string",
      "type": "n8n-nodes-base.code",
      "position": [
        -432,
        448
      ],
      "parameters": {
        "jsCode": "// Code node \u2014 Run Once for All Items\n\n// Collect all links from input items\nconst links = [];\nfor (const item of $input.all()) {\n  if (item.json.link) {\n    links.push(item.json.link);\n  }\n  // if articles are inside \"chosen\" array:\n  if (Array.isArray(item.json.chosen)) {\n    for (const c of item.json.chosen) {\n      if (c.link) links.push(c.link);\n    }\n  }\n}\n\n// Return as one item with all links\nreturn [\n  {\n    json: {\n      links,                          // array of links\n      linksString: links.join(\"\\n\")   // optional: single string\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "08664bf9-7b56-4c33-897e-76285e664224",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        240
      ],
      "parameters": {
        "width": 848,
        "height": 720,
        "content": "# Generate content based on the news for Medium, Linkedin & Instagram\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b5ec2230-dba8-417d-980c-417e6d4788e7",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1840,
        -176
      ],
      "parameters": {
        "width": 1984,
        "height": 352,
        "content": "# This automation is made by Codint\n\nHow to use this workflow?\n1. Update the RSS feed node, to a relevant news source \n2. Change the prompt in the Best article finder to tailor for you company. Do this by using AI for an even better result.\n3. Use an AI to change the system-prompts in the content generators. Make sure to include a tone of voice here!\n4. Update where the emails are being send.\n\n\nPotential improvements and why it isn't included:\n- You could add a loop after sending the mail, so that the user can accept, change or cancel the post. We have decided to not do this to save cost, since you can create a similar gpt and update it in there for free.\n- Automatically post the contents,  AI can make mistakes a human in the loop is always valuable\n- More and other platforms to post on\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6adbd885-701a-4fde-82eb-b3ef528eaf35",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3200,
        304
      ],
      "parameters": {
        "width": 1296,
        "height": 416,
        "content": "# \ud83d\udcf0 Related News to Content Marketing\n\nThis workflow collects news from an RSS feed, finds the best article, and generates shareable content for Medium, LinkedIn, and Instagram using OpenAI. Drafts are sent to your email for review before posting.\n\n## Quick Setup\n\t1.\tRSS Feed \u2192 Update the RSS Read node with your preferred news source(s).\n\t2.\tOpenAI \u2192 Add your API key in the Chat Model node and adjust prompts if needed.\n\t3.\tEmail \u2192 Connect Gmail (or another service) in the Send Content Confirmation nodes and change mail to your personal mail\n\t4.\tRun \u2192 Test manually, then enable the Schedule Trigger for automation.\n\n## \u2705 Perfect for marketers, social media managers, and creators who want consistent, AI-powered content."
      },
      "typeVersion": 1
    },
    {
      "id": "33de8be9-86ec-4b50-9529-435bf4f182fe",
      "name": "4o-mini",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -1072,
        768
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c7e77239-65b0-4286-bb25-f6516aac9739",
      "name": "4.1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -432,
        688
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "gpt-4.1"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "489ccfa3-f539-4948-a50e-b02e55636cd8",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -816,
        448
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    }
  ],
  "connections": {
    "4.1": {
      "ai_languageModel": [
        [
          {
            "node": "Tone of voice content writer",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Instagram & Linkedin Writer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Find the urls the ai outputted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4o-mini": {
      "ai_languageModel": [
        [
          {
            "node": "Best Article finder",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "RSS Read": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "group the news into 1 item",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "RSS Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Best Article finder": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "All url's to 1 string": {
      "main": [
        [
          {
            "node": "Tone of voice content writer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Content Confirmation1": {
      "main": [
        [
          {
            "node": "Instagram & Linkedin Writer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "group the news into 1 item": {
      "main": [
        [
          {
            "node": "Best Article finder",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Instagram & Linkedin Writer": {
      "main": [
        [
          {
            "node": "Send Content Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tone of voice content writer": {
      "main": [
        [
          {
            "node": "Send Content Confirmation1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find the urls the ai outputted": {
      "main": [
        [
          {
            "node": "All url's to 1 string",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow automatically collects news from an RSS feed, identifies the most relevant article(s), and generates ready-to-use social media and blog content tailored for Medium, LinkedIn, and Instagram.

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

V2 (2026) available! An intelligent, fully automated news aggregation system that collects articles from multiple sources (RSS feeds + Google Search), uses AI to classify and summarize the most import

N8N Nodes Serpapi, Text Classifier, Output Parser Structured +6
AI & RAG

My workflow 14. Uses rssFeedRead, chainLlm, lmChatOpenAi, openWeatherMap. Scheduled trigger; 40 nodes.

RSS Feed Read, Chain Llm, OpenAI Chat +6
AI & RAG

This workflow automates the process of generating, reviewing, and publishing blog posts across multiple platforms, now enhanced with support for RSS Feeds as a content source. It streamlines the manag

HTTP Request, Html Extract, RSS Feed Read +9
AI & RAG

Tags: ESL, English Learning, Podcasts, RSS, AI Exercises, ElevenLabs

Agent, Gmail, RSS Feed Read +4
AI & RAG

This n8n workflow automatically fetches RSS articles, extracts featured images, and publishes them across multiple social media platforms. The workflow runs on a schedule, processes news articles from

WordPress, Edit Image, HTTP Request +9