This workflow corresponds to n8n.io template #5993 — we link there as the canonical source.
This workflow follows the Agent → Chat Trigger 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 →
{
"nodes": [
{
"id": "2ad62f13-abb9-4278-b356-e864f6195333",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
-880
],
"parameters": {
"color": 2,
"width": 832,
"height": 544,
"content": "## Video Tutorial\n\n@[youtube](J4Zwc6UzxAg)"
},
"typeVersion": 1
},
{
"id": "d5a76a59-a08d-4ed9-aa47-e49f01192e19",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1136,
-48
],
"parameters": {},
"typeVersion": 1.3
},
{
"id": "1bbdea91-baef-465b-9d7a-29e3af85cdd3",
"name": "Official n8n Documentation",
"type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-848,
-48
],
"parameters": {
"mode": "retrieve-as-tool",
"topK": 10,
"options": {},
"tableName": {
"__rl": true,
"mode": "list",
"value": "documents",
"cachedResultName": "documents"
},
"toolDescription": "Get related chunks of the official n8n documentation.",
"includeDocumentMetadata": false
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "8c365d9c-c6f5-448d-8900-e51140056f0a",
"name": "Default Data Loader",
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
576,
-1552
],
"parameters": {
"options": {},
"jsonData": "={{ $json.documentation }}",
"jsonMode": "expressionData",
"textSplittingMode": "custom"
},
"typeVersion": 1.1
},
{
"id": "345ffcae-00ad-4555-ab88-4b9c5b4e7fac",
"name": "Recursive Character Text Splitter",
"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
672,
-1344
],
"parameters": {
"options": {
"splitCode": "markdown"
},
"chunkSize": 1500,
"chunkOverlap": 200
},
"typeVersion": 1
},
{
"id": "42c79849-3529-471e-b355-76363791f0f5",
"name": "Remove Duplicate Documentation Content",
"type": "n8n-nodes-base.removeDuplicates",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-48,
-1776
],
"parameters": {
"options": {
"scope": "node",
"historySize": 10000
},
"operation": "removeItemsSeenInPreviousExecutions",
"dedupeValue": "={{ $json.documentation }}"
},
"typeVersion": 2
},
{
"id": "3e914e61-6eb1-4570-83ca-89987b32bbcd",
"name": "Only Keep Doc Paths",
"type": "n8n-nodes-base.filter",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
80,
-2544
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "52b8b89a-30cd-4a0d-a428-e5d341bcebbf",
"operator": {
"type": "string",
"operation": "endsWith"
},
"leftValue": "={{ $json.link }}",
"rightValue": "/"
},
{
"id": "d8019c4e-e1a1-43ec-93a8-dac3d8c083b6",
"operator": {
"type": "string",
"operation": "notStartsWith"
},
"leftValue": "={{ $json.link }}",
"rightValue": "https://"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "648fc609-500b-49cb-b1a2-a3d531e04ed9",
"name": "Clean Documentation",
"type": "n8n-nodes-base.set",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-480,
-1776
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "5ed964a6-5200-454c-b983-f3dc7c8c7a48",
"name": "documentation",
"type": "string",
"value": "={{ $json.data.replace(/([^#\\n]+)\\s*#/g, '# $1').trim().replace(/^\\s*https?:\\/\\/\\S+\\s*/, '') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f2ffe790-312a-43b9-b568-398ef2ae508d",
"name": "Gemini 2.5 Flash",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1488,
-48
],
"parameters": {
"options": {
"temperature": 0
}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "fbda8b9a-038d-4968-b65d-a438cbfac493",
"name": "Your Supabase Vector Store",
"type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
464,
-1776
],
"parameters": {
"mode": "insert",
"options": {},
"tableName": {
"__rl": true,
"mode": "list",
"value": "documents",
"cachedResultName": "documents"
},
"embeddingBatchSize": 30
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "e09949fc-205a-4a6e-ac02-038c8c8409da",
"name": "Get All n8n Documentation Links",
"type": "n8n-nodes-base.httpRequest",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1072,
-2544
],
"parameters": {
"url": "https://docs.n8n.io/",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "2bccb047-cdb0-41cd-bd23-457b3aaffc02",
"name": "Extract Links from HTML",
"type": "n8n-nodes-base.html",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-784,
-2544
],
"parameters": {
"options": {},
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "links",
"attribute": "href",
"cssSelector": "a",
"returnArray": true,
"returnValue": "attribute"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "6cbddaa0-24b2-4bff-b72f-13220065ceee",
"name": "Split Out Links",
"type": "n8n-nodes-base.splitOut",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-448,
-2544
],
"parameters": {
"options": {
"destinationFieldName": "link"
},
"fieldToSplitOut": "links"
},
"typeVersion": 1
},
{
"id": "75d011f4-cb3b-4f8c-8cd0-902205ea6e8b",
"name": "Remove Duplicate Links",
"type": "n8n-nodes-base.removeDuplicates",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-144,
-2544
],
"parameters": {
"compare": "selectedFields",
"options": {},
"fieldsToCompare": "link"
},
"typeVersion": 2
},
{
"id": "2ff289f1-9fca-4b26-bd97-8748c4c0c982",
"name": "Add Documentation Page to Vector Store",
"type": "n8n-nodes-base.executeWorkflow",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
592,
-2512
],
"parameters": {
"options": {
"waitForSubWorkflow": true
},
"workflowId": {
"__rl": true,
"mode": "id",
"value": "={{ $workflow.id }}"
},
"workflowInputs": {
"value": {},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"data"
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2,
"alwaysOutputData": true
},
{
"id": "602123a8-8889-4f07-a7bd-2c2f3e1f710d",
"name": "Get Documentation Page",
"type": "n8n-nodes-base.httpRequest",
"notes": "\u00a9 2025 Lucas Peyrin",
"onError": "continueErrorOutput",
"position": [
-1008,
-1776
],
"parameters": {
"url": "=https://docs.n8n.io/{{ $json.link }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "f3d49729-da95-4676-ba77-2f1f69c03b4c",
"name": "Extract Documentation Content",
"type": "n8n-nodes-base.html",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-704,
-1776
],
"parameters": {
"options": {},
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "data",
"cssSelector": "article",
"skipSelectors": "img, footer, form"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "10d376c0-d5e8-4d3e-a420-78616724f491",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2560,
-2192
],
"parameters": {
"color": 7,
"width": 760,
"height": 752,
"content": "-- Enable the pgvector extension to work with embedding vectors (REMOVE THIS LINE IF ALREADY ENABLED)\ncreate extension vector;\n\n-- Create a table to store your documents\ncreate table documents (\n id bigserial primary key,\n content text, -- corresponds to Document.pageContent\n metadata jsonb, -- corresponds to Document.metadata\n embedding vector(768) -- 768 works for Gemini embeddings, CHANGE IF OPENAI EMBEDDINGS\n);\n\n-- Create a function to search for documents\ncreate function match_documents (\n query_embedding vector(1536),\n match_count int default null,\n filter jsonb DEFAULT '{}'\n) returns table (\n id bigint,\n content text,\n metadata jsonb,\n similarity float\n)\nlanguage plpgsql\nas $$\n#variable_conflict use_column\nbegin\n return query\n select\n id,\n content,\n metadata,\n 1 - (documents.embedding <=> query_embedding) as similarity\n from documents\n where metadata @> filter\n order by documents.embedding <=> query_embedding\n limit match_count;\nend;\n$$;"
},
"typeVersion": 1
},
{
"id": "dc7586a5-10ff-445a-add8-c385a3f19e5c",
"name": "Gemini Query Embedding",
"type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-768,
144
],
"parameters": {},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "0c699715-c6d5-4292-aa2e-cacf9f684c2f",
"name": "Gemini Chunk Embedding",
"type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
448,
-1552
],
"parameters": {},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "8706ada8-8b69-4b68-aab2-c96c2b2119d0",
"name": "Keep Supabase Instance Alive",
"type": "n8n-nodes-base.supabase",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-112,
-896
],
"parameters": {
"limit": 1,
"tableId": "documents",
"operation": "getAll"
},
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "c140b29f-6fea-456d-a2f2-de02e669f48b",
"name": "Every 6 Days",
"type": "n8n-nodes-base.scheduleTrigger",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-336,
-896
],
"parameters": {
"rule": {
"interval": [
{
"daysInterval": 6
}
]
}
},
"typeVersion": 1.2
},
{
"id": "1e7540da-bf42-4fcb-b3cb-37f45a532728",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1664,
-2896
],
"parameters": {
"color": 7,
"width": 2640,
"height": 1760,
"content": "## Part 1: Building the Knowledge Base (The Library)\n\n**Goal:** To read all n8n documentation, break it into small pieces, and store it in our Supabase database.\n**Action:** You only need to run this part **ONCE** by clicking the \"Execute workflow\" button on the top-left trigger.\n**Time:** This will take several minutes to complete (~15 to 20)."
},
"typeVersion": 1
},
{
"id": "272fcc9f-887a-4b7c-a92e-212b73286230",
"name": "Loop Over Documentation Pages",
"type": "n8n-nodes-base.splitInBatches",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
368,
-2544
],
"parameters": {
"options": {},
"batchSize": 10
},
"typeVersion": 3
},
{
"id": "a620eb1b-3afa-41b2-a92c-00c0250fb62d",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2624,
-3424
],
"parameters": {
"color": 6,
"width": 1064,
"height": 504,
"content": "# Tutorial: Build an AI Expert with RAG\n\nWelcome! This workflow teaches you **RAG (Retrieval-Augmented Generation)**.\n\n**The Goal:** To create an AI chatbot that is an expert on a specific topic (the n8n docs) and *never* makes up answers.\n\n**It has two parts:**\n1. **TOP FLOW (Indexing):** You run this once manually to build the AI's knowledge base. It reads the n8n docs and stores them in a Supabase database.\n2. **BOTTOM FLOW (Chat):** This is the live chatbot. It retrieves relevant info from the knowledge base to answer your questions accurately.\n\n---\n\n### Automate your operations today\nYour time is valuable. Let us automate the boring stuff for you.\n\n**\ud83d\udc47 CHOOSE YOUR PATH:**\n\n[ **\u26a1\ufe0f I WANT A FREE AUDIT (2 min)** ](https://workflows.ac/audit?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=create_a_documentation_expert_bot_with_rag_gemini_and_supabase&utm_content=5993)\n> *We've put our heart into this business evaluation machine.*\n\n[ **\ud83d\udca1 I HAVE A SPECIFIC REQUEST** ](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=create_a_documentation_expert_bot_with_rag_gemini_and_supabase&utm_content=5993)\n"
},
"typeVersion": 1
},
{
"id": "52b33334-f3bf-4fd0-a595-9993b5e59e45",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2624,
-2896
],
"parameters": {
"color": 7,
"width": 924,
"height": 3228,
"content": "# Workflow Setup"
},
"typeVersion": 1
},
{
"id": "cbd4f31b-1ae0-4b9a-b479-0ac0598b829a",
"name": "n8n Docs AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1120,
-640
],
"parameters": {
"options": {
"systemMessage": "=<role>\nYou are a specialized AI assistant, an expert in n8n's official documentation. Your sole mission is to help users by providing accurate and factual information extracted exclusively from this documentation. You are meticulous, factual, and never deviate from your knowledge scope.\n</role>\n\n<instructions>\n<goal>\nYour primary goal is to provide precise and factual answers to user questions about the n8n automation platform, based **exclusively** on the excerpts from the official documentation provided in the context.\n</goal>\n\n<context>\nYou operate according to a RAG (Retrieval-Augmented Generation) model. For each user question, use the appropriate tool to retrieve the necessary information from the n8n documentation's vector database.\n\n**Mandatory rules:**\n\n1. **Single source of truth:** Your answer MUST be entirely and solely derived from the information present in the provided documentation.\n2. **Accuracy and implicit citation:** Base your answer as literally as possible on the documentation text. Rephrase for clarity and conciseness, but do not add any information not found there. Act as if the documentation is your only knowledge in the world.\n3. **Do not mention the process:** Never mention your tool or the fact that you are a RAG system in your answer to the user. Respond as an expert who directly consults their documentation.\n</context>\n\n<output_format>\n* **Clarity:** Provide a clear, concise, and direct answer.\n* **Structuring:** If the context contains steps, lists, or code examples, use Markdown syntax to format them legibly (bullet points, numbered lists, code blocks for code snippets, JSON, etc.).\n* **Tone:** Adopt a professional, helpful, and confident tone, that of a technical n8n expert.\n</output_format>\n</instructions>"
}
},
"typeVersion": 2.1
},
{
"id": "b034896c-93d8-4ea9-99d1-4e4d5e014412",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1168,
-2752
],
"parameters": {
"color": 7,
"width": 288,
"height": 400,
"content": "### Step 1.1: Find All the 'Books'\n\n**What it does:** This node visits the main n8n documentation page.\n**Analogy:** We're asking the library's front desk for a complete list of every single book they have."
},
"typeVersion": 1
},
{
"id": "46c45a67-e934-4b08-8e26-4cde8452fc75",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-864,
-2752
],
"parameters": {
"color": 7,
"width": 272,
"height": 400,
"content": "### Step 1.2: Read the List of Books\n\n**What it does:** It takes the HTML from the previous step and extracts every single link (`<a>` tag).\n**Analogy:** We're reading the list from the front desk and pulling out just the titles of the books (the links)."
},
"typeVersion": 1
},
{
"id": "f1f4f619-bf7f-46bd-b693-a52d4d086792",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-576,
-2752
],
"parameters": {
"color": 7,
"width": 336,
"height": 400,
"content": "### Step 1.3: Process One Book at a Time\n\n**What it does:** It takes the big list of links and turns each link into a separate item for n8n to process.\n**Analogy:** Instead of trying to read all the books at once, we're creating a separate to-do item for each book."
},
"typeVersion": 1
},
{
"id": "c797b838-0aee-4e27-b13b-f9bbc106fb65",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-2752
],
"parameters": {
"color": 7,
"width": 480,
"height": 400,
"content": "### Step 1.4: Tidy Up the To-Do List\n\n**What it does:** First, it removes any duplicate links. Then, it filters out any links that don't point to an actual documentation page (e.g., links to the homepage or external sites).\n**Analogy:** We're throwing away duplicate to-do items and any notes that aren't actually books."
},
"typeVersion": 1
},
{
"id": "b0e2599e-5e8d-40a7-8c8e-69e874ce22dc",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
-2752
],
"parameters": {
"color": 4,
"width": 512,
"height": 464,
"content": "### Step 1.5: The Librarian's Reading Loop\n\n**What it does:** This is the engine of the indexing process. It takes our clean list of pages and processes them one by one. The `Execute Workflow` node calls the \"sub-workflow\" below for each and every page.\n**Analogy:** This loop tells our librarian to pick up one book (link) at a time and go through the full process of reading and indexing it."
},
"typeVersion": 1
},
{
"id": "3177c487-9dfb-4f21-839f-130f65a9b859",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1104,
-1984
],
"parameters": {
"color": 7,
"width": 288,
"height": 384,
"content": "### Step 1.5.1: Read a Single Page\n\n**What it does:** This node takes a single URL from the loop and fetches the HTML content of that page.\n**Analogy:** The librarian opens one book to the first page."
},
"typeVersion": 1
},
{
"id": "e6f2fa91-e79a-4157-9985-79b591d88df5",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-2128
],
"parameters": {
"color": 5,
"width": 512,
"height": 528,
"content": "### Why Use a Sub-Workflow?\n\nThe main reason is **memory management**.\n\nProcessing a single web page, especially creating vector embeddings for all its chunks, uses a lot of memory (RAM). The n8n documentation has over 1,000 pages. If we tried to process all of them in a single, linear run, the memory usage would build up with each page and would likely crash your n8n instance.\n\nWhen a sub-workflow finishes its run for one item (one page), n8n **clears out the memory** (RAM) it used before starting the next one.\n\nBy using a sub-workflow, we process pages one-by-one in a memory-efficient loop, making the entire indexing process stable and reliable, even on a massive scale."
},
"typeVersion": 1
},
{
"id": "db438316-dbed-4d25-ac1a-80373a7235af",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
-800,
-1984
],
"parameters": {
"color": 7,
"width": 512,
"height": 384,
"content": "### Step 1.5.2: Get the Good Stuff\n\n**What it does:** It extracts only the main text from the article on the page, ignoring menus, footers, and images. Then, it cleans up the formatting.\n**Analogy:** The librarian tears out only the useful pages from the book and cleans up any smudges or messy handwriting."
},
"typeVersion": 1
},
{
"id": "9b8b485b-4be8-474a-9ba1-1a1d55d7a02e",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
-272,
-2208
],
"parameters": {
"color": 5,
"width": 544,
"height": 608,
"content": "### Step 1.5.3: Avoid Re-reading\n\n**What it does:** It checks if we have already processed this exact page content in a previous run. If so, it stops here to save time and resources.\n**Analogy:** The librarian checks their \"already read\" pile to avoid reading the same book twice.\n\n**A Powerful Feature Explained:**\n\nUsually, the \"Remove Duplicates\" node only looks at the items in the *current* execution. But here, it's set to **\"Remove items seen in previous executions.\"**\n\nThis is incredibly powerful in a sub-workflow. Even though our sub-workflow only sees one page at a time, this node has a long-term memory. It remembers every single page it has *ever* processed across all previous runs.\n\nThis makes the workflow robust. You can run the indexing process again and again to update the knowledge base with new documentation, and it will never waste resources re-processing old pages and more importantly, it won't create duplicate chunks in Supabase."
},
"typeVersion": 1
},
{
"id": "e271d052-dc6e-4380-be18-8d51c49fc6ef",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
288,
-2208
],
"parameters": {
"color": 6,
"width": 656,
"height": 1040,
"content": "### Step 1.5.4: Create & Store the 'Magic Index Cards'\n\nThis is the most important step of indexing!\n\n1. **`Recursive Character Text Splitter`:** The text is broken down into small, overlapping paragraphs (\"chunks\").\n * **Analogy:** The librarian breaks the book down into small, meaningful paragraphs. This is vital for finding very specific answers later.\n\n2. **`Gemini Chunk Embedding`:** An AI model converts each chunk of text into a list of numbers (a \"vector\" or \"embedding\").\n * **Analogy:** The librarian uses a 'magic pen' to turn each paragraph into a unique set of numbers. Paragraphs with similar meanings get similar numbers.\n\n3. **`Your Supabase Vector Store (Insert)`:** The original text chunk and its new vector are saved together in your Supabase database.\n * **Analogy:** The librarian files the original paragraph along with its magic number on an index card and puts it in a special filing cabinet (your Supabase vector store)."
},
"typeVersion": 1
},
{
"id": "041060ee-020a-4541-b894-3a7f531fc20e",
"name": "Sticky Note16",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1664,
-1104
],
"parameters": {
"color": 7,
"width": 1200,
"height": 1440,
"content": "## Part 2: The Chatbot (Talking to the Expert Librarian)\n\n**Goal:** To provide an interface where a user can ask a question, have the system find relevant information from the knowledge base, and get an accurate, AI-generated answer.\n**Action:** After running the Indexing flow, **Activate** this workflow. Then, open the `When chat message received` node and use its Public URL to chat."
},
"typeVersion": 1
},
{
"id": "f93ae799-f751-48ce-ac9e-98a0ec2c8cda",
"name": "Sticky Note17",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-944
],
"parameters": {
"color": 4,
"width": 368,
"height": 448,
"content": "### The Front Desk: Ask Your Question Here\n\n**What it does:** This is the public-facing chat interface. When you send a message here, the entire RAG process begins.\n\n**Action:**\n1. **Activate** the entire workflow.\n2. To test directly inside n8n, click the **\"Open Chat\"** button in this node's parameter panel.\n3. To chat publicly, copy the **Public URL** from this node and open it in a new browser tab."
},
"typeVersion": 1
},
{
"id": "e13e5f83-3628-4bc9-9d4a-2b2a1d8f5af8",
"name": "Sticky Note18",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1248,
-832
],
"parameters": {
"color": 5,
"width": 560,
"height": 400,
"content": "### The Brains: The Expert Librarian\n\n**What it does:** This is the AI agent that orchestrates the entire response. It understands your question, decides which tools to use, and formulates the final answer.\n**System Prompt:** Its instructions (in the System Message) are very strict: **\"Only use the provided documents to answer. Do not make things up.\"**"
},
"typeVersion": 1
},
{
"id": "5597474d-cded-474e-a9cc-631050986d63",
"name": "Sticky Note19",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-480
],
"parameters": {
"color": 7,
"width": 368,
"height": 576,
"content": "### The 'Synthesizer' & 'Strategist'\n\n**What it does:** This is the Large Language Model (LLM). It has two critical jobs:\n\n1. **The Strategist:** Based on your question and the conversation history, it decides *what information to look for* in the knowledge base (the library).\n2. **The Synthesizer:** After getting the relevant documents, it generates the final, human-readable answer based *only* on that context.\n\n\n**Analogy:** This is the part of the librarian's brain that first decides which section of the library to search, and then reads the specific index cards to write a clear, helpful response.\n\nThe model used here is **Gemini 2.5 Flash**."
},
"typeVersion": 1
},
{
"id": "60d88a66-9f0c-482f-8235-461695fd9d02",
"name": "Sticky Note20",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1248,
-416
],
"parameters": {
"color": 7,
"width": 288,
"height": 512,
"content": "### Short-Term Memory\n\n**What it does:** This node stores the last few messages of your conversation.\n**Analogy:** This helps the librarian remember what you just talked about, so you can ask follow-up questions without having to repeat yourself."
},
"typeVersion": 1
},
{
"id": "c2c15516-c4f3-4770-9435-8a2ec33d4d80",
"name": "Sticky Note21",
"type": "n8n-nodes-base.stickyNote",
"position": [
-944,
-416
],
"parameters": {
"color": 6,
"width": 448,
"height": 720,
"content": "### The Tool: The 'Magic Filing Cabinet' Retriever\n\nThis is the \"Retrieval\" part of RAG. When the agent gets your question, it uses this tool to find the most relevant information.\n\n1. **`Gemini Query Embedding`:** Your question is converted into its own 'magic number' (vector of 768 dimensions).\n\n2. **`Vector Store (Retrieve)`:** It searches the Supabase database for the stored document chunks with the most similar 'magic numbers' to your question's number.\n\n\n**Analogy:** The librarian takes your question, finds the most relevant index cards from the filing cabinet, and hands them over to the 'Synthesizer' to formulate the answer."
},
"typeVersion": 1
},
{
"id": "d450a7b2-584a-4e47-b66b-0f5442db45ec",
"name": "Sticky Note22",
"type": "n8n-nodes-base.stickyNote",
"position": [
-432,
-1104
],
"parameters": {
"color": 7,
"width": 544,
"height": 416,
"content": "## Optional: Keep the Database Awake\n\n**What it does:** Free Supabase projects \"go to sleep\" after a week of inactivity. This scheduled trigger runs a tiny query every 6 days to keep your database awake and ready.\n**Action:** You can delete this if you have a paid Supabase plan or a self-hosted instance."
},
"typeVersion": 1
},
{
"id": "ee177bf3-36c5-4b05-baad-b0858be54d0a",
"name": "Start Indexing",
"type": "n8n-nodes-base.manualTrigger",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1312,
-2544
],
"parameters": {},
"typeVersion": 1
},
{
"id": "b1e9e574-d2d7-41be-8859-b3aeea8c5be0",
"name": "RAG Chatbot",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1472,
-640
],
"parameters": {
"public": true,
"options": {
"title": "",
"subtitle": "",
"customCss": "/* === THEME OVERRIDE: n8n Glass & Glow (Revised) === */\n\n/*\n This theme is built upon the default n8n chat CSS variables.\n We'll use your desired branding and layout, and then add\n the \"glass\" effect using a semi-transparent background\n and a backdrop-filter on the main window class.\n*/\n\n:root {\n /* --- 1. CORE BRANDING & FONTS --- */\n /* Your choices for font and primary color are applied here. */\n --chat--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --chat--color-primary: #EA4B71; /* n8n Red */\n --chat--color-primary-shade-50: #D93A60;\n --chat--color-primary-shade-100: #C82A50;\n --chat--color-secondary: #20b69e; /* Kept default secondary for things like file uploads */\n --chat--color-secondary-shade-50: #1ca08a;\n --chat--color-white: #ffffff;\n --chat--color-light: #f2f4f8;\n --chat--color-dark: #1F2937; /* Darker, more modern text color */\n --chat--color-disabled: #9CA3AF;\n --chat--color-typing: #404040;\n\n /* --- 2. WINDOW & LAYOUT --- */\n /* Your dimensions and rounded corners. The actual glass effect is handled in the class override below. */\n --chat--window--width: 430px;\n --chat--window--height: 80vh;\n --chat--window--border-radius: 16px;\n --chat--window--border: 1px solid rgba(255, 255, 255, 0.3);\n --chat--spacing: 1rem; /* 16px base spacing */\n --chat--window--z-index: 9999;\n --chat--window--bottom: var(--chat--spacing);\n --chat--window--right: var(--chat--spacing);\n --chat--window--margin-bottom: var(--chat--spacing);\n\n /* --- 3. GLASSMORPHISM BACKGROUNDS --- */\n /* We make the main sections transparent to let the glass window show through. */\n --chat--header--background: transparent;\n --chat--body--background: transparent;\n --chat--footer--background: transparent;\n\n /* --- 4. HEADER STYLING (REMOVED) --- */\n /* The header is removed by setting its height, padding, and border to 0/none. */\n --chat--header-height: 0;\n --chat--header--padding: 0;\n --chat--header--border-bottom: none;\n /* The rest of the header variables are now irrelevant. */\n --chat--header--color: var(--chat--color-dark);\n --chat--heading--font-size: 1.5rem;\n --chat--subtitle--font-size: 0.875rem;\n --chat--subtitle--line-height: 1.4;\n --chat--close--button--color-hover: var(--chat--color-primary);\n\n /* --- 5. MESSAGE BUBBLES --- */\n --chat--message--font-size: 0.875rem;\n --chat--message--padding: 12px 16px;\n --chat--message--border-radius: 12px;\n --chat--message-line-height: 1.6;\n --chat--message--margin-bottom: calc(var(--chat--spacing) * 0.75);\n /* Adjusted padding: Top is 0, sides and bottom use the base spacing. */\n --chat--messages-list--padding: 0 var(--chat--spacing) var(--chat--spacing);\n --chat--message--bot--background: var(--chat--color-white);\n --chat--message--bot--color: #111827;\n --chat--message--bot--border: none;\n --chat--message--user--background: var(--chat--color-primary);\n --chat--message--user--color: var(--chat--color-white);\n --chat--message--user--border: none;\n\n /* --- 6. INPUT AREA --- */\n --chat--textarea--height: 50px;\n --chat--textarea--max-height: 10rem;\n --chat--input--font-size: 0.9rem;\n --chat--input--border: 0;\n --chat--input--border-radius: 12px; /* Rounded input field */\n --chat--input--padding: 12px 16px;\n --chat--input--background: rgba(255, 255, 255, 0.5); /* Semi-transparent input */\n --chat--input--text-color: #111827;\n --chat--input--line-height: 1.5;\n --chat--input--border-active: 0;\n\n /* --- 7. SEND & FILE BUTTONS --- */\n --chat--input--send--button--background: transparent;\n --chat--input--send--button--color: var(--chat--color-primary);\n --chat--input--send--button--background-hover: transparent;\n --chat--input--send--button--color-hover: var(--chat--color-primary-shade-50);\n --chat--input--file--button--background: transparent;\n --chat--input--file--button--color: var(--chat--color-secondary);\n --chat--input--file--button--background-hover: transparent;\n --chat--input--file--button--color-hover: var(--chat--color-secondary-shade-50);\n\n /* --- 8. TOGGLE BUTTON & OTHERS --- */\n /* Using your primary brand color for the main toggle button */\n --chat--toggle--size: 64px;\n --chat--toggle--width: var(--chat--toggle--size);\n --chat--toggle--height: var(--chat--toggle--size);\n --chat--toggle--border-radius: 50%;\n --chat--toggle--background: var(--chat--color-primary);\n --chat--toggle--hover--background: var(--chat--color-primary-shade-50);\n --chat--toggle--active--background: var(--chat--color-primary-shade-100);\n --chat--toggle--color: var(--chat--color-white);\n}\n\n/* === CLASS OVERRIDES === */\n/*\n These are essential for effects that CSS variables can't control,\n like the glass blur, shadows, and max-height.\n*/\n\n.chat-window {\n /* This is the magic for the glass effect! */\n background-color: rgba(249, 243, 245, 0.6); /* A semi-transparent background color */\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px); /* For Safari compatibility */\n\n /* A subtle shadow helps lift the window off the page */\n box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.1);\n\n /* Here we apply the max-height you wanted */\n max-height: 750px;\n}\n\n/* Add top margin to the first message only for initial spacing */\n.chat-messages-list .chat-message:first-child {\n margin-top: var(--chat--spacing);\n}\n\n/* Make user messages slightly wider for better balance */\n.chat-message.is-user {\n\tmax-width: 70%;\n}\n\n.chat-message.is-bot {\n\tmax-width: 80%;\n}\n\n/* Add a subtle glow to messages on hover */\n.chat-message {\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n}\n.chat-message:hover {\n transform: translateY(-2px);\n box-shadow: 0 0 25px 0 rgba(234, 75, 113, 0.2);\n}\n\n/* === PAGE BACKGROUND === */\n/* Your dotted background to simulate the n8n canvas. Perfect as is! */\nbody {\n background-color: #FDFBFF;\n background-image:\n radial-gradient(circle at 1px 1px, rgba(0,0,0,0.07) 1px, transparent 0),\n linear-gradient(135deg, #F9F3F5 0%, #EFF3FB 100%);\n background-size: 25px 25px, 100% 100%;\n}",
"inputPlaceholder": "Type your n8n related question.."
},
"initialMessages": "Hello! I'm an AI assistant trained on the official n8n documentation.\nYou can ask me anything about n8n nodes, workflows, or concepts. For example:\n\"How does the IF node work?\"\n\"What is a sub-workflow?\""
},
"typeVersion": 1.1
},
{
"id": "486ed614-77bc-41fd-bc8e-d034701b6919",
"name": "Sticky Note25",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-2816
],
"parameters": {
"width": 704,
"height": 256,
"content": "## Setup Step 1: Create Your Supabase Project\n\nFirst, we need to create the \"library\" where your AI's knowledge will be stored.\n\n**Action:**\n1. Go to [supabase.com](https://supabase.com/) and sign up for a free account.\n2. Create a **New Project**. Give it a name (e.g., \"n8n-rag-tutorial\") and generate a secure password.\n\n\nYou now have an empty database ready to be configured."
},
"typeVersion": 1
},
{
"id": "ece95b88-01df-4d23-9004-878c5d6a7b49",
"name": "Sticky Note26",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-2544
],
"parameters": {
"width": 832,
"height": 1136,
"content": "## Setup Step 2: Prepare the Database (SQL)\n\nNow we need to build the \"shelves\" and \"card catalog system\" for our library.\n\n**Action:**\n1. In your Supabase project, go to the **SQL Editor**.\n2. Find the other large sticky note on this canvas that contains the SQL code.\n3. **Copy the entire SQL code** and paste it into the Supabase SQL Editor, then click **\"RUN\"**.\n\n\n**\u26a0\ufe0f IMPORTANT:**\n* If you get an error that the `pgvector` extension already exists, simply delete the first line of the code (`create extension vector;`) and run it again.\n* This script is configured for **Gemini embeddings (dimension 768)**. If you plan to use an OpenAI model like `text-embedding-3-small`, you **MUST** change the vector dimension in the script from `vector(768)` to `vector(1536)`."
},
"typeVersion": 1
},
{
"id": "f68cfb36-4229-42de-b249-d99ae6de65ee",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-16
],
"parameters": {
"width": 624,
"height": 320,
"content": "## Setup Step 7: Chat with Your Expert!\n\nCongratulations, the library is built! Now it's time to ask the expert librarian a question.\n\n**Action:**\n1. **Activate** the entire workflow using the toggle switch at the top of the screen.\n2. Open the **`RAG Chatbot`** chat trigger node (bottom-left).\n3. To chat:\n * Copy its **Public URL** and open it in a new browser tab.\n * OR, click the **\"Open Chat\"** button in the node's panel to test it directly inside n8n.\n\n\n**Try asking:** \"How does the IF node work?\" or \"What is a sub-workflow?\""
},
"typeVersion": 1
},
{
"id": "1f66a70a-1da1-42f1-ada9-4d298fe6636f",
"name": "Sticky Note23",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-1392
],
"parameters": {
"width": 720,
"height": 272,
"content": "## Setup Step 3: Get Your Supabase Keys\n\nTo let n8n access your new library, we need the keys.\n\n**Action:**\n1. Go to **Project Settings > API**.\n2. Find the **Project URL**. Copy it.\n3. Find the **Project API Keys** section. Copy the key under the `service_role` (it's the long, secret one).\n\n\nKeep these two values ready for the next step. They are your library's address and master key."
},
"typeVersion": 1
},
{
"id": "16a876d7-73f4-4d60-8fc2-9f6b682e346d",
"name": "Sticky Note24",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-1104
],
"parameters": {
"width": 656,
"height": 400,
"content": "## Setup Step 4: Connect Your Credentials\n\nNow, let's save those keys securely in n8n without leaving the workflow.\n\n**Action for Supabase:**\n1. Go to the **`Your Supabase Vector Store`** node on the canvas.\n2. Click the **Credential** dropdown and select **`+ Create New Credential`**.\n3. In the window that opens:\n * Paste your **Project URL** into the `Host` field.\n * Paste your **Service Role Key** into the `API Key` field.\n4. Click **Save**. Your new credential will be created and automatically selected for this node.\n\n**Action for Google AI:**\n1. Go to the **`Gemini 2.5 Flash`** node.\n2. Click the **Credential** dropdown and select **`+ Create New Credential`**.\n3. Paste your **Gemini API key** and click **Save**."
},
"typeVersion": 1
},
{
"id": "5e4db806-3fda-48f3-b0e4-be7d042dec8e",
"name": "Sticky Note27",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-688
],
"parameters": {
"width": 864,
"height": 368,
"content": "## Setup Step 5: Select Credentials for Other Nodes\n\nYour new credentials are now saved. Let's make sure all the other nodes are using them.\n\n**Action:**\nGo to the remaining Supabase and Gemini nodes. Your new credentials will now be available in their **Credential** dropdown lists. Simply select the correct one for each.\n\n**Select your Supabase credential for:**\n* `Official n8n Documentation`\n* `Keep Supabase Instance Alive`\n\n**Select your Google AI credential for:**\n* `Gemini Chunk Embedding`\n* `Gemini Query Embedding`"
},
"typeVersion": 1
},
{
"id": "49d66d23-1eb4-4cb3-bada-c2dc3cea3599",
"name": "Sticky Note28",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2592,
-304
],
"parameters": {
"width": 784,
"height": 272,
"content": "## Setup Step 6: Build the Knowledge Base (Indexing)\n\nThis is the big one-time step where the \"librarian\" reads all the books.\n\n**Action:**\n1. Find the **`Start Indexing`** manual trigger node at the top-left of the canvas.\n2. Click its **\"Execute workflow\"** button.\n\n\n**\u26a0\ufe0f Be Patient!** This process will take **15-20 minutes** to scrape, process, and store the entire n8n documentation. Let it run until it completes successfully. You only need to do this once."
},
"typeVersion": 1
},
{
"id": "a981dd10-915b-46bf-9c79-58ec73dd7cd7",
"name": "Ingest Web Page",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"notes": "\u00a9 2025 Lucas Peyrin",
"position": [
-1312,
-1776
],
"parameters": {
"inputSource": "passthrough"
},
"typeVersion": 1.1
},
{
"id": "d4bd1733-e4c7-4487-a6c1-591c3acbffc0",
"name": "Sticky Note30",
"type": "n8n-nodes-base.stickyNote",
"position": [
-432,
-656
],
"parameters": {
"color": 7,
"width": 544,
"height": 1088,
"content": "## Was this helpful? Let me know!\n[](https://workflows.ac/form)\n\nI really hope this template helped you. Your feedback is what helps me create better resources for the n8n community.\n\n### **Have Feedback, a Question, or a Project Idea?**\n\n\n#### \u27a1\ufe0f **[Click here to go to the Contact Form](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=create_a_documentation_expert_bot_with_rag_gemini_and_supabase&utm_content=5993)**\n\nUse this single link for anything you need:\n\n* **Give Feedback:** Share your thoughts on this template, whether you found a typo, encountered an unexpected error, have a suggestion, or just want to say thanks!\n\n* **Automation Coaching:** Get personalized, one-on-one guidance to master n8n. We can work together to help you reach an expert level.\n\n* **Automation Consulting:** Have a complex business challenge or need custom workflows built from scratch? We offer a plug and play automation department for 8 to 88 people teams with unlimited automation requests.\n\n---\n\nHappy Automating!\nLucas Peyrin | [Workflows Accelerator](https://workflows.ac?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=create_a_documentation_expert_bot_with_rag_gemini_and_supabase&utm_content=5993)"
},
"typeVersion": 1
}
],
"connections": {
"RAG Chatbot": {
"main": [
[
{
"node": "n8n Docs AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Every 6 Days": {
"main": [
[
{
"node": "Keep Supabase Instance Alive",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "n8n Docs AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Start Indexing": {
"main": [
[
{
"node": "Get All n8n Documentation Links",
"type": "main",
"index": 0
}
]
]
},
"Ingest Web Page": {
"main": [
[
{
"node": "Get Documentation Page",
"type": "main",
"index": 0
}
]
]
},
"Split Out Links": {
"main": [
[
{
"node": "Remove Duplicate Links",
"type": "main",
"index": 0
}
]
]
},
"Gemini 2.5 Flash": {
"ai_languageModel": [
[
{
"node": "n8n Docs AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Clean Documentation": {
"main": [
[
{
"node": "Remove Duplicate Documentation Content",
"type": "main",
"index": 0
}
]
]
},
"Default Data Loader": {
"ai_document": [
[
{
"node": "Your Supabase Vector Store",
"type": "ai_document",
"index": 0
}
]
]
},
"Only Keep Doc Paths": {
"main": [
[
{
"node": "Loop Over Documentation Pages",
"type": "main",
"index": 0
}
]
]
},
"Gemini Chunk Embedding": {
"ai_embedding": [
[
{
"node": "Your Supabase Vector Store",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Gemini Query Embedding": {
"ai_embedding": [
[
{
"node": "Official n8n Documentation",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Get Documentation Page": {
"main": [
[
{
"node": "Extract Documentation Content",
"type": "main",
"index": 0
}
]
]
},
"Remove Duplicate Links": {
"main": [
[
{
"node": "Only Keep Doc Paths",
"type": "main",
"index": 0
}
]
]
},
"Extract Links from HTML": {
"main": [
[
{
"node": "Split Out Links",
"type": "main",
"index": 0
}
]
]
},
"Official n8n Documentation": {
"ai_tool": [
[
{
"node": "n8n Docs AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Extract Documentation Content": {
"main": [
[
{
"node": "Clean Documentation",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Documentation Pages": {
"main": [
[],
[
{
"node": "Add Documentation Page to Vector Store",
"type": "main",
"index": 0
}
]
]
},
"Get All n8n Documentation Links": {
"main": [
[
{
"node": "Extract Links from HTML",
"type": "main",
"index": 0
}
]
]
},
"Recursive Character Text Splitter": {
"ai_textSplitter": [
[
{
"node": "Default Data Loader",
"type": "ai_textSplitter",
"index": 0
}
]
]
},
"Add Documentation Page to Vector Store": {
"main": [
[
{
"node": "Loop Over Documentation Pages",
"type": "main",
"index": 0
}
]
]
},
"Remove Duplicate Documentation Content": {
"main": [
[
{
"node": "Your Supabase Vector Store",
"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.
googlePalmApisupabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template is a complete, hands-on tutorial for building a RAG (Retrieval-Augmented Generation) pipeline. In simple terms, you'll teach an AI to become an expert on a specific topic—in this case, the official n8n documentation—and then build a chatbot to ask it questions.
Source: https://n8n.io/workflows/5993/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
crawl4 ai. Uses documentDefaultDataLoader, textSplitterCharacterTextSplitter, vectorStoreSupabase, embeddingsOllama. Scheduled trigger; 65 nodes.
Tech Radar. Uses googleDrive, documentDefaultDataLoader, stickyNote, mySql. Scheduled trigger; 53 nodes.
This project is built on top of the famous open source ThoughtWorks Tech Radar.
Personal Portfolio Resume CV Chatbot. Uses embeddingsGoogleGemini, stickyNote, scheduleTrigger, lmChatGoogleGemini. Scheduled trigger; 35 nodes.
This template is perfect for: