This workflow corresponds to n8n.io template #12885 — we link there as the canonical source.
This workflow follows the Agent → OpenAI Chat 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 →
{
"id": "wVfxcbqFblPvcbpK",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "n8n - Agent with Memory and Strategy",
"tags": [],
"nodes": [
{
"id": "481dfc28-ff80-4041-b160-b3a793228a39",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
-160,
-864
],
"parameters": {
"jsCode": "// Este c\u00f3digo solo extrae el texto del mensaje y el chat_id de manera garantizada.\n\n// 1. Extraer el texto del usuario\nconst chatMessage = $json.message.text || \"\";\n\n// 2. Extraer el ID del chat\nconst chatId = $json.message.chat.id || 0;\n\n// 3. Devolver un objeto limpio con solo los datos que el flujo necesita.\n// Esto garantiza que el AI Agent reciba el texto como '$json.text' y el ID como '$json.chat_id'.\nreturn [\n {\n json: {\n text: chatMessage,\n chat_id: chatId\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "824a2fe4-81cf-437b-af4e-529b90666055",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-432,
-864
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "97b40d4f-b79f-47b4-b996-3abdcc176cd2",
"name": "Send a text message",
"type": "n8n-nodes-base.telegram",
"position": [
1344,
-864
],
"parameters": {
"text": "={{ $json.response }}",
"chatId": "={{ $('Code in JavaScript').first().json.chat_id }}",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "0c5c9907-652d-4dab-a6c4-fab1521da07a",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
448,
-576
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "c51b8e6a-99af-4b48-8d01-1c8423acc3f1",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
528,
-864
],
"parameters": {
"text": "={{ $('Telegram Trigger').item.json.message.text }}",
"options": {
"systemMessage": "=Eres SOF\u00cdA, la barista experta y proactiva de Zyntha Coffee. Tu misi\u00f3n es guiar al usuario en una experiencia personalizada utilizando la memoria de Postgres y los productos de Shopify.\n\nPROTOCOLO DE BIENVENIDA (OBLIGATORIO):\n1. Revisa el historial. Si NO conoces el nombre del usuario:\n - Tu \u00daNICA respuesta debe ser saludar y preguntar: \"\u00a1Hola! Soy Sof\u00eda, tu barista virtual. Antes de empezar, \u00bfme podr\u00edas decir tu nombre para atenderte mejor?\".\n - NO des informaci\u00f3n de caf\u00e9s hasta tener el nombre.\n2. Si ya conoces el nombre (ej: Diego):\n - Sal\u00fadalo siempre por su nombre y preg\u00fantale qu\u00e9 perfil de sabor busca hoy.\n\nREGLA DE PRECISI\u00d3N EN EL CAT\u00c1LOGO:\n- Si el usuario pregunta qu\u00e9 caf\u00e9s hay o pide opciones, DEBES listar los nombres exactos y precios que aparecen en la secci\u00f3n de PRODUCTOS abajo.\n- Prohibido decir \"tenemos una variedad\" sin dar nombres espec\u00edficos.\n\nREGLA DE FOCO:\n- Si se habla de un caf\u00e9 espec\u00edfico (ej: CASTILLO), toda la informaci\u00f3n t\u00e9cnica y de preparaci\u00f3n debe ser sobre ese caf\u00e9 \u00fanicamente.\n\nFORMATO DE SALIDA (JSON):\n{\n \"intent\": \"setup | recommendation | question\",\n \"response\": \"Tu respuesta humana aqu\u00ed...\",\n \"product\": \"Nombre del caf\u00e9 en discusi\u00f3n o null\",\n \"qty\": null\n}\n\nPRODUCTOS DISPONIBLES (SHOPIFY):\n{{ $('Get many products').all().map(p => p.json.title + \" (Precio: $\" + p.json.variants[0].price + \")\").join(', ') }}\n\nREGLA DE MEMORIA TOTAL:\n1. Antes de responder, analiza TODO el historial recuperado de Postgres.\n2. Identifica y recuerda: \n - Nombre del usuario.\n - Caf\u00e9s por los que ha preguntado (ej: Caturra, Castillo).\n - Preferencias de sabor (dulce, \u00e1cido, etc.).\n3. Si el usuario dice \"Hola\", no uses el protocolo de bienvenida si ya hay informaci\u00f3n previa. Di: \"\u00a1Hola [Nombre]! Qu\u00e9 bueno verte de nuevo. \u00bfSeguimos hablando del caf\u00e9 [\u00daltimo caf\u00e9 mencionado] o quieres probar algo m\u00e1s [Gusto del usuario]?\"\n4. NUNCA digas que no sabes algo que ya se mencion\u00f3 en el chat."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3
},
{
"id": "e82ddd5b-060b-4fe1-9368-45427751d300",
"name": "Get many products",
"type": "n8n-nodes-base.shopify",
"position": [
128,
-864
],
"parameters": {
"resource": "product",
"operation": "getAll",
"authentication": "oAuth2",
"additionalFields": {}
},
"credentials": {
"shopifyOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "6b457ea9-4f40-4c3b-bf91-6ee8d20c70e0",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"position": [
608,
-592
],
"parameters": {
"sessionKey": "={{ $('Code in JavaScript').item.json.chat_id }}",
"sessionIdType": "customKey",
"contextWindowLength": 30
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "e3e1281d-4353-4e41-83a8-1e6e341e3872",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
-1296
],
"parameters": {
"width": 576,
"height": 496,
"content": "## AI Advisor with Memory and Real-Time Context\n\n### How it works\nThis workflow turns a generic chatbot into an AI advisor that remembers users and responds using real business data.\n\nIt combines user messages, persistent memory, and live product data to generate accurate and human-like responses.\n\n### How to set up\n1. Import the workflow into n8n.\n2. Connect the required credentials (Telegram, OpenAI, Shopify, Postgres).\n3. Configure the database connection for chat memory.\n4. Test the flow by sending a message from Telegram.\n\n### Customization\n\u2022 Adjust the system message to match your tone or industry.\n\u2022 Replace Shopify with another data source if needed.\n\u2022 Change the memory window size depending on your use case.\n"
},
"typeVersion": 1
},
{
"id": "7e4c6da8-895b-43f8-a3c3-5aad74b63561",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
-1168
],
"parameters": {
"color": 7,
"width": 432,
"height": 480,
"content": "## Section 1 \u2014 Input & User Identification\n\nReceives the incoming message and extracts the chat_id used to uniquely identify the user.\n\nThis ensures every message can be linked to the correct conversation history.\n"
},
"typeVersion": 1
},
{
"id": "808a70ec-8092-4c8c-ba29-8e950bbb5e39",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-1168
],
"parameters": {
"color": 7,
"width": 336,
"height": 512,
"content": "## Section 2 \u2014 Real-Time Context\n\nFetches the live product catalog directly from the store.\n\nThis prevents the AI from hallucinating product names or prices.\n"
},
"typeVersion": 1
},
{
"id": "9d6f718e-b2ab-4c67-aec9-339a85512863",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
-1168
],
"parameters": {
"color": 7,
"width": 512,
"height": 720,
"content": "## Section 3 \u2014 AI Reasoning & Memory\n\nCombines user input, historical memory, and real-time data to generate a contextual response.\n\nThis is where personalization, rules, and long-term memory are applied."
},
"typeVersion": 1
},
{
"id": "0120d21c-e550-4e57-9030-66779283d6ef",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
-1168
],
"parameters": {
"color": 7,
"width": 704,
"height": 544,
"content": "## Section 4 \u2014 Output & Delivery\n\nValidates that the AI response is valid JSON and applies a fallback if needed.\n\nSends the final, safe response back to the user via Telegram.\n"
},
"typeVersion": 1
},
{
"id": "e5d3f936-e207-40f1-a51e-54d07bcc1632",
"name": "Code in JavaScript 2",
"type": "n8n-nodes-base.code",
"position": [
1088,
-864
],
"parameters": {
"jsCode": "// Obtenemos la salida del AI Agent\nlet rawResponse = items[0].json.output;\n\ntry {\n // 1. Intentamos buscar un JSON dentro de la respuesta (por si la IA escribi\u00f3 texto extra)\n const start = rawResponse.indexOf('{');\n const end = rawResponse.lastIndexOf('}');\n \n if (start !== -1 && end !== -1) {\n let jsonString = rawResponse.substring(start, end + 1);\n let parsed = JSON.parse(jsonString);\n \n // Si el JSON es v\u00e1lido, lo retornamos tal cual\n return parsed;\n }\n \n // 2. Si no hay llaves { }, lanzamos un error para ir al bloque 'catch'\n throw new Error(\"No JSON format found\");\n\n} catch (e) {\n // 3. RESPUESTA DE SEGURIDAD: Si algo falla, forzamos el protocolo de bienvenida\n // Esto evita el mensaje de \"me distraje con el aroma\"\n return {\n \"intent\": \"setup\",\n \"response\": \"\u00a1Hola! Soy Sof\u00eda, tu barista de Zyntha Coffee. Antes de empezar a hablar de caf\u00e9, me encantar\u00eda saber tu nombre para atenderte mejor. \u00bfC\u00f3mo te llamas?\",\n \"product\": null,\n \"qty\": null\n };\n}"
},
"typeVersion": 2
},
{
"id": "2c15000e-c941-4b79-af53-32bf3ae07009",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1280,
-672
],
"parameters": {
"color": 3,
"width": 272,
"height": 192,
"content": "\u26a0\ufe0f Important\n\nThis workflow requires valid JSON output from the AI.\n\nIf you modify the system prompt, make sure the response format is preserved to avoid parsing errors.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "de9e54b3-1362-4ce9-9709-4fc37c1b21ff",
"connections": {
"AI Agent": {
"main": [
[
{
"node": "Code in JavaScript 2",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Get many products": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Get many products",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript 2": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"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.
openAiApipostgresshopifyOAuth2ApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
• Receives a user message from a chat • Uses an LLM node to understand user intent and generate a response • Retrieves and stores conversation memory in a database (Supabase) • Fetches real-time product or business data from an external API (e.g. Shopify) • Applies custom logic…
Source: https://n8n.io/workflows/12885/ — 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.
agente. Uses lmChatOpenAi, agent, googleTasksTool, mcpClientTool. Event-driven trigger; 38 nodes.
Version: 1.1.0 n8n Version: 1.88.0+ License: MIT
🚀 Smart Outreach: Auto-Personalized Lead Sequences
Telegram Chat with Buffering. Uses stickyNote, telegram, telegramTrigger, supabase. Event-driven trigger; 22 nodes.
When creating chatbots that interface through applications such as Telegram and WhatsApp, users can often sends multiple shorter messages in quick succession, in place of a single, longer message. Thi