AutomationFlowsAI & RAG › Monitor Twitter Accounts & Generate Intelligence Summaries with Gemini AI &…

Monitor Twitter Accounts & Generate Intelligence Summaries with Gemini AI &…

Original n8n title: Monitor Twitter Accounts & Generate Intelligence Summaries with Gemini AI & Telegram

Byjellyfish @jellyfish on n8n.io

This workflow automates the process of monitoring Twitter accounts for intelligence gathering. It fetches new tweets from specified accounts via RSS, uses a powerful AI model (Google Gemini) to analyze the content based on your custom prompts, and sends formatted alerts to a…

Cron / scheduled trigger★★★★☆ complexityAI-powered18 nodesPostgresGoogle GeminiRSS Feed ReadTelegram
AI & RAG Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Googlegemini → Telegram 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
{
  "name": "Twitter Intelligence Analysis",
  "tags": [
    {
      "name": "Twitter"
    },
    {
      "name": "AI"
    },
    {
      "name": "Telegram"
    }
  ],
  "nodes": [
    {
      "id": "dd5e616a-9663-4c10-851b-758934fcb265",
      "name": "Filter New Tweets",
      "type": "n8n-nodes-base.filter",
      "position": [
        544,
        -464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a996252d-86f6-45c3-847a-be067263c565",
              "operator": {
                "type": "dateTime",
                "operation": "after"
              },
              "leftValue": "={{ $json.isoDate }}",
              "rightValue": "={{ $('Config').first().json.last_update_time }}"
            }
          ]
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "77aa830d-f4f5-41d0-9081-37ef8dfc21ac",
      "name": "Config",
      "type": "n8n-nodes-base.postgres",
      "position": [
        0,
        -464
      ],
      "parameters": {
        "query": "SELECT * FROM twitter_following_config WHERE id = 1;",
        "options": {},
        "operation": "executeQuery"
      },
      "retryOnFail": true,
      "typeVersion": 2.6,
      "alwaysOutputData": true
    },
    {
      "id": "d1675590-638c-43ea-bce8-64299c5c4433",
      "name": "Analyze Tweet with AI",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -208,
        208
      ],
      "parameters": {
        "text": "={{ $('Config').item.json.prompt }}\n\nHere is the [Input Tweet]\nTitle: {{ $json.title }}\nContent: {{ $json.content }}\nOriginal Link: {{ $json.link }}",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "resource": "document"
      },
      "typeVersion": 1
    },
    {
      "id": "dc4a7a05-fe01-46a1-811e-fa0532481ee2",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        -16,
        208
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Get the raw, deeply nested string output from the AI node\nconst aiRawOutput = $json.content.parts[0].text;\n\n// Use a regular expression to extract the JSON string part enclosed in ```\nconst jsonMatch = aiRawOutput.match(/\\{[\\s\\S]*\\}/);\n\n// Check if a JSON string was successfully found\nif (jsonMatch && jsonMatch[0]) {\n  try {\n    // Parse the extracted pure JSON string into a real JSON object\n    const parsedData = JSON.parse(jsonMatch[0]);\n    \n    // Return the parsed object as the output of this node\n    return {\n      json: parsedData\n    };\n  } catch (error) {\n    // If parsing fails, return an error message\n    return { json: { error: \"Failed to parse JSON\", details: error.message } };\n  }\n}\n\n// If no JSON string is found, also return an error message\nreturn { json: { error: \"JSON block not found in AI output\" } };"
      },
      "retryOnFail": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "b453644d-24be-4404-9869-97b3751df12c",
      "name": "Get Latest Timestamp",
      "type": "n8n-nodes-base.code",
      "position": [
        -144,
        -160
      ],
      "parameters": {
        "jsCode": "// Get all items passed from the previous node\nconst items = $input.all();\n\n// If there is no input data, return an empty array to stop the workflow here\nif (items.length === 0) {\n  return [];\n}\n\n// Use the reduce method to iterate through all items and find the latest date\n// We start with a very early date as the initial comparison value\nconst initialValue = { json: { isoDate: '1970-01-01T00:00:00.000Z' } };\n\nconst latestItem = items.reduce((latest, current) => {\n  // ISO format date strings can be compared directly\n  if (current.json.isoDate > latest.json.isoDate) {\n    return current;\n  } else {\n    return latest;\n  }\n}, initialValue);\n\n// Extract the isoDate from the found latest item\nconst latestTimestamp = latestItem.json.isoDate;\n\n// Return the result in the standard n8n format\n// This result can be easily used by subsequent nodes (like IF or Set nodes)\nreturn [\n  {\n    json: {\n      latestTimestamp: latestTimestamp\n    }\n  }\n];"
      },
      "retryOnFail": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "6a9e35db-ddff-400c-9b7b-ecc61f7ceff3",
      "name": "Update Latest Timestamp",
      "type": "n8n-nodes-base.postgres",
      "position": [
        160,
        -160
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "twitter_following_config",
          "cachedResultName": "twitter_following_config"
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public",
          "cachedResultName": "public"
        },
        "columns": {
          "value": {
            "id": "={{ $('Config').first().json.id }}",
            "last_update_time": "={{ $json.latestTimestamp }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "twitter_account",
              "type": "string",
              "display": true,
              "removed": true,
              "required": true,
              "displayName": "twitter_account",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_update_time",
              "type": "dateTime",
              "display": true,
              "required": false,
              "displayName": "last_update_time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "note",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "note",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.6
    },
    {
      "id": "d7b10e6f-bb4a-4833-bc1e-feb47c3b496c",
      "name": "Check if New Tweets Exist",
      "type": "n8n-nodes-base.if",
      "position": [
        -464,
        -144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fe59cf26-d6fe-4d67-b6d3-e868bc4dd75f",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$('Filter New Tweets').all()}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d837d13e-c9fd-4ecc-84d2-15aeeb2ebe3e",
      "name": "RSS",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        272,
        -464
      ],
      "parameters": {
        "url": "=[https://your-rsshub-instance.com/twitter/user/](https://your-rsshub-instance.com/twitter/user/){{ $json.twitter_account }}",
        "options": {}
      },
      "retryOnFail": true,
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "19e81953-f5fb-4e19-b71e-13b9827292db",
      "name": "Send Telegram Message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        352,
        208
      ],
      "parameters": {
        "text": "=\ud83d\udea8 Intelligence Level A\n\nTweet Analysis:\n{{ $json.summary }}\n\nKeywords: {{ $json.keywords.map(k => `#${k}`).join(' ') }}\n\nOriginal Link:\n{{ $json.link }}",
        "chatId": "YOUR_CHAT_ID",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4d5ac869-e761-4fd7-98af-67c5110ca967",
      "name": "Filter by Level",
      "type": "n8n-nodes-base.filter",
      "position": [
        176,
        208
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4be18a2a-4de2-422d-b5a0-875e63f925cc",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.level }}",
              "rightValue": "A"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fd215a22-c9fa-402a-ae0a-69617d3bbb8e",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -464,
        -464
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "33ef18d6-6c7e-40d7-9a95-f2e8e6c0a154",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -704
      ],
      "parameters": {
        "width": 208,
        "height": 400,
        "content": "## Trigger Setting\n\nSet the interval for automatic triggering (e.g., every 15 minutes)."
      },
      "typeVersion": 1
    },
    {
      "id": "931315cb-b601-4399-a417-bbb2c984aed7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -704
      ],
      "parameters": {
        "width": 448,
        "height": 400,
        "content": "## Read Config from Database\nA database table template might look like this:\n\n| id | twitter_account | last_update_time | prompt | note |\n| --- | --- | --- | --- | --- |\n| 1 | elonmusk | 2025-08-12 15:20:08+00 | Your AI prompt... | A note about this account |\n\n---\n\n- **id**: Primary key.\n- **twitter_account**: The Twitter handle to monitor (without the @).\n- **last_update_time**: The ISO Date of the last processed tweet.\n- **prompt**: The prompt for the AI to analyze the tweet.\n- **note**: A personal note for this entry."
      },
      "typeVersion": 1
    },
    {
      "id": "33d98bb3-2c42-4fbc-a5e4-e1eccf16f3e5",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -704
      ],
      "parameters": {
        "height": 400,
        "content": "## RSSHub Feed\n\nThis node fetches tweets via an RSS feed. You'll need your own RSSHub instance.\n\nFor more info on the URL format, check the official docs: [RSSHub Guide](https://docs.rsshub.app/routes/social-media#x-twitter)"
      },
      "typeVersion": 1
    },
    {
      "id": "020b6d79-bf6c-47c4-b74a-5e83ce3e4607",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        -704
      ],
      "parameters": {
        "height": 400,
        "content": "## Filter New Tweets\n\nFilters tweets to only include new ones based on their publication date (IsoDate).\n\nThis node only returns tweets with an IsoDate that is after the `last_update_time` retrieved from the Config node."
      },
      "typeVersion": 1
    },
    {
      "id": "029b9e0a-c4cf-4625-bbb5-2f87fe27191b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -256
      ],
      "parameters": {
        "width": 208,
        "height": 240,
        "content": "## IF Node\n\nChecks if the 'Filter New Tweets' node produced any output. If it's empty, the workflow stops. If not, it proceeds."
      },
      "typeVersion": 1
    },
    {
      "id": "8e71aa08-d0d2-4a16-a8ea-d466c0afc5a3",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -256
      ],
      "parameters": {
        "width": 592,
        "height": 240,
        "content": "Finds the latest timestamp among all new tweets and updates the timestamp in the database for the next run."
      },
      "typeVersion": 1
    },
    {
      "id": "7fb4a07f-0970-41f2-8203-bd996276fc8a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        32
      ],
      "parameters": {
        "width": 800,
        "height": 352,
        "content": "## Analysis Pipeline\n\n1.  **Analyze Tweet with AI**: Sends the tweet content and a prompt (from the Config node) to the AI for analysis.\n2.  **Parse AI Response**: Extracts the JSON object from the AI's text response.\n3.  **Filter by Level**: Filters the results based on the analysis (e.g., only proceed if `level` is 'A').\n4.  **Send Telegram Message**: Sends the final, formatted analysis to a Telegram chat."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "RSS": {
      "main": [
        [
          {
            "node": "Filter New Tweets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "RSS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter by Level": {
      "main": [
        [
          {
            "node": "Send Telegram Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter New Tweets": {
      "main": [
        [
          {
            "node": "Check if New Tweets Exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Filter by Level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Latest Timestamp": {
      "main": [
        [
          {
            "node": "Update Latest Timestamp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Tweet with AI": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if New Tweets Exist": {
      "main": [
        [
          {
            "node": "Get Latest Timestamp",
            "type": "main",
            "index": 0
          },
          {
            "node": "Analyze Tweet with AI",
            "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 automates the process of monitoring Twitter accounts for intelligence gathering. It fetches new tweets from specified accounts via RSS, uses a powerful AI model (Google Gemini) to analyze the content based on your custom prompts, and sends formatted alerts to a…

Source: https://n8n.io/workflows/7316/ — 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 creates a daily “n8n News Radar” briefing: Pulls the latest n8n ecosystem updates from Blog, Community, GitHub Releases, and Reddit. Filters to the last 24 hours + keyword relevance. Use

Telegram, Notion, Google Gemini +2
AI & RAG

Start your day with a personalized news podcast delivered directly to your Telegram. This workflow helps you stay informed without scrolling through endless feeds. It automatically collects news from

RSS Feed Read, YouTube, Google Gemini +2
AI & RAG

This template watches an external documentation site every day and sends an AI-generated Vietnamese summary to Telegram whenever pages change. It is built around Postgres content hashing so it works w

N8N Nodes Firecrawl V2, Postgres, Google Gemini +1
AI & RAG

AI Institutional Stock Valuation Engine with Risk Scoring & Scenario Targets

Google Sheets, XML, HTTP Request +3
AI & RAG

Overview This is a production-grade, fully automated stock analysis system built entirely in n8n. It combines institutional-level financial analysis, dual AI model consensus, and a self-improving back

Google Sheets, XML, HTTP Request +3