AutomationFlowsAI & RAG › Generate Twitter Content in Personal Style with Openai & Supabase RAG

Generate Twitter Content in Personal Style with Openai & Supabase RAG

ByYusuke @yusuke-matsuba on n8n.io

Learn your voice. Generate posts that sound like you — not AI.

Event trigger★★★★☆ complexityAI-powered18 nodesForm TriggerOpenAI EmbeddingsDocument Default Data LoaderText Splitter Recursive Character Text SplitterSupabase Vector StoreFormOpenAI ChatAgent
AI & RAG Trigger: Event Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Documentdefaultdataloader 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": "6aee89e6-1147-415b-aa55-af6fceb67fee",
      "name": "Form: Add to KB",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        1456,
        880
      ],
      "parameters": {
        "options": {},
        "formTitle": "Add to KB",
        "formFields": {
          "values": [
            {
              "fieldType": "textarea",
              "fieldLabel": "content",
              "placeholder": "\ud83d\udcdd Paste your past post or idea here\u2026",
              "requiredField": true
            },
            {
              "fieldLabel": "topic",
              "placeholder": "\ud83d\udcac e.g. creator_mindset, ai_automation, productivity"
            }
          ]
        },
        "formDescription": "Paste your past posts or notes. Optionally tag topic and mark as style sample."
      },
      "typeVersion": 2.2
    },
    {
      "id": "20b70111-5194-41fb-8ea4-07c71dfdfa00",
      "name": "Normalize (ingest)",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        880
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ ({ content: $json.fields.content, topic: ($json.fields.topic || ''), style: 'true' }) }}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "e513bb3f-3cfe-420a-8365-d9cc20d2a90b",
      "name": "Embeddings OpenAI (ingest)",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        1904,
        896
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c63114f2-ef60-4796-b8af-5f434382eaba",
      "name": "Document Loader (+metadata)",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        2032,
        896
      ],
      "parameters": {
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "source",
                "value": "user_ingest"
              },
              {
                "name": "style",
                "value": "true"
              },
              {
                "name": "topic",
                "value": "={{ $json.topic || '' }}"
              }
            ]
          }
        },
        "jsonData": "={{ $json.content }}",
        "jsonMode": "expressionData"
      },
      "typeVersion": 1
    },
    {
      "id": "5d45d346-d224-4c1e-86ba-18a0e3b75a9f",
      "name": "Text Splitter",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        2112,
        1104
      ],
      "parameters": {
        "options": {},
        "chunkSize": 1200,
        "chunkOverlap": 150
      },
      "typeVersion": 1
    },
    {
      "id": "3a99f2d4-e71d-4617-8a9c-2aa321211a29",
      "name": "VectorStore (Supabase)",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "position": [
        1936,
        672
      ],
      "parameters": {
        "mode": "insert",
        "options": {
          "queryName": "match_documents"
        },
        "tableName": {
          "__rl": true,
          "mode": "list",
          "value": "documents"
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e4fad627-65a6-46f0-8128-b4ce1027a9bc",
      "name": "End Page (ingest)",
      "type": "n8n-nodes-base.form",
      "position": [
        2400,
        880
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "={{ $json.metadata.topic }}",
        "completionMessage": "={{ $json.pageContent }}"
      },
      "typeVersion": 2.3
    },
    {
      "id": "d37dad08-4b54-42b5-9f68-209ad7fa0578",
      "name": "Form: Generate",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        1456,
        1392
      ],
      "parameters": {
        "options": {},
        "formTitle": "Generate Posts",
        "formFields": {
          "values": [
            {
              "fieldLabel": "topic"
            },
            {
              "fieldType": "number",
              "fieldLabel": "topK",
              "placeholder": "Default 5"
            },
            {
              "fieldLabel": "hint",
              "placeholder": "Optional hint (e.g., Consistency vs creativity)"
            }
          ]
        },
        "formDescription": "Create post/quote/reply/image_prompt from your knowledge base."
      },
      "typeVersion": 2.2
    },
    {
      "id": "d00d4e20-2590-43ef-bedb-519184336051",
      "name": "Build Params",
      "type": "n8n-nodes-base.set",
      "position": [
        1680,
        1392
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ ({ topic: $json.fields.topic || '', style: 'true', topK: Number($json.fields.topK || 5), hint: $json.fields.hint || '', filters: { topic: ($json.fields.topic || ''), style: true } }) }}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "9f41f462-fcdf-4794-a3f2-b86faec6be4b",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1904,
        1616
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "c4c2de4b-432d-4a88-afc4-23c6daca5754",
      "name": "KB (Supabase VectorStore)",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "position": [
        2032,
        1616
      ],
      "parameters": {
        "mode": "retrieve-as-tool",
        "options": {
          "queryName": "match_documents"
        },
        "toolName": "kb_vectorstore",
        "tableName": {
          "__rl": true,
          "mode": "id",
          "value": "documents"
        },
        "toolDescription": "KB search over Supabase `documents` (use filters like {\"topic\":\"creator_mindset\",\"style\":\"true\"})"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "214659b2-a7a9-4e0f-8a3f-c9dfd7c4778e",
      "name": "Generator Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1936,
        1392
      ],
      "parameters": {
        "text": "=You are a content engineer for X posts.\nUse the KB (tool) to fetch up to {{$json.topK || 5}} relevant snippets using {{$json.filters}}.\nThen output **JSON only** with keys exactly:\n{\"post\",\"quote\",\"reply\",\"image_prompt\"}\n- post: one original tweet (<=230 chars, no hashtags/links)\n- quote: sharp quote-tweet for a given topic/link (<=200 chars)\n- reply: constructive reply (<=180 chars, end with a short question)\n- image_prompt: brief photoreal/graphic prompt\nKeep tone aligned to retrieved examples. Topic: {{$json.topic}}. Hint: {{$json.hint}}",
        "options": {
          "systemMessage": "Be concise, concrete, and aligned to prior high-engagement style."
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "3769f432-c187-45fe-9451-d278a83c52ff",
      "name": "Edit Fields (format HTML)",
      "type": "n8n-nodes-base.set",
      "position": [
        2400,
        1392
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ (() => { const cur = Array.isArray($json) ? $json[0] : $json; let o = {}; try { o = typeof cur.output === 'string' ? JSON.parse(cur.output) : (cur.output || {}); } catch(e) { o = {}; } return { completionTitle: '\ud83c\udfaf Generated Results', completionMessage: `<div style=\\\"font-family:sans-serif; line-height:1.5;\\\"><h3>\ud83d\udcdd Post</h3><p>${o.post ?? ''}</p><hr/><h3>\ud83d\udcac Quote</h3><p>${o.quote ?? ''}</p><hr/><h3>\ud83d\udcad Reply</h3><p>${o.reply ?? ''}</p><hr/><h3>\ud83c\udfa8 Image Prompt</h3><p>${o.image_prompt ?? ''}</p></div>` }; })() }}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "b7f522ca-5478-4f41-8926-93cd1677a4d6",
      "name": "End Page (generate)",
      "type": "n8n-nodes-base.form",
      "position": [
        2624,
        1392
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "={{ $json.completionTitle }}",
        "completionMessage": "={{ $json.completionMessage }}"
      },
      "typeVersion": 2.3
    },
    {
      "id": "7f01e91f-0fa7-4fb3-a75a-75bca886ec1d",
      "name": "Sticky: Overview (yellow)1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        560
      ],
      "parameters": {
        "color": 7,
        "width": 540,
        "height": 416,
        "content": "## Self-Learning X Content Engine (Creator RAG Booster)\n\n### How it works\nThis workflow builds a small knowledge base from your past posts. Ingested text is cleaned, chunked, embedded, and stored in Supabase. The generator then retrieves relevant snippets and creates one post, one quote-tweet, one reply, and one image prompt.\n\n### Setup steps\n1. Add your OpenAI + Supabase creds.\n2. Use **Add to KB** to ingest 10\u201320 samples per topic.\n3. Go to **Generate Posts** \u2192 choose topic, topK, hint.\n4. View results on the final page.\n5. Add more samples for better tone accuracy."
      },
      "typeVersion": 1
    },
    {
      "id": "fafe155c-76c5-4cf3-93fe-1a0ffa94aedc",
      "name": "Sticky: Step ",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        672
      ],
      "parameters": {
        "width": 380,
        "height": 180,
        "content": "## Ingest (build KB)\nNormalize text \u2192 add metadata \u2192 split into chunks \u2192 embed \u2192 store in Supabase.\nUse **Add to KB** to add posts and notes."
      },
      "typeVersion": 1
    },
    {
      "id": "323fb28f-b2fc-457a-bae4-46d9e256778a",
      "name": "Sticky: Step 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1376,
        1200
      ],
      "parameters": {
        "width": 360,
        "content": "## Generate (use KB)\nSet topic + topK + optional hint.\nThe agent searches Supabase and returns a post, quote, reply, and image prompt."
      },
      "typeVersion": 1
    },
    {
      "id": "bb2f7f95-bad9-46bd-90ac-6985aa183af2",
      "name": "Sticky: Troubleshooting1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        1040
      ],
      "parameters": {
        "width": 360,
        "content": "## Troubleshooting\nBlank page \u2192 check form is Completion type.\nNo inserts \u2192 Supabase creds/RLS.\nGeneric tone \u2192 add more samples.\nOdd matches \u2192 adjust topic or topK."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Build Params": {
      "main": [
        [
          {
            "node": "Generator Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "Document Loader (+metadata)",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "Form: Generate": {
      "main": [
        [
          {
            "node": "Build Params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Form: Add to KB": {
      "main": [
        [
          {
            "node": "Normalize (ingest)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generator Agent": {
      "main": [
        [
          {
            "node": "Edit Fields (format HTML)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generator Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Normalize (ingest)": {
      "main": [
        [
          {
            "node": "VectorStore (Supabase)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "VectorStore (Supabase)": {
      "main": [
        [
          {
            "node": "End Page (ingest)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields (format HTML)": {
      "main": [
        [
          {
            "node": "End Page (generate)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "KB (Supabase VectorStore)": {
      "ai_tool": [
        [
          {
            "node": "Generator Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI (ingest)": {
      "ai_embedding": [
        [
          {
            "node": "VectorStore (Supabase)",
            "type": "ai_embedding",
            "index": 0
          },
          {
            "node": "KB (Supabase VectorStore)",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Document Loader (+metadata)": {
      "ai_document": [
        [
          {
            "node": "VectorStore (Supabase)",
            "type": "ai_document",
            "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

Learn your voice. Generate posts that sound like you — not AI.

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

Your AI workforce is ready. Are you?

Google Sheets Tool, Mcp Trigger, Google Drive +29
AI & RAG

Chat with docs - 5minAI New version. Uses httpRequest, documentDefaultDataLoader, textSplitterRecursiveCharacterTextSplitter, embeddingsOpenAi. Event-driven trigger; 62 nodes.

HTTP Request, Document Default Data Loader, Text Splitter Recursive Character Text Splitter +10
AI & RAG

I prepared a detailed guide that illustrates the entire process of building an AI agent using Supabase and Google Drive within N8N workflows.

HTTP Request, Document Default Data Loader, Text Splitter Recursive Character Text Splitter +10
AI & RAG

Auto repost job with RAG is a workflow designed to automatically extract, process, and publish job listings from monitored sources using Google Drive, OpenAI, Supabase, and WordPress. This integration

Google Drive, Supabase Vector Store, OpenAI Embeddings +12
AI & RAG

This n8n workflow turns your Telegram bot into a smart, multi-modal AI assistant that accepts text, documents, images, and audio messages, interprets them using OpenAI models, and responds instantly w

Telegram Trigger, Telegram, OpenAI +10