This workflow follows the Agent → Chainllm 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 →
{
"name": "Contextual Retrieval",
"nodes": [
{
"parameters": {
"model": "gpt-4.1-mini",
"options": {}
},
"id": "629a895b-249f-4b04-95d8-5322c6a0f78c",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1,
"position": [
-680,
980
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsonMode": "expressionData",
"jsonData": "={{\n{\n \"content\": `${ $json.text }\\n---\\n${ $json.chunk }`\n}\n}}",
"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 }}"
},
{
"name": "file_url",
"value": "={{ $('Set File ID').first().json.file_url }}"
}
]
}
}
},
"id": "b1b305cc-59d1-4b3f-9561-bc2b77a34ff3",
"name": "Default Data Loader",
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
"typeVersion": 1,
"position": [
1460,
1700
]
},
{
"parameters": {
"model": "text-embedding-3-small",
"options": {}
},
"id": "03aa41f8-a136-4245-aeb0-dec739b28d23",
"name": "Embeddings OpenAI1",
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1,
"position": [
1300,
1700
],
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "## Tool to Add Google Drive Files to Vector DB with Contextual Embeddings",
"height": 867,
"width": 2853,
"color": 5
},
"id": "fd7c0f3f-6040-4312-ab4f-44becbefd071",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-980,
1180
]
},
{
"parameters": {
"operation": "download",
"fileId": {
"__rl": true,
"value": "={{ $('Set File ID').item.json.file_id }}",
"mode": "id"
},
"options": {
"googleFileConversion": {
"conversion": {
"docsToFormat": "text/plain"
}
}
}
},
"id": "d3d96ca0-a464-487a-9685-b2729bb296f4",
"name": "Download File",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
-80,
1440
],
"executeOnce": true,
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"value": "1iLcA4aE4rOe87BNXhiArRaHkG9dfzJqw",
"mode": "list",
"cachedResultName": "Neon",
"cachedResultUrl": "https://drive.google.com/drive/folders/1iLcA4aE4rOe87BNXhiArRaHkG9dfzJqw"
},
"event": "fileCreated",
"options": {}
},
"id": "a9e45a07-5f03-4f2d-a947-e71feae2c374",
"name": "File Created",
"type": "n8n-nodes-base.googleDriveTrigger",
"typeVersion": 1,
"position": [
-920,
1300
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"value": "1iLcA4aE4rOe87BNXhiArRaHkG9dfzJqw",
"mode": "list",
"cachedResultName": "Neon",
"cachedResultUrl": "https://drive.google.com/drive/folders/1iLcA4aE4rOe87BNXhiArRaHkG9dfzJqw"
},
"event": "fileUpdated",
"options": {}
},
"id": "c1edc043-6c13-4161-b8c6-9d22655da94a",
"name": "File Updated",
"type": "n8n-nodes-base.googleDriveTrigger",
"typeVersion": 1,
"position": [
-920,
1460
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "text",
"options": {}
},
"id": "ab685f23-0081-49dc-a91e-51f929e101f0",
"name": "Extract Document Text",
"type": "n8n-nodes-base.extractFromFile",
"typeVersion": 1,
"position": [
120,
1300
],
"alwaysOutputData": true
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $(\"When chat message received\").item.json.sessionId }}"
},
"id": "e4f7272e-0ef4-45f5-b9cb-ada6c29a7db5",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1,
"position": [
-500,
980
],
"notesInFlow": false,
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"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": "a4f9c240-bd71-420d-973e-5bcf19d172a1",
"name": "Set File ID",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-520,
1440
]
},
{
"parameters": {
"content": "## RAG AI Agent with Contextual Retrieval",
"height": 485,
"width": 1036
},
"id": "d81eeed4-bbd7-4074-ba91-4976a78a1c42",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-980,
680
]
},
{
"parameters": {
"options": {
"systemMessage": "=## Role\n\nYou are a Retrieval-Augmented Generation (RAG) assistant designed to answer questions a user has. You use a corpus of documents that are all text based. Your primary goal is to provide accurate, up-to-date, and relevant information based on what the user asks and the documents you retrieve.\n\n## Responsibilities\n\n- Answer user queries with a good mix of being comprehensive but still concise\n- Present information in an easy-to-understand and professional manner \n- Clarify misconceptions or misinformation\n\n## Other Key Information and Instructions\n\n- Always tell the user if you didn't find the answer. Don't make something up just to please them.\n- Keep your language neutral and factual. Do not show bias or opinion \n\n## Error Handling\n- If the information cannot be found using the provided instructions respond with: \n \u201cI\u2019m sorry, I couldn\u2019t find relevant information based on your documents.\u201d\n"
}
},
"id": "701de0d9-5ece-44da-9aa6-b4cdfeec3f88",
"name": "RAG AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.6,
"position": [
-600,
760
]
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1.2,
"position": [
-160,
1020
],
"id": "1643bbef-d8c6-49d7-828e-eec86ca0df2d",
"name": "Embeddings OpenAI2",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"options": {
"reset": false
}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
-700,
1300
],
"id": "0d74aee4-7188-4e6d-8ce7-18e37a30bd5f",
"name": "Loop Over Items"
},
{
"parameters": {
"chunkSize": 2000,
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
"typeVersion": 1,
"position": [
1580,
1860
],
"id": "d74c50f4-99cf-49cc-9d27-b885f3bc84d9",
"name": "Recursive Character Text Splitter"
},
{
"parameters": {
"public": true,
"options": {}
},
"id": "870b78ea-00cd-4187-9cf3-72c120d592ff",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [
-880,
760
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const chunks = [];\nconst chunkSize = 400;\nconst chunkOverlap = 0;\nconst text = $json.data.replace(/\\n/, '');\n\nfor (let i=0, j=Math.round(text.length/chunkSize); i<j; i++) {\n chunks.push(\n text.substr(\n Math.max(0,(i * chunkSize)-chunkOverlap),\n chunkSize\n )\n );\n}\n\nreturn { chunks };"
},
"id": "714947e8-e62a-4c3e-b454-35ff2fb28037",
"name": "Create Chunks From Doc",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
360,
1460
]
},
{
"parameters": {
"fieldToSplitOut": "chunks",
"options": {
"destinationFieldName": "chunk"
}
},
"id": "e4b50ede-9e2e-4a58-9929-831a66a2fa63",
"name": "Chunks To List",
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
580,
1320
]
},
{
"parameters": {
"promptType": "define",
"text": "=<document> \n{{ $('Extract Document Text').first().json.data }} \n</document>\nHere is the chunk we want to situate within the whole document \n<chunk> \n{{ $json.chunk }}\n</chunk> \nPlease give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else. "
},
"id": "2337b1e4-cb00-4e2b-b0df-7eb2e3cd2a43",
"name": "Generate Contextual Text",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.4,
"position": [
800,
1460
]
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-nano",
"mode": "list",
"cachedResultName": "gpt-4.1-nano"
},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.2,
"position": [
760,
1700
],
"id": "49a94474-d8c8-4d6a-a62d-27e5e16945cb",
"name": "OpenAI Chat Model3",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "069d067c-3534-4939-8ff4-34dee02a9436",
"name": "chunk",
"value": "={{ $('Chunks To List').item.json.chunk }}",
"type": "string"
},
{
"id": "24e01f4f-e156-47e9-a89e-9cbdccda6bd4",
"name": "text",
"value": "={{ $('Generate Contextual Text').item.json.text }}",
"type": "string"
}
]
},
"options": {}
},
"id": "4a569383-b3b6-470f-a567-df168ac22400",
"name": "Get Values",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1160,
1340
]
},
{
"parameters": {
"mode": "insert",
"tableName": "documents_pg",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
"typeVersion": 1.1,
"position": [
1380,
1440
],
"id": "f188cb0e-64cb-4389-a97e-bd53f82bab48",
"name": "Postgres PGVector Store",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "retrieve-as-tool",
"toolName": "documents_pg",
"toolDescription": "Use RAG to look up information in the knowledgebase.",
"tableName": "documents_pg",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.vectorStorePGVector",
"typeVersion": 1.1,
"position": [
-280,
880
],
"id": "10bf0453-c3a8-4584-8209-65e79a542b45",
"name": "Document RAG Tool1",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "DO $$\nBEGIN\n IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'documents_pg') THEN\n EXECUTE 'DELETE FROM documents_pg WHERE metadata->>''file_id'' LIKE ''%' || $1 || '%''';\n END IF;\nEND\n$$;",
"options": {
"queryReplacement": "={{ $json.file_id }}"
}
},
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.5,
"position": [
-300,
1300
],
"id": "48754246-3a5d-4a4d-a815-b77ad68242e4",
"name": "Delete Old Doc Records",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
}
],
"connections": {
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "RAG AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Download File": {
"main": [
[
{
"node": "Extract Document Text",
"type": "main",
"index": 0
}
]
]
},
"File Created": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Extract Document Text": {
"main": [
[
{
"node": "Create Chunks From Doc",
"type": "main",
"index": 0
}
]
]
},
"Embeddings OpenAI1": {
"ai_embedding": [
[
{
"node": "Postgres PGVector Store",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Default Data Loader": {
"ai_document": [
[
{
"node": "Postgres PGVector Store",
"type": "ai_document",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "RAG AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Set File ID": {
"main": [
[
{
"node": "Delete Old Doc Records",
"type": "main",
"index": 0
}
]
]
},
"File Updated": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Embeddings OpenAI2": {
"ai_embedding": [
[
{
"node": "Document RAG Tool1",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "Set File ID",
"type": "main",
"index": 0
}
]
]
},
"Recursive Character Text Splitter": {
"ai_textSplitter": [
[
{
"node": "Default Data Loader",
"type": "ai_textSplitter",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "RAG AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Chunks To List": {
"main": [
[
{
"node": "Generate Contextual Text",
"type": "main",
"index": 0
}
]
]
},
"Create Chunks From Doc": {
"main": [
[
{
"node": "Chunks To List",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model3": {
"ai_languageModel": [
[
{
"node": "Generate Contextual Text",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Generate Contextual Text": {
"main": [
[
{
"node": "Get Values",
"type": "main",
"index": 0
}
]
]
},
"Get Values": {
"main": [
[
{
"node": "Postgres PGVector Store",
"type": "main",
"index": 0
}
]
]
},
"Postgres PGVector Store": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Document RAG Tool1": {
"ai_tool": [
[
{
"node": "RAG AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Delete Old Doc Records": {
"main": [
[
{
"node": "Download File",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "bf4b5d55-ee85-4bac-ba54-8212c00dba4f",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "Tbo3PW1c2qp2gZJi",
"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.
googleDriveOAuth2ApiopenAiApipostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Contextual Retrieval. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, googleDrive. Event-driven trigger; 24 nodes.
Source: https://github.com/DPabloFlores/ottomator-agents/blob/main/contextual-retrieval-n8n-agent/Contextual_Retrieval_RAG_Agent.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
Your AI workforce is ready. Are you?
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
Automate Outreach Prospect automates finding, enriching, and messaging potential partners (like restaurants, malls, and bars) using Apify Google Maps scraping, Perplexity enrichment, OpenAI LLMs, Goog
Chat with docs - 5minAI New version. Uses httpRequest, documentDefaultDataLoader, textSplitterRecursiveCharacterTextSplitter, embeddingsOpenAi. Event-driven trigger; 62 nodes.