This workflow follows the Agent → HTTP Request 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": "ZEP Memory",
"nodes": [
{
"parameters": {
"promptType": "define",
"text": "={{ $json.message.text }}",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 2,
"position": [
220,
-560
],
"id": "541507eb-abde-478e-9960-567439f41475",
"name": "AI Agent"
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
0,
-560
],
"id": "210ce106-4b4e-40e6-9aff-abd151a33dd6",
"name": "Telegram Trigger",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"text": "={{ $json.output }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
580,
-560
],
"id": "03069cee-447d-41d3-95b1-d98f0445ad3c",
"name": "Send a text message",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
-20,
0
],
"id": "58415b2c-bed0-447a-9009-c825668bfd94",
"name": "Telegram Trigger1",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"disabled": true
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger1').item.json.message.chat.id }}",
"text": "={{ $('AI Agent 2').item.json.output }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1140,
0
],
"id": "6c1bc09a-f627-4719-9304-8c28fef7c264",
"name": "Send a text message1",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// n8n Code Node\n// This code extracts all facts from the JSON structure\n\n// Get the input data\nconst items = $input.all();\nconst facts = [];\n\n// Process each item\nfor (const item of items) {\n try {\n // Parse the data string if it exists\n if (item.json.data) {\n const parsedData = JSON.parse(item.json.data);\n \n // Check if edges array exists\n if (parsedData.edges && Array.isArray(parsedData.edges)) {\n // Extract facts from each edge\n parsedData.edges.forEach(edge => {\n if (edge.fact) {\n facts.push(edge.fact);\n }\n });\n }\n }\n } catch (error) {\n // Handle parsing errors\n console.error('Error parsing data:', error);\n }\n}\n\n// Return all facts as an array in a single item\nreturn [{\n json: {\n facts: facts\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
300,
80
],
"id": "5ef7ad9d-9fc9-49a9-b716-6abd508e67cc",
"name": "Code"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Telegram Trigger1').item.json.message.text }}",
"options": {
"systemMessage": "=You are a helpful assistant.\n\nHere is some additional information about Nate:\n{{ $json.facts.join(\"\\n\") }}\n\n5 most recent interactions with Nate:\n{{ $json.conversations.join(\"\\n\\n\")}}"
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 2,
"position": [
620,
0
],
"id": "4ce5948e-9f07-4ff4-82bc-f0a722ce7f51",
"name": "AI Agent 2"
},
{
"parameters": {
"url": "=https://api.getzep.com/api/v2/sessions/{{ $json.message.chat.id }}/messages",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "zepApi",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "limit",
"value": "10"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
160,
-80
],
"id": "6e2c0c5e-304d-45b2-b946-83855db03a57",
"name": "Context Window",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"method": "POST",
"url": "https://api.getzep.com/api/v2/graph/search",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "zepApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"zep_c6b8b1f0611f69464c860b3ae885639e022d1c54b59ffe82d16faf9c08cc24b0\",\n \"query\": \"{{ $json.message.text }}\",\n \"scope\": \"edges\",\n \"limit\": 3,\n \"search_filters\": {\n \"min_relevance\": 0.7\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
160,
80
],
"id": "4508f733-d001-499b-8828-11a191282a1b",
"name": "User Graph",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Loop through each item\nfor (const item of $input.all()) {\n // Parse the JSON data\n const jsonData = JSON.parse(item.json.data);\n const messages = jsonData.messages;\n \n // Array to store formatted message pairs\n const messagePairs = [];\n \n // Process messages in pairs (Human followed by AI)\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n \n // Look for Human messages\n if (message.role === \"Human\" && message.role_type === \"user\") {\n // Check if there's a corresponding AI response\n if (i + 1 < messages.length && messages[i + 1].role === \"AI\" && messages[i + 1].role_type === \"assistant\") {\n // Format the pair\n const pair = `Human: ${message.content}\\nAI: ${messages[i + 1].content}`;\n messagePairs.push(pair);\n \n // Skip the AI message in the next iteration since we've already processed it\n i++;\n } else {\n // If no AI response, just add the human message\n messagePairs.push(`Human: ${message.content}`);\n }\n } else if (message.role === \"AI\" && message.role_type === \"assistant\") {\n // Handle standalone AI messages (shouldn't happen in normal conversation flow)\n messagePairs.push(`AI: ${message.content}`);\n }\n }\n \n // Return all pairs as a single array\n return [{\n json: {\n conversations: messagePairs\n }\n }];\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
300,
-80
],
"id": "8b7169e3-e930-49e4-8969-158a52247a81",
"name": "Code1"
},
{
"parameters": {
"mode": "combine",
"combineBy": "combineByPosition",
"options": {}
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3.2,
"position": [
460,
0
],
"id": "ca50e57e-f1a8-447c-99e7-8db833bd7d9d",
"name": "Merge"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.getzep.com/api/v2/sessions/{{ $('Telegram Trigger1').item.json.message.chat.id }}/memory",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "zepApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"zep_c6b8b1f0611f69464c860b3ae885639e022d1c54b59ffe82d16faf9c08cc24b0\",\n \"session_id\": \"{{ $('Telegram Trigger1').item.json.message.chat.id }}\",\n \"messages\": [\n {\n \"role_type\": \"user\",\n \"content\": \"{{ $('Telegram Trigger1').item.json.message.text }}\"\n },\n {\n \"role_type\": \"assistant\",\n \"content\": \"{{ $json.output.replace(/\\n/g, '').replace(/\"/g, '') }}\"\n }\n ]\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
940,
0
],
"id": "6aa1334a-b036-4c8f-943b-1bdb8293e5ec",
"name": "Add Memory",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
-20,
480
],
"id": "16f6bd19-c4b9-4480-89bb-e58583f5e78d",
"name": "Telegram Trigger2",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"disabled": true
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger2').item.json.message.chat.id }}",
"text": "={{ $('AI Agent 3').item.json.output }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1000,
480
],
"id": "dd14c87f-9583-472f-86d3-5ff12ba4ec19",
"name": "Send a text message2",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// n8n Code Node\n// This code extracts all facts from the JSON structure\n\n// Get the input data\nconst items = $input.all();\nconst facts = [];\n\n// Process each item\nfor (const item of items) {\n try {\n // Parse the data string if it exists\n if (item.json.data) {\n const parsedData = JSON.parse(item.json.data);\n \n // Check if edges array exists\n if (parsedData.edges && Array.isArray(parsedData.edges)) {\n // Extract facts from each edge\n parsedData.edges.forEach(edge => {\n if (edge.fact) {\n facts.push(edge.fact);\n }\n });\n }\n }\n } catch (error) {\n // Handle parsing errors\n console.error('Error parsing data:', error);\n }\n}\n\n// Return all facts as an array in a single item\nreturn [{\n json: {\n facts: facts\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
300,
480
],
"id": "609694f0-51d1-4e18-8a9c-b6283695136a",
"name": "Code2"
},
{
"parameters": {
"method": "POST",
"url": "https://api.getzep.com/api/v2/graph/search",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "zepApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"zep_c6b8b1f0611f69464c860b3ae885639e022d1c54b59ffe82d16faf9c08cc24b0\",\n \"query\": \"{{ $json.message.text }}\",\n \"scope\": \"edges\",\n \"limit\": 3,\n \"search_filters\": {\n \"min_relevance\": 0.7\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
140,
480
],
"id": "53375e1f-a339-4da1-8afd-afead4487874",
"name": "User Graph1",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Telegram Trigger2').item.json.message.chat.id }}"
},
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1.3,
"position": [
580,
680
],
"id": "13e2b02b-7e35-4573-99e4-552cb939a82d",
"name": "Postgres Chat Memory",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "# Zep Memory\nContext & User Graph\n",
"height": 500,
"width": 940,
"color": 2
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-120,
-700
],
"id": "3c56fef7-8976-4268-a7c0-f36fd02928ce",
"name": "Sticky Note"
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
200,
-380
],
"id": "87aa689c-ce1e-4d94-8ecf-4beaaa742f08",
"name": "GPT 4.1 mini",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
600,
180
],
"id": "be8992db-c837-453a-b4b7-0a1830fc950e",
"name": "GPT 4.1 mini1",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
440,
680
],
"id": "06dc2089-155d-48f0-8188-a518c562a251",
"name": "GPT 4.1 mini2",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Telegram Trigger2').item.json.message.text }}",
"options": {
"systemMessage": "=You are a helpful assistant.\n\nHere is some additional information about Nate:\n{{ $json.facts.join(\"\\n\") }}"
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 2,
"position": [
500,
480
],
"id": "04dc87f1-4a5d-41b4-ba84-6a09961094eb",
"name": "AI Agent 3"
},
{
"parameters": {
"content": "# Zep Memory (HTTP)\nContext & User Graph\n",
"height": 500,
"width": 1480,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-120,
-180
],
"id": "bfcf0335-be1a-4f3a-ade8-2a07fe78c7cc",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "# Zep & Postgres Hybrid\nContext & User Graph\n",
"height": 500,
"width": 1360,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-120,
340
],
"id": "e73b68c0-ae8c-41d4-95e3-5ba58360fcca",
"name": "Sticky Note2"
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "=1"
},
"type": "@n8n/n8n-nodes-langchain.memoryZep",
"typeVersion": 1.3,
"position": [
400,
-380
],
"id": "f8b87230-812e-421c-8bb4-3a3c12896964",
"name": "Zep",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
},
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
940,
-380
],
"id": "fcdcdeba-4193-454f-8cef-38d5dba2e984",
"name": "Simple Memory"
},
{
"parameters": {
"method": "POST",
"url": "=https://api.getzep.com/api/v2/sessions/{{ $('Telegram Trigger2').item.json.message.chat.id }}/memory",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "zepApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"user_id\": \"zep_c6b8b1f0611f69464c860b3ae885639e022d1c54b59ffe82d16faf9c08cc24b0\",\n \"session_id\": \"{{ $('Telegram Trigger2').item.json.message.chat.id }}\",\n \"messages\": [\n {\n \"role_type\": \"user\",\n \"content\": \"{{ $('Telegram Trigger2').item.json.message.text }}\"\n },\n {\n \"role_type\": \"assistant\",\n \"content\": \"{{ $json.output.replace(/\\n/g, '').replace(/\"/g, '') }}\"\n }\n ]\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
820,
480
],
"id": "7b0547f0-4f8d-4b93-9250-be3f39ec5b52",
"name": "Add Memory1",
"credentials": {
"zepApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "# \ud83d\udee0\ufe0f Setup Guide \n**Author:** [Nate Herk](https://www.youtube.com/@nateherk)\n\nFollow the steps below to get this workflow up and running:\n\n### \u2705 Step 1: Set Up Your [ZEP](https://www.getzep.com/) Account \nHead to [ZEP](https://www.getzep.com/) and create a free account. This gives you access to your API key. \nOnce you have your key: \n- Plug it into the ZEP Memory Module in n8n. \n- You can also reuse this credential in HTTP Request nodes that call ZEP\u2019s API.\n\n### \u2705 Step 2: Connect a Chat Model \nHook up a chat model to your AI agents to power conversations. \nOptions include: \n- [OpenRouter](https://openrouter.ai/) \u2013 connect your OpenRouter API key. \n- Or use any other model provider of your choice.\n\n### \u2705 Step 3: Connect Telegram (Optional) \nWant to chat with your agents via Telegram? \n- Add your Telegram credentials in n8n so your agents can send/receive messages there.\n\n### \u2705 Step 4: Add Your Postgres Credential \nIn hybrid workflows that combine ZEP + Postgres, plug in your Postgres credentials. \n- This helps maintain a solid context window across memory systems.\n\n### \ud83d\udca1 Final Step: Start Testing & Exploring \n- Check token usage. \n- Explore your user graph in ZEP. \n- Fine-tune your agents. \n- Happy automating!\n",
"height": 780,
"width": 780
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-920,
-700
],
"id": "e46332bd-ddda-4c73-b0e6-d8a5faedda22",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## Ew... simple memory",
"height": 300,
"width": 300,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
840,
-500
],
"id": "1b8398c5-f2bd-476e-8cb7-2eac3f7285a3",
"name": "Sticky Note4"
}
],
"connections": {
"Telegram Trigger": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger1": {
"main": [
[
{
"node": "Context Window",
"type": "main",
"index": 0
},
{
"node": "User Graph",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"User Graph": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Context Window": {
"main": [
[
{
"node": "Code1",
"type": "main",
"index": 0
}
]
]
},
"Code1": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "AI Agent 2",
"type": "main",
"index": 0
}
]
]
},
"AI Agent 2": {
"main": [
[
{
"node": "Add Memory",
"type": "main",
"index": 0
}
]
]
},
"Add Memory": {
"main": [
[
{
"node": "Send a text message1",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger2": {
"main": [
[
{
"node": "User Graph1",
"type": "main",
"index": 0
}
]
]
},
"Code2": {
"main": [
[
{
"node": "AI Agent 3",
"type": "main",
"index": 0
}
]
]
},
"User Graph1": {
"main": [
[
{
"node": "Code2",
"type": "main",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "AI Agent 3",
"type": "ai_memory",
"index": 0
}
]
]
},
"GPT 4.1 mini": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"GPT 4.1 mini1": {
"ai_languageModel": [
[
{
"node": "AI Agent 2",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"GPT 4.1 mini2": {
"ai_languageModel": [
[
{
"node": "AI Agent 3",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent 3": {
"main": [
[
{
"node": "Add Memory1",
"type": "main",
"index": 0
}
]
]
},
"Zep": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[]
]
},
"Add Memory1": {
"main": [
[
{
"node": "Send a text message2",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "e8c7f5bb-22d9-4b81-90d6-e18e413c4092",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "GxMydqOT8W74wJW7",
"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.
openRouterApipostgrestelegramApizepApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow enables seamless, context-aware conversations with an AI agent via Telegram, preserving memory of past interactions to deliver personalised responses without repetitive explanations. It's ideal for developers or teams building intelligent chatbots that handle ongoing dialogues, such as customer support or personal assistants, saving hours on manual context management. The key step involves the AI agent querying a Postgres-based memory store before processing messages, integrated with OpenRouter for advanced language model capabilities and Telegram for real-time messaging.
Use this workflow when you need event-driven AI interactions that retain conversation history across sessions, like in automated advisory services or interactive bots. Avoid it for one-off queries or high-volume traffic without scaling the Postgres memory backend, as it could lead to performance issues. Common variations include swapping OpenRouter for a custom LLM provider or adding branching logic for multi-user scenarios.
About this workflow
ZEP Memory. Uses agent, telegramTrigger, telegram, httpRequest. Event-driven trigger; 29 nodes.
Source: https://github.com/Zie619/n8n-workflows — 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.
Arvifund - Supabase. Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
Arvifund - Supabase (Fixed v2). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
Arvifund - Supabase (Fixed v4). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
Arvifund - Supabase (Fixed v3). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
AI-powered Telegram bot for effortless expense tracking. Send receipts, voice messages, or text - the bot automatically extracts and categorizes your expenses. 📸 Receipt & Invoice OCR - Send photos of