AutomationFlowsAI & RAG › Curate Learning Content From Reddit & RSS with Gpt-4.1-mini and Google Sheets

Curate Learning Content From Reddit & RSS with Gpt-4.1-mini and Google Sheets

Byhigashiyama @kazushi on n8n.io

This workflow is for learners, educators, and professionals who want to automatically collect and filter the most relevant educational articles, tutorials, and resources based on specific keywords. Fetches content from RSS feeds and Reddit based on user-defined keywords. AI…

Cron / scheduled trigger★★★★☆ complexityAI-powered18 nodesGoogle SheetsRSS Feed ReadAgentOpenAI ChatHTTP Request
AI & RAG Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Google Sheets 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
{
  "id": "SPMdOPACsv0whzC1",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Personalized Learning Content Aggregator with AI Filtering",
  "tags": [],
  "nodes": [
    {
      "id": "530285ce-4719-441a-9027-a5a1f55454f8",
      "name": "Schedule Trigger - Twice Daily",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        144,
        272
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            },
            {
              "triggerAtHour": 18
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "01138c7e-b68b-4772-bb47-ff096170fad2",
      "name": "Workflow Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        368,
        272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-2",
              "name": "rssFeeds",
              "type": "string",
              "value": "<__PLACEHOLDER_VALUE__Comma-separated RSS feed URLs to monitor__>"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "f752f79f-3242-49bd-9ad9-536aadf3ecda",
      "name": "Get Keywords from Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        592,
        272
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE/edit#gid=0",
          "cachedResultName": "\u30b7\u30fc\u30c81"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE/edit?usp=drivesdk",
          "cachedResultName": "\u7121\u984c\u306e\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "bf214976-ba37-435f-8191-1d6af7ed0159",
      "name": "Loop Over Keywords",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        272
      ],
      "parameters": {
        "jsCode": "const keywords = $input.all().map(item => item.json);\nconst outputs = [];\n\nfor (const row of keywords) {\n  let keyword = row.keyword || row.Keyword || Object.values(row)[0];\n\n  // \u6587\u5b57\u5217\u3067\u306a\u3044\u5834\u5408\u306e\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\n  if (typeof keyword === 'object' && keyword !== null) {\n    keyword = Object.values(keyword)[0];\n  }\n\n  if (typeof keyword === 'string' && keyword.trim()) {\n    outputs.push({ json: { keyword: keyword.trim() } });\n  }\n}\n\nreturn outputs;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "91891a18-73a3-4582-af3f-a932483dd8e2",
      "name": "Search RSS Feeds",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        1040,
        80
      ],
      "parameters": {
        "url": "={{ $('Workflow Configuration').first().json.rssFeeds.split(',')[0] }}",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "fa1e5bad-c831-42d8-a246-a694b5ff11f4",
      "name": "Merge All Search Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        1264,
        176
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "7b189ca5-cd33-42fb-a415-6573cba65dd8",
      "name": "Prepare Articles for AI",
      "type": "n8n-nodes-base.code",
      "position": [
        1488,
        176
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst articles = [];\n\nfor (const item of items) {\n  const data = item.json;\n  \n  // Handle Reddit API response format (data.children array)\n  if (data.data && data.data.children && Array.isArray(data.data.children)) {\n    for (const child of data.data.children) {\n      const post = child.data;\n      let article = {\n        title: post.title || 'No title',\n        url: post.url || `https://reddit.com${post.permalink}` || '',\n        description: post.selftext || post.title || '',\n        source: 'Reddit',\n        publishedAt: post.created_utc ? new Date(post.created_utc * 1000).toISOString() : new Date().toISOString()\n      };\n      articles.push(article);\n    }\n  }\n  // Handle individual Reddit post format\n  else if (data.subreddit || data.permalink) {\n    let article = {\n      title: data.title || data.name || 'No title',\n      url: data.url || data.permalink || '',\n      description: data.selftext || data.text || data.title || '',\n      source: 'Reddit',\n      publishedAt: data.created_utc ? new Date(data.created_utc * 1000).toISOString() : new Date().toISOString()\n    };\n    articles.push(article);\n  }\n  // Handle Twitter format\n  else if (data.author_id || data.tweet_id) {\n    let article = {\n      title: data.text ? data.text.substring(0, 100) : 'No title',\n      url: data.url || '',\n      description: data.text || data.content || '',\n      source: 'Twitter',\n      publishedAt: data.created_at || new Date().toISOString()\n    };\n    articles.push(article);\n  }\n  // Handle RSS format\n  else {\n    let article = {\n      title: data.title || data.name || 'No title',\n      url: data.url || data.link || '',\n      description: data.description || data.content || '',\n      source: 'RSS',\n      publishedAt: data.pubDate || data.published || new Date().toISOString()\n    };\n    articles.push(article);\n  }\n}\n\nconst articlesText = articles.map((a, i) => \n  `Article ${i + 1}:\\nTitle: ${a.title}\\nURL: ${a.url}\\nDescription: ${a.description.substring(0, 300)}...\\nSource: ${a.source}\\n`\n).join('\\n---\\n');\n\nreturn [{ json: { articles, articlesText, keyword: $('Loop Over Keywords').first().json.keyword } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "04657aeb-6396-46a1-8457-174cbd5380d6",
      "name": "AI Content Filter",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1712,
        176
      ],
      "parameters": {
        "text": "=You are a content curator for personalized learning. Your task is to analyze articles and select only those that are:\n1. Highly relevant to the keyword: {{ $json.keyword }}\n2. Contain NEW and valuable information (tutorials, new features, announcements, guides)\n3. NOT promotional content, spam, or low-quality posts\n\nHere are the articles to analyze:\n\n{{ $json.articlesText }}\n\nRespond with a JSON array containing only the article numbers (1, 2, 3, etc.) that meet the criteria. Example: [1, 3, 5]\nIf no articles meet the criteria, respond with an empty array: []\n\nOnly return the JSON array, nothing else",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "047ef445-5190-4a41-83cc-535cc0419149",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2064,
        176
      ],
      "parameters": {
        "jsCode": "const aiResponse = $json.output;\nconst articles = $('Prepare Articles for AI').first().json.articles;\n\nlet selectedIndices = [];\ntry {\n  // Try to parse the AI response as JSON\n  const match = aiResponse.match(/\\[(.*?)\\]/s);\n  if (match) {\n    selectedIndices = JSON.parse('[' + match[1] + ']');\n  }\n} catch (error) {\n  console.log('Failed to parse AI response:', error);\n  return [];\n}\n\nconst selectedArticles = selectedIndices\n  .map(index => articles[index - 1])\n  .filter(article => article !== undefined);\n\nreturn selectedArticles.map(article => ({ json: article }));"
      },
      "typeVersion": 2
    },
    {
      "id": "ccc0797d-0636-4027-98e0-6aae1e8ecb58",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1792,
        400
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "8c4b9ba8-1478-4a8a-96fc-93971fd97d7b",
      "name": "Search Reddit via API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1040,
        272
      ],
      "parameters": {
        "url": "https://www.reddit.com/search.json",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.keyword }}"
            },
            {
              "name": "limit",
              "value": "10"
            },
            {
              "name": "sort",
              "value": "relevance"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "578fc36c-a9d8-4893-821d-7cbb04a6174d",
      "name": "Save to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2288,
        176
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $json.url }}",
            "Title": "={{ $json.title }}",
            "Source": "={{ $json.source }}",
            "Added Date": "={{ $now.toISO() }}",
            "Description": "={{ $json.description }}"
          },
          "schema": [
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Title",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Source",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Added Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Added Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Title"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1891354699,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE/edit#gid=1891354699",
          "cachedResultName": "\u30b7\u30fc\u30c83"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1e7dTOI3g-SEmv2unfMTrmzuLllb5TBY6IXajPjZ1RmE/edit?usp=drivesdk",
          "cachedResultName": "\u7121\u984c\u306e\u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "846c183a-c784-4ca2-bc85-78503934df11",
      "name": "Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        64
      ],
      "parameters": {
        "width": 560,
        "height": 896,
        "content": "## Personalized Learning Content Aggregator with AI Filtering\n\n### Who\u2019s it for\nThis workflow is for learners, educators, and professionals who want to automatically collect and filter the most relevant educational articles, tutorials, and resources based on specific keywords.\n\n### How it works\n- Fetches content from RSS feeds and Reddit based on user-defined keywords.\n- AI analyzes and filters the articles to keep only **relevant, educational, and non-promotional** posts.\n- Saves curated results into a Google Sheet for easy review.\n\n### How to set up\n1. Connect your **Google Sheets** and **AI** (OpenAI or LangChain) credentials.\n2. Add your RSS feed URLs and keywords to Google Sheets.\n3. Adjust schedule timing in the trigger node (default: 8 AM & 6 PM daily).\n4. Run the workflow and check the results in your Google Sheet.\n\n### Requirements\n- Google Sheets account for storage.\n- RSS feed URLs and keyword list.\n- AI node (OpenAI / Gemini / Claude) for filtering logic.\n\n### How to customize\n- Change or add new content sources (e.g., YouTube, Medium, Dev.to).\n- Adjust AI prompt criteria to match your learning goals.\n- Save results to other platforms (e.g., Notion, Slack, or Airtable).\n\n**Note:** This workflow uses no personal identifiers or API keys directly in nodes. All credentials are safely stored in n8n\u2019s credential manager."
      },
      "typeVersion": 1
    },
    {
      "id": "57735186-ac1c-45cb-a685-1fa0aba45fc5",
      "name": "Configuration Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        176
      ],
      "parameters": {
        "content": "Holds the RSS feed URLs and user-defined keywords from Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "50c96cef-b37c-44fa-930a-bafbb2f1b0f9",
      "name": "Fetch Reddit Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        464
      ],
      "parameters": {
        "height": 128,
        "content": "Fetches learning-related posts from Reddit via public API based on keywords."
      },
      "typeVersion": 1
    },
    {
      "id": "461e1737-57fa-4116-a0c9-83d5c02136ff",
      "name": "Merge Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        48
      ],
      "parameters": {
        "content": "Combines results from all content sources (RSS + Reddit) for unified AI filtering."
      },
      "typeVersion": 1
    },
    {
      "id": "85ed87bf-4ecf-4ceb-9cdd-6d66712b1ccf",
      "name": "AI Filter Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        16
      ],
      "parameters": {
        "content": "AI analyzes articles and keeps only high-quality, relevant educational content."
      },
      "typeVersion": 1
    },
    {
      "id": "3cc34535-4907-4957-92fa-11ae789bdcec",
      "name": "Save Results Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2208,
        32
      ],
      "parameters": {
        "content": "Saves the final curated articles to your connected Google Sheet automatically."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "efbba744-6c3b-4fd9-b47b-f5e3b08a8256",
  "connections": {
    "Search RSS Feeds": {
      "main": [
        [
          {
            "node": "Merge All Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Content Filter": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Content Filter",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Save to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Keywords": {
      "main": [
        [
          {
            "node": "Search RSS Feeds",
            "type": "main",
            "index": 0
          },
          {
            "node": "Search Reddit via API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Reddit via API": {
      "main": [
        [
          {
            "node": "Merge All Search Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Workflow Configuration": {
      "main": [
        [
          {
            "node": "Get Keywords from Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Articles for AI": {
      "main": [
        [
          {
            "node": "AI Content Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Search Results": {
      "main": [
        [
          {
            "node": "Prepare Articles for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger - Twice Daily": {
      "main": [
        [
          {
            "node": "Workflow Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Keywords from Google Sheets": {
      "main": [
        [
          {
            "node": "Loop Over Keywords",
            "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

This workflow is for learners, educators, and professionals who want to automatically collect and filter the most relevant educational articles, tutorials, and resources based on specific keywords. Fetches content from RSS feeds and Reddit based on user-defined keywords. AI…

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

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

This automated disaster response workflow streamlines emergency management by monitoring multiple alert sources and coordinating property protection teams. Designed for property managers, insurance co

Google Sheets, Google Calendar, Gmail +4
AI & RAG

We’ve released Version 4 of our AI Powered Blog Automation workflow. We heard your complains and made a complete redesign built for serious content creators.

RSS Feed Read, OpenAI Chat, Text Classifier +6
AI & RAG

This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform

Agent, OpenAI Chat, Airtable Tool +7
AI & RAG

This workflow is designed for: Content creators and marketers E-commerce and product-based businesses Agencies producing social media visuals and videos Automation builders looking for AI-powered crea

HTTP Request, Edit Image, Google Drive +7