AutomationFlowsAI & RAG › Automate Twitter Posting with Gpt-4 Content Generation & Google Sheets Tracking

Automate Twitter Posting with Gpt-4 Content Generation & Google Sheets Tracking

ByIntuz @intuz on n8n.io

This workflow uses an AI agent to intelligently generate unique, high-quality content, check for duplicates, and post it on a consistent schedule to automate your entire Twitter presence. Social Media Managers Marketing Teams & Agencies Startup Founders & Solopreneurs Content…

Cron / scheduled trigger★★★★☆ complexityAI-powered18 nodesAgentOpenAI ChatMemory Buffer WindowTwitterGoogle Sheets ToolGoogle Sheets
AI & RAG Trigger: Cron / scheduled Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #8010 — 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": "i8ATrlawNnV9FGIV",
  "name": "Automate Social Media Posting on Twitter (x.com) using AI Agent & Google Sheets",
  "tags": [],
  "nodes": [
    {
      "id": "185ffe75-df92-4137-a4a2-985e9d4c4359",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        640,
        832
      ],
      "parameters": {
        "text": "=You are an expert social media manager for Intuz's Twitter account. Generate engaging tweets for C-suite executives, CTOs, and engineering leaders.\n\n\ud83d\udea8 ABSOLUTE CHARACTER LIMIT: 250 CHARACTERS MAXIMUM (including ALL text, spaces, hashtags, URLs)\n\nMANDATORY PROCESS:\n1. Draft tweet\n2. Count EVERY character (letters, spaces, punctuation, hashtags, URLs)\n3. If >250 characters: Shorten immediately\n4. Recount until \u2264250 characters\n5. Never exceed 250 under any circumstances\n6. Check for existing same tweets from the Google Sheet, so as to avoid duplicate tweets\n\nOUTPUT FORMAT:\n{\n\"tweet_content\": \"[Your tweet here - max 280 chars]\",\n\"character_count\": \"[X/280]\",\n\"status\": \"Published\"\n}\n\nCONTENT FOCUS: AI trends, automation, cloud tech, RAG, ML innovations, MCP, n8n, Software Development\n\nREQUIREMENTS:\n- Always include #Intuz\n- Add 4-7 relevant hashtags\n- Include URL for https://www.mlopscrew.com/ if the tweet is cloud related otherwise add https://www.intuz.com/\n- Ask questions or add CTAs\n- Make each tweet unique\n- Keep tone: innovative, authoritative, educational\n\nCHARACTER BUDGET:\n- Core message: ~150-180 chars\n- Hashtags: ~40-60 chars\n- URL: ~20-30 chars\n- TOTAL: \u2264250 chars\n\nTARGET: Drive leads, engagement, \"Contact Us\" inquiries\n\nFINAL CHECK: Confirm character count \u2264280 before submitting!",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "fc8d5d4f-bb1b-4645-8301-d9f08f2d00a6",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        400,
        1248
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "gpt-4.1-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "a768abfb-aa5a-4363-b942-eee38f5deeff",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        736,
        1728
      ],
      "parameters": {
        "sessionKey": "TWEETS",
        "sessionIdType": "customKey",
        "contextWindowLength": 15
      },
      "typeVersion": 1.3
    },
    {
      "id": "68527ad0-d27f-42aa-bf28-36a8e4f86b84",
      "name": "Create Tweet",
      "type": "n8n-nodes-base.twitter",
      "position": [
        2256,
        992
      ],
      "parameters": {
        "text": "={{ $json.tweet_content }}",
        "additionalFields": {}
      },
      "typeVersion": 2
    },
    {
      "id": "0efc1811-933f-4765-838d-48d48c4e231d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        1168
      ],
      "parameters": {
        "width": 464,
        "height": 272,
        "content": "### Step 1: Scheduler Trigger  \nThis node acts as the workflow\u2019s timer \u23f1\ufe0f.  \nIt is configured to automatically trigger the workflow every **6 hours**, ensuring that new tweet content is generated and posted consistently without requiring manual input.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1f98869b-5a49-4e0b-97c2-beac42127f00",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        672
      ],
      "parameters": {
        "color": 5,
        "width": 560,
        "height": 352,
        "content": "### Step 2: AI Agent Node  \nThis node acts as the **content brain \ud83e\udde0** of the workflow.  \nIt uses a carefully designed prompt to control the tweet generation process, ensuring that each post is relevant, professional, and aligned with the intended tone. The AI agent dynamically adapts content based on the given context, making every tweet unique and impactful.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "c855336e-907a-4d16-bcb1-d3f40d355ba9",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        1216
      ],
      "parameters": {
        "color": 3,
        "width": 384,
        "height": 368,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n### Step 2.1: AI Agent Node  \nThis node acts as the **content brain \ud83e\udde0** of the workflow.  \nIt uses a carefully designed prompt to control the tweet generation process, ensuring that each post is relevant, professional, and aligned with the intended tone. The AI agent dynamically adapts content based on the given context, making every tweet unique and impactful.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "44a5383e-df8d-4e20-8c5e-413d31a74bce",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        1712
      ],
      "parameters": {
        "color": 4,
        "width": 464,
        "height": 304,
        "content": "\n\n\n\n\n\n\n\n\n\n### Step 2.2: Simple Memory Node  \nThis node acts as a **context store \ud83e\udde0**, holding the conversation history and relevant details passed from the AI Agent and Chat Model.  \nIt ensures continuity so that future tweet generations stay consistent in tone, style, and context.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "43269c90-3691-48dc-8c3a-aea53349206b",
      "name": "Get Data from Google Sheet",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        1120,
        1248
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}/edit#gid=0",
          "cachedResultName": "Tweets"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}/edit?usp=drivesdk",
          "cachedResultName": "Twitter"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "dcf857b1-9cf0-42aa-8b5c-651d6cc97118",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        1232
      ],
      "parameters": {
        "color": 6,
        "width": 496,
        "height": 304,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n### Step 2.3: Get Rows from Google Sheet Node  \nThis node retrieves the list of **already published tweets \ud83d\udcd1** from a connected Google Sheet.  \nBy keeping track of past posts, it ensures the workflow avoids publishing duplicate tweets and maintains fresh, engaging content each time.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "410b5cb5-b4fb-4c00-9d06-464860334a43",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1616,
        1232
      ],
      "parameters": {
        "jsCode": "// Input: string with escaped or messy JSON\nconst inputString = $input.first().json.output;\n\nfunction safeParse(str) {\n  try {\n    // Try direct parse first\n    return JSON.parse(str);\n  } catch (e) {\n    // Try to extract JSON substring with regex\n    const match = str.match(/\\{[\\s\\S]*\\}/);\n    if (match) {\n      try {\n        return JSON.parse(match[0]);\n      } catch (err) {\n        return { error: \"Failed to parse extracted JSON\", raw: str };\n      }\n    }\n    return { error: \"Invalid JSON format\", raw: str };\n  }\n}\n\nconst parsed = safeParse(inputString);\n\n// Return cleaned output\nreturn [\n  {\n    json: parsed\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ea5b0b4f-a8f2-41fb-9fa7-d11d89f8b9c1",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1456,
        1040
      ],
      "parameters": {
        "width": 400,
        "height": 352,
        "content": "### Step 3: Code Node  \nThis node parses the **raw string response \ud83d\udcdd** generated by the AI model into a clean, structured **JSON format**.  \nBy converting the response into executable JSON, it ensures that the tweet content is easy to process and ready for further automation steps.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "190e5bfe-99e6-4dbf-abc2-a56e633ef4a3",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2080,
        816
      ],
      "parameters": {
        "color": 3,
        "width": 432,
        "height": 352,
        "content": "### Step 4: X Create Tweet Node  \nThis node publishes the final tweet \ud83d\udc26 generated by the AI directly to **X (Twitter)**.  \nIt ensures that the content parsed and validated in earlier steps is posted automatically on schedule, keeping your feed consistent and engaging.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "44d53ba9-ffdc-44dd-9414-65149f2b2449",
      "name": "Add new Tweet to Google sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3024,
        1200
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $('Parse AI Response').item.json.status }}",
            "Tweet Content": "={{ $('Parse AI Response').item.json.tweet_content }}"
          },
          "schema": [
            {
              "id": "Tweet Content",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tweet Content",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Tweet Content"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}/edit#gid=0",
          "cachedResultName": "Tweets"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/{YOUR_GOOGLE_SHEETS_DOCUMENT_ID}/edit?usp=drivesdk",
          "cachedResultName": "Twitter"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "95ba4418-c676-425d-bdee-a756f1422bea",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2816,
        960
      ],
      "parameters": {
        "color": 4,
        "width": 496,
        "height": 432,
        "content": "### Step 5: Add New Tweet to Google Sheet Node  \nThis node logs each newly published tweet into the connected **Google Sheet**.  \nIt records both the **tweet content** and its **status** (marked as *Published*) to maintain a structured history of all posts.  \n\nThis log is later referenced in **Step 2.3** (Get Rows from Google Sheet) to check for duplicates, ensuring that the AI never regenerates or reposts the same tweet \u2014 completing the cycle of tweet creation, publication, and validation.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "e9779654-a51b-4c71-b356-9fd7e7d08ea4",
      "name": "Start Workflow",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -96,
        1312
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "28fca0ca-9c2d-4b14-9c50-4b533bc7fac9",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        592
      ],
      "parameters": {
        "color": 3,
        "width": 528,
        "height": 432,
        "content": "### Prerequisites  \n\n#### Google Sheets  \n- Connect your Google credentials with **Google Sheets** and **Google Drive** services enabled.  \n- Create a Google Sheet with the following column headers:  \n  - **Tweet Content**  \n  - **Status**  \n- Use this sheet in all Google Sheet nodes within the workflow.  \n\n#### OpenAI  \n- Add and connect your **OpenAI API Key** in the **OpenAI Chat Model node** to enable tweet generation.  \n\n#### X (Twitter)  \n- Connect your **Twitter (X) account credentials** in the **Create Tweet node** to allow automated posting.  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "7d1f8ed7-e600-482f-b4b2-bae71fd337c2",
      "name": "Sticky Note23",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1552,
        1584
      ],
      "parameters": {
        "color": 2,
        "width": 440,
        "height": 240,
        "content": "## Need Help? \n\nWe develop tailored workflow to save youe valuable time. Should you have any questions or wish to explore more custom automation solutions, we would be happy to connect\n\n\n### Email: getstarted@intuz.com\n### Website: https://www.intuz.com/\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "0d4ea7d6-69a6-40bc-a8f3-4fb1ce2c6315",
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Tweet": {
      "main": [
        [
          {
            "node": "Add new Tweet to Google sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Start Workflow": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Create Tweet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Data from Google Sheet": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "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 uses an AI agent to intelligently generate unique, high-quality content, check for duplicates, and post it on a consistent schedule to automate your entire Twitter presence. Social Media Managers Marketing Teams & Agencies Startup Founders & Solopreneurs Content…

Source: https://n8n.io/workflows/8010/ — 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 is perfect for creators, solopreneurs, and personal brands who want to consistently publish bold, high-performing content on X (Twitter) — without writing a single line themselves. After

OpenAI Chat, Memory Buffer Window, Tool Workflow +10
AI & RAG

Template Name: AI Personal Assistant - Task & Email Management Price: $27 Category: Productivity & Automation Difficulty: Intermediate Use Case: Personal productivity automation for busy professionals

Telegram, HTTP Request, OpenAI +8
AI & RAG

This workflow manages subscription billing reminders and data updates via Telegram. It runs daily at 8:00 AM to check for upcoming due subscriptions, formats relevant information, and sends reminders

OpenAI Chat, Memory Buffer Window, Telegram +7
AI & RAG

⚠️ DISCLAIMER: This workflow uses the AnySite LinkedIn community node, which is only available on self-hosted n8n instances. It will not work on n8n.cloud.

OpenAI Chat, Output Parser Structured, Google Sheets +6
AI & RAG

Enhance your support, onboarding, and internal knowledge workflows with an intelligent RAG-powered chatbot that responds using live data stored in Google Sheets. 🤖📚 Built for teams that rely on struct

Chat Trigger, Output Parser Structured, Memory Buffer Window +6