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 →
{
"createdAt": "2025-07-01T08:58:58.065Z",
"updatedAt": "2025-10-13T10:21:19.926Z",
"id": "OpPhzm9k32dxiE2B",
"name": "contoh-rag",
"active": false,
"isArchived": true,
"nodes": [
{
"parameters": {
"jsonMode": "expressionData",
"jsonData": "={{ $json.data || $json.text || $json.concatenated_data }}",
"options": {
"metadata": {
"metadataValues": [
{
"name": "=file_id",
"value": "={{ $('Set File ID').first().json.file_id }}"
},
{
"name": "file_title",
"value": "={{ $('Set File ID').first().json.file_title }}"
}
]
}
}
},
"id": "0f11aa7c-54be-4063-bf6c-209f6ed156f2",
"name": "Default Data Loader",
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
"typeVersion": 1,
"position": [
540,
1040
]
},
{
"parameters": {
"model": "text-embedding-3-small",
"options": {}
},
"id": "4b9a07ef-1087-4261-8237-59931c73202b",
"name": "Embeddings OpenAI1",
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1,
"position": [
300,
1040
]
},
{
"parameters": {
"content": "## Tool to Add a Google Drive File to Vector DB",
"height": 867,
"width": 3073,
"color": 5
},
"id": "7dd23160-3934-4ddb-9061-97ccba867a9d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2200,
440
]
},
{
"parameters": {
"operation": "download",
"fileId": {
"__rl": true,
"value": "={{ $('Set File ID').item.json.file_id }}",
"mode": "id"
},
"options": {
"googleFileConversion": {
"conversion": {
"docsToFormat": "text/plain"
}
}
}
},
"id": "fd03e5c7-8b7f-49a1-a314-226303a75b3e",
"name": "Download File",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
-1120,
720
],
"executeOnce": true
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"value": "1HtaIIK3kWwjbwhsmEbtJ-upalxVn3Ek9",
"mode": "list",
"cachedResultName": "n8n Documents",
"cachedResultUrl": "https://drive.google.com/drive/folders/1HtaIIK3kWwjbwhsmEbtJ-upalxVn3Ek9"
},
"event": "fileCreated",
"options": {}
},
"id": "f41dc2a2-cd6f-4514-8f64-3558bf0d65f7",
"name": "File Created",
"type": "n8n-nodes-base.googleDriveTrigger",
"typeVersion": 1,
"position": [
-2140,
560
]
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"value": "1HtaIIK3kWwjbwhsmEbtJ-upalxVn3Ek9",
"mode": "list",
"cachedResultName": "n8n Documents",
"cachedResultUrl": "https://drive.google.com/drive/folders/1HtaIIK3kWwjbwhsmEbtJ-upalxVn3Ek9"
},
"event": "fileUpdated",
"options": {}
},
"id": "d0cf99ed-188b-463a-ba95-9656b5dc539c",
"name": "File Updated",
"type": "n8n-nodes-base.googleDriveTrigger",
"typeVersion": 1,
"position": [
-2140,
720
]
},
{
"parameters": {
"operation": "text",
"options": {}
},
"id": "8b067ed9-b3e1-494c-af96-1d00906c5122",
"name": "Extract Document Text",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
-260,
1040
],
"alwaysOutputData": true
},
{
"parameters": {
"operation": "delete",
"tableId": "documents",
"filterType": "string",
"filterString": "=metadata->>file_id=like.*{{ $json.file_id }}*"
},
"id": "66ed6255-8d40-4cbb-b26c-ffaa88fe5088",
"name": "Delete Old Doc Rows",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
-1600,
560
],
"alwaysOutputData": true
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "10646eae-ae46-4327-a4dc-9987c2d76173",
"name": "file_id",
"value": "={{ $json.id }}",
"type": "string"
},
{
"id": "f4536df5-d0b1-4392-bf17-b8137fb31a44",
"name": "file_type",
"value": "={{ $json.mimeType }}",
"type": "string"
},
{
"id": "77d782de-169d-4a46-8a8e-a3831c04d90f",
"name": "file_title",
"value": "={{ $json.name }}",
"type": "string"
},
{
"id": "9bde4d7f-e4f3-4ebd-9338-dce1350f9eab",
"name": "file_url",
"value": "={{ $json.webViewLink }}",
"type": "string"
}
]
},
"options": {}
},
"id": "aaaa2acb-268b-41cf-91a4-d22085806c28",
"name": "Set File ID",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-1780,
720
]
},
{
"parameters": {
"content": "## RAG AI Agent with Chat Interface",
"height": 464.8027193303974,
"width": 1035.6381264595484
},
"id": "61a75da6-4485-41f3-9b28-94d7fb982594",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1500,
-40
]
},
{
"parameters": {
"operation": "pdf",
"options": {}
},
"id": "2136941b-4a3d-4f3b-9586-9f8d51003d90",
"name": "Extract PDF Text",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
-260,
480
]
},
{
"parameters": {
"aggregate": "aggregateAllItemData",
"options": {}
},
"id": "e89ddcf9-a8c6-47dd-b116-d4885c8a4058",
"name": "Aggregate",
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
-220,
660
]
},
{
"parameters": {},
"id": "eef97445-5ca1-472b-8704-dcf63845cd08",
"name": "Character Text Splitter",
"type": "@n8n/n8n-nodes-langchain.textSplitterCharacterTextSplitter",
"typeVersion": 1,
"position": [
440,
1160
]
},
{
"parameters": {
"fieldsToSummarize": {
"values": [
{
"aggregation": "concatenate",
"field": "data"
}
]
},
"options": {}
},
"id": "685c3b2d-3e7e-4ef5-8490-346447cd734c",
"name": "Summarize",
"type": "n8n-nodes-base.summarize",
"typeVersion": 1,
"position": [
-20,
740
]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $('Set File ID').item.json.file_type }}",
"rightValue": "application/pdf",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
}
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "2ae7faa7-a936-4621-a680-60c512163034",
"leftValue": "={{ $('Set File ID').item.json.file_type }}",
"rightValue": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
}
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "fc193b06-363b-4699-a97d-e5a850138b0e",
"leftValue": "={{ $('Set File ID').item.json.file_type }}",
"rightValue": "=application/vnd.google-apps.spreadsheet",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
}
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "b69f5605-0179-4b02-9a32-e34bb085f82d",
"leftValue": "={{ $('Set File ID').item.json.file_type }}",
"rightValue": "application/vnd.google-apps.document",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
}
}
]
},
"options": {
"fallbackOutput": 3
}
},
"id": "d21a91de-1377-476f-b582-f0256e55777a",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
-920,
700
]
},
{
"parameters": {
"mode": "insert",
"tableName": {
"__rl": true,
"value": "documents",
"mode": "list",
"cachedResultName": "documents"
},
"options": {
"queryName": "match_documents"
}
},
"id": "4bf25082-8071-4f3b-8acb-1d74efd6dc3d",
"name": "Insert into Supabase Vectorstore",
"type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
"typeVersion": 1,
"position": [
460,
820
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "xlsx",
"options": {}
},
"id": "fe7ed958-e47f-4573-870c-1fc5c8b63c17",
"name": "Extract from Excel",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
-440,
660
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "f422e2e0-381c-46ea-8f38-3f58c501d8b9",
"name": "schema",
"value": "={{ $('Extract from Excel').isExecuted ? $('Extract from Excel').first().json.keys().toJsonString() : $('Extract from CSV').first().json.keys().toJsonString() }}",
"type": "string"
},
{
"id": "bb07c71e-5b60-4795-864c-cc3845b6bc46",
"name": "data",
"value": "={{ $json.concatenated_data }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
420,
600
],
"id": "317c721f-dfd9-416d-91b7-2ca5c4ab2a07",
"name": "Set Schema"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
-440,
840
],
"id": "e14b6c96-9ed8-4e61-bb75-94e03238fcec",
"name": "Extract from CSV"
},
{
"parameters": {
"content": "## Run Each Node Once to Set Up Database Tables",
"height": 300,
"width": 680,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-2200,
120
],
"typeVersion": 1,
"id": "20a3ab64-1b40-4ad5-876b-3f5f799827d7",
"name": "Sticky Note3"
},
{
"parameters": {
"operation": "executeQuery",
"query": "CREATE TABLE document_metadata (\n id TEXT PRIMARY KEY,\n title TEXT,\n url TEXT,\n created_at TIMESTAMP DEFAULT NOW(),\n schema TEXT\n);",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-1940,
220
],
"id": "7441b410-2f1e-4429-bfb6-f4362cacdb3b",
"name": "Create Document Metadata Table",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "CREATE TABLE document_rows (\n id SERIAL PRIMARY KEY,\n dataset_id TEXT REFERENCES document_metadata(id),\n row_data JSONB -- Store the actual row data\n);",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-1720,
220
],
"id": "48eb1daf-f0f1-498f-be96-cd36dff33203",
"name": "Create Document Rows Table (for Tabular Data)"
},
{
"parameters": {
"options": {
"reset": false
}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
-1960,
560
],
"id": "169a9301-a7e6-4dc5-b374-2fbefae101e7",
"name": "Loop Over Items"
},
{
"parameters": {
"operation": "executeQuery",
"query": "-- Enable the pgvector extension to work with embedding vectors\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(1536) -- 1536 works for OpenAI embeddings, change if needed\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$$;",
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-2140,
220
],
"id": "1867a57a-a226-441b-82f2-4bf760444d6a",
"name": "Create Documents Table and Match Function",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "delete",
"tableId": "document_rows",
"filters": {
"conditions": [
{
"keyName": "dataset_id",
"condition": "eq",
"keyValue": "={{ $('Set File ID').item.json.file_id }}"
}
]
}
},
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
-1440,
720
],
"id": "f5cd4159-b8e5-4da3-9ad9-55a333401c60",
"name": "Delete Old Data Rows",
"alwaysOutputData": true,
"executeOnce": true
},
{
"parameters": {
"operation": "upsert",
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"table": {
"__rl": true,
"value": "document_metadata",
"mode": "list",
"cachedResultName": "document_metadata"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"id": "={{ $('Set File ID').item.json.file_id }}",
"title": "={{ $('Set File ID').item.json.file_title }}",
"url": "={{ $('Set File ID').item.json.file_url }}"
},
"matchingColumns": [
"id"
],
"schema": [
{
"id": "id",
"displayName": "id",
"required": true,
"defaultMatch": true,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "title",
"displayName": "title",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false
},
{
"id": "url",
"displayName": "url",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false,
"removed": false
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "dateTime",
"canBeUsedToMatch": false
},
{
"id": "schema",
"displayName": "schema",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false,
"removed": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-1280,
580
],
"id": "d1c35cfb-9083-485b-8a81-6fbe9655e2cf",
"name": "Insert Document Metadata",
"executeOnce": true
},
{
"parameters": {
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"table": {
"__rl": true,
"value": "document_rows",
"mode": "list",
"cachedResultName": "document_rows"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"dataset_id": "={{ $('Set File ID').item.json.file_id }}",
"row_data": "={{ $json.toJsonString().replaceAll(/'/g, \"''\") }}"
},
"matchingColumns": [
"id"
],
"schema": [
{
"id": "id",
"displayName": "id",
"required": false,
"defaultMatch": true,
"display": true,
"type": "number",
"canBeUsedToMatch": true,
"removed": true
},
{
"id": "dataset_id",
"displayName": "dataset_id",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "row_data",
"displayName": "row_data",
"required": false,
"defaultMatch": false,
"display": true,
"type": "object",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-220,
840
],
"id": "1a43e237-c025-4e8c-9a51-b0a31b1762fa",
"name": "Insert Table Rows"
},
{
"parameters": {
"operation": "upsert",
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"table": {
"__rl": true,
"value": "document_metadata",
"mode": "list",
"cachedResultName": "document_metadata"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"id": "={{ $('Set File ID').item.json.file_id }}",
"schema": "={{ $json.schema }}"
},
"matchingColumns": [
"id"
],
"schema": [
{
"id": "id",
"displayName": "id",
"required": true,
"defaultMatch": true,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "title",
"displayName": "title",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false,
"removed": true
},
{
"id": "url",
"displayName": "url",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false,
"removed": true
},
{
"id": "created_at",
"displayName": "created_at",
"required": false,
"defaultMatch": false,
"display": true,
"type": "dateTime",
"canBeUsedToMatch": false
},
{
"id": "schema",
"displayName": "schema",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
640,
600
],
"id": "10305a92-3eae-4e24-afc1-170de1ff161a",
"name": "Update Schema for Document Metadata"
},
{
"parameters": {
"content": "## \ud83d\ude80 Ultimate n8n Agentic RAG Template\n\n**Author:** [Cole Medin](https://www.youtube.com/@ColeMedin)\n\n## What is this?\nThis template provides a complete implementation of an **Agentic RAG (Retrieval Augmented Generation)** system in n8n that can be extended easily for your specific use case and knowledge base. Unlike standard RAG which only performs simple lookups, this agent can reason about your knowledge base, self-improve retrieval, and dynamically switch between different tools based on the specific question.\n\n## Why Agentic RAG?\nStandard RAG has significant limitations:\n- Poor analysis of numerical/tabular data\n- Missing context due to document chunking\n- Inability to connect information across documents\n- No dynamic tool selection based on question type\n\n## What makes this template powerful:\n- **Intelligent tool selection**: Switches between RAG lookups, SQL queries, or full document retrieval based on the question\n- **Complete document context**: Accesses entire documents when needed instead of just chunks\n- **Accurate numerical analysis**: Uses SQL for precise calculations on spreadsheet/tabular data\n- **Cross-document insights**: Connects information across your entire knowledge base\n- **Multi-file processing**: Handles multiple documents in a single workflow loop\n- **Efficient storage**: Uses JSONB in Supabase to store tabular data without creating new tables for each CSV\n\n## Getting Started\n1. Run the table creation nodes first to set up your database tables in Supabase\n2. Upload your documents through Google Drive (or swap out for a different file storage solution)\n3. The agent will process them automatically (chunking text, storing tabular data in Supabase)\n4. Start asking questions that leverage the agent's multiple reasoning approaches\n\n## Customization\nThis template provides a solid foundation that you can extend by:\n- Tuning the system prompt for your specific use case\n- Adding document metadata like summaries\n- Implementing more advanced RAG techniques\n- Optimizing for larger knowledge bases\n\n---\n\nI do intend on making a local version of this agent very soon!",
"height": 1320,
"width": 540,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-2780,
-20
],
"typeVersion": 1,
"id": "c6b8c61d-607d-4b42-bbd3-b50ea9de787f",
"name": "Sticky Note9"
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1.2,
"position": [
-200,
220
],
"id": "3be06a44-848a-48ac-86bb-251ea4628e42",
"name": "Embeddings OpenAI2"
},
{
"parameters": {
"mode": "retrieve-as-tool",
"toolName": "documents",
"toolDescription": "Use RAG to look up information in the knowledgebase.",
"tableName": {
"__rl": true,
"value": "documents",
"mode": "list",
"cachedResultName": "documents"
},
"options": {
"queryName": "match_documents"
}
},
"type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
"typeVersion": 1,
"position": [
-300,
40
],
"id": "588e2d4c-11b7-4660-b08e-2abf42a0ca76",
"name": "Supabase Vector Store1"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Run a SQL query - use this to query from the document_rows table once you know the file ID you are querying. dataset_id is the file_id and you are always using the row_data for filtering, which is a jsonb field that has all the keys from the file schema given in the document_metadata table.\n\nExample query:\n\nSELECT AVG((row_data->>'revenue')::numeric)\nFROM document_rows\nWHERE dataset_id = '123';\n\nExample query 2:\n\nSELECT \n row_data->>'category' as category,\n SUM((row_data->>'sales')::numeric) as total_sales\nFROM dataset_rows\nWHERE dataset_id = '123'\nGROUP BY row_data->>'category';",
"operation": "executeQuery",
"query": "{{ $fromAI('sql_query') }}",
"options": {}
},
"type": "n8n-nodes-base.postgresTool",
"typeVersion": 2.5,
"position": [
-620,
260
],
"id": "50322ff7-c172-456e-8568-9f3d4d998ccc",
"name": "Query Document Rows"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Given a file ID, fetches the text from the document.",
"operation": "executeQuery",
"query": "SELECT \n string_agg(content, ' ') as document_text\nFROM documents\n WHERE metadata->>'file_id' = $1\nGROUP BY metadata->>'file_id';",
"options": {
"queryReplacement": "={{ $fromAI('file_id') }}"
}
},
"type": "n8n-nodes-base.postgresTool",
"typeVersion": 2.5,
"position": [
-780,
260
],
"id": "5d6a677d-1f01-416a-8306-fde8a6d44934",
"name": "Get File Contents"
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Use this tool to fetch all available documents, including the table schema if the file is a CSV or Excel file.",
"operation": "select",
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"table": {
"__rl": true,
"value": "document_metadata",
"mode": "list",
"cachedResultName": "document_metadata"
},
"returnAll": true,
"options": {}
},
"type": "n8n-nodes-base.postgresTool",
"typeVersion": 2.5,
"position": [
-920,
260
],
"id": "eeaeec4b-a6a8-49c9-b317-1af5f4057cfe",
"name": "List Documents"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.chatInput }}",
"options": {
"systemMessage": "You are a personal assistant who helps answer questions from a corpus of documents. The documents are either text based (Txt, docs, extracted PDFs, etc.) or tabular data (CSVs or Excel documents).\n\nYou are given tools to perform RAG in the 'documents' table, look up the documents available in your knowledge base in the 'document_metadata' table, extract all the text from a given document, and query the tabular files with SQL in the 'document_rows' table.\n\nAlways start by performing RAG unless the question requires a SQL query for tabular data (fetching a sum, finding a max, something a RAG lookup would be unreliable for). If RAG doesn't help, then look at the documents that are available to you, find a few that you think would contain the answer, and then analyze those.\n\nAlways tell the user if you didn't find the answer. Don't make something up just to please them."
}
},
"id": "48939f9d-a816-4674-ada9-2a45445d2af5",
"name": "RAG AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.6,
"position": [
-980,
40
]
},
{
"parameters": {
"httpMethod": "POST",
"path": "bf4dd093-bb02-472c-9454-7ab9af97bd1d",
"authentication": "headerAuth",
"responseMode": "responseNode",
"options": {}
},
"id": "772e8c8e-2f2c-4334-985f-a1b09c37f405",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-1460,
240
]
},
{
"parameters": {
"public": true,
"options": {}
},
"id": "39681c8b-67cb-4003-9111-730d7ebcc7b3",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [
-1460,
40
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "9a9a245e-f1a1-4282-bb02-a81ffe629f0f",
"name": "chatInput",
"value": "={{ $json?.chatInput || $json.body.chatInput }}",
"type": "string"
},
{
"id": "b80831d8-c653-4203-8706-adedfdb98f77",
"name": "sessionId",
"value": "={{ $json?.sessionId || $json.body.sessionId}}",
"type": "string"
}
]
},
"options": {}
},
"id": "8e69005e-5ce1-4edd-ac60-86feee6a1a65",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-1200,
40
]
},
{
"parameters": {
"options": {}
},
"id": "13ac5cf8-22b6-4c65-8198-72f12b3feedb",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
-640,
40
]
},
{
"parameters": {},
"id": "b60a9775-4c01-41e0-874a-8442b623f3b0",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1,
"position": [
-1060,
260
],
"notesInFlow": false
},
{
"parameters": {
"content": "## Agent Tools for RAG",
"height": 528.85546469693,
"width": 583.4552380860637,
"color": 4
},
"id": "1aa74cc4-3dc1-41c6-b53e-3912145a922a",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-460,
-100
]
},
{
"parameters": {
"options": {}
},
"id": "fb4de6a9-4c5c-41a0-9ed5-edaa61609d55",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1,
"position": [
-1200,
260
]
}
],
"connections": {
"Download File": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"File Created": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Extract Document Text": {
"main": [
[
{
"node": "Insert into Supabase Vectorstore",
"type": "main",
"index": 0
}
]
]
},
"Embeddings OpenAI1": {
"ai_embedding": [
[
{
"node": "Insert into Supabase Vectorstore",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Default Data Loader": {
"ai_document": [
[
{
"node": "Insert into Supabase Vectorstore",
"type": "ai_document",
"index": 0
}
]
]
},
"Delete Old Doc Rows": {
"main": [
[
{
"node": "Delete Old Data Rows",
"type": "main",
"index": 0
}
]
]
},
"Set File ID": {
"main": [
[
{
"node": "Delete Old Doc Rows",
"type": "main",
"index": 0
}
]
]
},
"File Updated": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Extract PDF Text": {
"main": [
[
{
"node": "Insert into Supabase Vectorstore",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "Summarize",
"type": "main",
"index": 0
}
]
]
},
"Character Text Splitter": {
"ai_textSplitter": [
[
{
"node": "Default Data Loader",
"type": "ai_textSplitter",
"index": 0
}
]
]
},
"Summarize": {
"main": [
[
{
"node": "Set Schema",
"type": "main",
"index": 0
},
{
"node": "Insert into Supabase Vectorstore",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Extract PDF Text",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract from Excel",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract from CSV",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Document Text",
"type": "main",
"index": 0
}
]
]
},
"Extract from Excel": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
},
{
"node": "Insert Table Rows",
"type": "main",
"index": 0
}
]
]
},
"Set Schema": {
"main": [
[
{
"node": "Update Schema for Document Metadata",
"type": "main",
"index": 0
}
]
]
},
"Extract from CSV": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
},
{
"node": "Insert Table Rows",
"type": "main",
"index": 0
}
]
]
},
"Create Document Metadata Table": {
"main": [
[
{
"node": "Create Document Rows Table (for Tabular Data)",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "Set File ID",
"type": "main",
"index": 0
}
]
]
},
"Insert into Supabase Vectorstore": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Create Documents Table and Match Function": {
"main": [
[
{
"node": "Create Document Metadata Table",
"type": "main",
"index": 0
}
]
]
},
"Delete Old Data Rows": {
"main": [
[
{
"node": "Insert Document Metadata",
"type": "main",
"index": 0
}
]
]
},
"Insert Document Metadata": {
"main": [
[
{
"node": "Download File",
"type": "main",
"index": 0
}
]
]
},
"Embeddings OpenAI2": {
"ai_embedding": [
[
{
"node": "Supabase Vector Store1",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Supabase Vector Store1": {
"ai_tool": [
[
{
"node": "RAG AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Query Document Rows": {
"ai_tool": [
[
{
"node": "RAG AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Get File Contents": {
"ai_tool": [
[
{
"node": "RAG AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"List Documents": {
"ai_tool": [
[
{
"node": "RAG AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "RAG AI Agent",
"type": "main",
"index": 0
}
]
]
},
"RAG AI Agent": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "RAG AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "RAG AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": null,
"versionId": "f859ba0f-5d0c-4d44-8a62-f99737b921ca",
"triggerCount": 0,
"shared": [
{
"createdAt": "2025-10-13T10:29:43.656Z",
"updatedAt": "2025-10-13T10:29:43.656Z",
"role": "workflow:owner",
"workflowId": "OpPhzm9k32dxiE2B",
"projectId": "FX62idw1VcxEmrbL"
}
],
"tags": []
}
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.
postgressupabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
contoh-rag. Uses documentDefaultDataLoader, embeddingsOpenAi, googleDrive, googleDriveTrigger. Event-driven trigger; 42 nodes.
Source: https://github.com/Cleign1/n8n-workflow/blob/a61ffba17b8c5342d4fbd06f89962a0fc22db3ce/contoh-rag-.json — 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.
A lightweight, self-hosted AI assistant built entirely in n8n. Multi-channel messaging (Telegram, WhatsApp, Gmail), persistent memory, task management, and autonomous work — all in a single visual wor
Alfred (funcional). Uses gmailTool, googleCalendarTool, gmail, embeddingsOpenAi. Event-driven trigger; 83 nodes.
Your AI workforce is ready. Are you?
Agent IA Projet Client. Uses executeWorkflowTrigger, lmChatOpenAi, toolWorkflow, vectorStoreQdrant. Event-driven trigger; 79 nodes.
This n8n template automatically classifies incoming emails (Sales, Support, Internal, Finance, Promotions) and routes them to a dedicated OpenAI LLM Agent for processing. Depending on the category, th