This workflow follows the Datatable → 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": "Telegram Intelligence Agent \u2014 Bot Control",
"nodes": [
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
-1300,
0
],
"id": "00000000-0000-4000-8000-000000000001",
"name": "Telegram Trigger"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "00000000-0000-4000-8000-000000000002",
"name": "openrouter_model",
"value": "={{ $vars.OPENROUTER_MODEL || \"openai/gpt-4.1-mini\" }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-1080,
0
],
"id": "00000000-0000-4000-8000-000000000003",
"name": "Runtime Config"
},
{
"parameters": {
"jsCode": "\nconst raw = String($json.message?.text || '').trim();\nconst chat_id = String($json.message?.chat?.id || '');\nconst user_id = String($json.message?.from?.id || $json.message?.chat?.id || '');\nconst parts = raw.split(/\\s+/); const command = (parts.shift() || '').split('@')[0].toLowerCase();\nconst help = \"Welcome to Telegram Intelligence Agent!\\n\\nThis bot monitors public Telegram channels and summarizes important posts.\\n\\nCommands:\\n\\n/add @channel\\nAdd a public channel\\n\\n/remove @channel\\nStop monitoring a channel\\n\\n/list\\nShow active channels\\n\\n/latest @channel [hours] [min_views]\\nShow recent posts\\n\\n/ask your question\\nAsk about collected posts\\n\\n/digest\\nGet the latest 24-hour digest\\n\\n/alert add keyword\\nCreate a keyword alert\\n\\n/alert list\\nShow your alerts\\n\\n/alert remove ALERT_ID\\nRemove an alert\";\nconst normalize = (v) => { const u=String(v||'').trim().replace(/^https?:\\/\\/t\\.me\\/(?:s\\/)?/i,'').replace(/^@/,'').replace(/\\/$/,'').toLowerCase(); return /^[a-z][a-z0-9_]{3,31}$/.test(u)?u:null; };\nconst reply = (text) => [{json:{chat_id,user_id,action:'reply',reply:text}}];\nif (command === '/start') return reply(help);\nif (command === '/help') return reply(help);\nif (command === '/list') return parts.length?reply('Correct format: /list'):[{json:{chat_id,user_id,action:'list'}}];\nif (command === '/digest') return parts.length?reply('Correct format: /digest'):[{json:{chat_id,user_id,action:'digest'}}];\nif (command === '/add' || command === '/remove') { const channel=parts.length===1?normalize(parts[0]):null; return channel?[{json:{chat_id,user_id,action:command.slice(1),channel_username:channel}}]:reply('Invalid public channel username. Example: @telegram'); }\nif (command === '/latest') { const channel=normalize(parts[0]); const hours=parts[1]===undefined?24:Number(parts[1]); const min_views=parts[2]===undefined?0:Number(parts[2]); if(parts.length<1||parts.length>3||!channel)return reply('Correct format: /latest @channel [hours] [min_views]'); if(!Number.isInteger(hours)||hours<1||hours>720)return reply('Hours must be an integer between 1 and 720.'); if(!Number.isInteger(min_views)||min_views<0)return reply('Minimum views must be a non-negative integer.'); return [{json:{chat_id,user_id,action:'latest',channel_username:channel,hours,min_views}}]; }\nif (command === '/ask') { const question=parts.join(' ').trim(); return question.length>=3?[{json:{chat_id,user_id,action:'ask',question}}]:reply('Write a clear question after /ask.'); }\nif (command === '/alert') { const sub=(parts.shift()||'').toLowerCase(); if(sub==='list'&&!parts.length)return [{json:{chat_id,user_id,action:'alert_list'}}]; if(sub==='add'){const keyword=parts.join(' ').trim();return keyword.length>=2&&keyword.length<=80?[{json:{chat_id,user_id,action:'alert_add',keyword}}]:reply('Correct format: /alert add keyword (2 to 80 characters)');} if(sub==='remove'&&parts.length===1&&/^[a-z0-9-]{6,64}$/i.test(parts[0]))return [{json:{chat_id,user_id,action:'alert_remove',alert_id:parts[0]}}]; return reply('Correct format: /alert add keyword | /alert list | /alert remove ALERT_ID'); }\nreturn reply(help);"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-850,
0
],
"id": "00000000-0000-4000-8000-000000000004",
"name": "Parse Command"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "reply",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "reply"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "add",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "add"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "remove",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "remove"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "list",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "list"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "latest",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "latest"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "ask",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "ask"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "digest",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "digest"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "alert_add",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "alert_add"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "alert_list",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "alert_list"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.action }}",
"rightValue": "alert_remove",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "alert_remove"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.3,
"position": [
-620,
0
],
"id": "00000000-0000-4000-8000-000000000005",
"name": "Route Command"
},
{
"parameters": {
"resource": "message",
"operation": "sendMessage",
"chatId": "={{ $json.chat_id }}",
"text": "={{ String($json.reply || \"Internal error\").slice(0, 4000).replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\") }}",
"additionalFields": {
"appendAttribution": false,
"parse_mode": "HTML"
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1500,
0
],
"id": "00000000-0000-4000-8000-000000000006",
"name": "Send Telegram Reply",
"onError": "continueRegularOutput"
},
{
"parameters": {
"resource": "row",
"operation": "rowExists",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
-500
],
"id": "00000000-0000-4000-8000-000000000007",
"name": "Subscription Exists?"
},
{
"parameters": {
"resource": "row",
"operation": "rowNotExists",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
-400
],
"id": "00000000-0000-4000-8000-000000000008",
"name": "Subscription New?"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'This channel is already active: @'+p.channel_username}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
-500
],
"id": "00000000-0000-4000-8000-000000000009",
"name": "Duplicate Subscription Reply"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{user_id:p.user_id,chat_id:p.chat_id,channel_username:p.channel_username,status:'active',added_at:new Date().toISOString(),last_checked_message_id:0}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
-400
],
"id": "00000000-0000-4000-8000-000000000010",
"name": "Prepare Subscription"
},
{
"parameters": {
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
140,
-400
],
"id": "00000000-0000-4000-8000-000000000011",
"name": "Insert Subscription"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'Channel @'+p.channel_username+' was added to monitoring.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
380,
-400
],
"id": "00000000-0000-4000-8000-000000000012",
"name": "Added Reply"
},
{
"parameters": {
"resource": "row",
"operation": "rowExists",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
-280
],
"id": "00000000-0000-4000-8000-000000000013",
"name": "Active Subscription Exists?"
},
{
"parameters": {
"resource": "row",
"operation": "rowNotExists",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
-180
],
"id": "00000000-0000-4000-8000-000000000014",
"name": "Active Subscription Missing?"
},
{
"parameters": {
"jsCode": "return [{json:{status:'inactive'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
-280
],
"id": "00000000-0000-4000-8000-000000000015",
"name": "Prepare Remove"
},
{
"parameters": {
"resource": "row",
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
140,
-280
],
"id": "00000000-0000-4000-8000-000000000016",
"name": "Deactivate Subscription"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'Monitoring stopped for @'+p.channel_username+'.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
380,
-280
],
"id": "00000000-0000-4000-8000-000000000017",
"name": "Removed Reply"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'This channel is not in your active watchlist.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
-180
],
"id": "00000000-0000-4000-8000-000000000018",
"name": "Missing Subscription Reply"
},
{
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "subscriptions",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "user_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.user_id }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
},
"returnAll": true
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
-60
],
"id": "00000000-0000-4000-8000-000000000019",
"name": "Get User Subscriptions",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const rows=$input.all().map(i=>i.json).filter(r=>r.channel_username); const body=rows.length?'Active channels:\\n'+rows.map(r=>'- @'+r.channel_username).join('\\n'):'You have no active channels.'; return [{json:{chat_id:p.chat_id,reply:body}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
-60
],
"id": "00000000-0000-4000-8000-000000000020",
"name": "Format Subscription List"
},
{
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "messages",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "channel_username",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.channel_username }}"
}
]
},
"returnAll": true,
"orderBy": true,
"orderByColumn": "published_at",
"orderByDirection": "DESC"
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
80
],
"id": "00000000-0000-4000-8000-000000000021",
"name": "Get Channel Messages",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const cutoff=Date.now()-p.hours*3600000; const rows=$input.all().map(i=>i.json).filter(r=>r.message_id&&new Date(r.published_at).getTime()>=cutoff&&Number(r.views||0)>=p.min_views).slice(0,10); const body=rows.length?rows.map(r=>'- '+(r.summary||r.text||'[Post without text]').slice(0,240)+'\\n'+r.message_url+' - Views: '+Number(r.views||0).toLocaleString('en-US')).join('\\n\\n'):'No posts matched this filter.'; return [{json:{chat_id:p.chat_id,reply:body}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
80
],
"id": "00000000-0000-4000-8000-000000000022",
"name": "Format Latest"
},
{
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "messages",
"mode": "name"
},
"matchType": "allConditions",
"returnAll": false,
"limit": 500,
"orderBy": true,
"orderByColumn": "published_at",
"orderByDirection": "DESC"
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
240
],
"id": "00000000-0000-4000-8000-000000000023",
"name": "Get Recent Context",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const digits=v=>String(v||'').replace(/[\\u06f0-\\u06f9]/g,d=>String('\\u06f0\\u06f1\\u06f2\\u06f3\\u06f4\\u06f5\\u06f6\\u06f7\\u06f8\\u06f9'.indexOf(d))).replace(/[\\u0660-\\u0669]/g,d=>String('\\u0660\\u0661\\u0662\\u0663\\u0664\\u0665\\u0666\\u0667\\u0668\\u0669'.indexOf(d))); const words={'\\u06cc\\u06a9':1,'\\u062f\\u0648':2,'\\u0633\\u0647':3,'\\u0686\\u0647\\u0627\\u0631':4,'\\u067e\\u0646\\u062c':5,'\\u0634\\u0634':6,'\\u0647\\u0641\\u062a':7,'\\u0647\\u0634\\u062a':8,'\\u0646\\u0647':9,'\\u062f\\u0647':10,'\\u0628\\u06cc\\u0633\\u062a':20,'\\u0633\\u06cc':30,'\\u0686\\u0647\\u0644':40,'\\u067e\\u0646\\u062c\\u0627\\u0647':50,'\\u0635\\u062f':100}; const num='(\\\\d{1,4}|\\u06cc\\u06a9|\\u062f\\u0648|\\u0633\\u0647|\\u0686\\u0647\\u0627\\u0631|\\u067e\\u0646\\u062c|\\u0634\\u0634|\\u0647\\u0641\\u062a|\\u0647\\u0634\\u062a|\\u0646\\u0647|\\u062f\\u0647|\\u0628\\u06cc\\u0633\\u062a|\\u0633\\u06cc|\\u0686\\u0647\\u0644|\\u067e\\u0646\\u062c\\u0627\\u0647|\\u0635\\u062f)'; const nv=v=>words[v]||Number(v)||null; const question=digits(String(p.question||'').replace(/\\u0645\\u0647\\u0646/g,'\\u0645\\u0647\\u0645')).trim(); const last=question.match(new RegExp('(?:\\u0622\\u062e\\u0631\\u06cc\\u0646\\\\s*)?'+num+'\\\\s*\\u067e\\u06cc\\u0627\\u0645(?:\\\\s*(?:\\u0627\\u062e\\u06cc\\u0631|\\u0622\\u062e\\u0631))?')); const period=question.match(new RegExp(num+'\\\\s*(\\u0633\\u0627\\u0639\\u062a|\\u0631\\u0648\\u0632|\\u0647\\u0641\\u062a\\u0647|\\u0645\\u0627\\u0647)\\\\s*(?:\\u0627\\u062e\\u06cc\\u0631|\\u06af\\u0630\\u0634\\u062a\\u0647)')); const channel=question.match(/@([a-z][a-z0-9_]{3,31})/i); const views=question.match(/(?:\\u062d\\u062f\\u0627\\u0642\\u0644|\\u0628\\u06cc\\u0634 \\u0627\\u0632|\\u0628\\u0627\\u0644\\u0627\\u06cc|\\u0628\\u0627\\u0644\\u0627\\u062a\\u0631 \\u0627\\u0632)\\s*([0-9][0-9,._]*)\\s*(?:\\u0628\\u0627\\u0632\\u062f\\u06cc\\u062f|\\u0648\\u06cc\\u0648)/i); const mult={'\\u0633\\u0627\\u0639\\u062a':1,'\\u0631\\u0648\\u0632':24,'\\u0647\\u0641\\u062a\\u0647':168,'\\u0645\\u0627\\u0647':720}; const plan={task:/(\\u0686\\u0646\\u062f\\s*\\u062a\\u0627|\\u0686\\u0646\\u062f\\s*\\u067e\\u06cc\\u0627\\u0645|\\u062a\\u0639\\u062f\\u0627\\u062f)/.test(question)?'count':/(\\u062e\\u0644\\u0627\\u0635\\u0647|\\u062c\\u0645\\u0639[\\u200c -]?\\u0628\\u0646\\u062f\\u06cc)/.test(question)?'summarize':'answer',last_n:last?Math.min(100,nv(last[1])):null,hours:period?Math.min(8760,nv(period[1])*mult[period[2]]):(/\\u0627\\u0645\\u0631\\u0648\\u0632/.test(question)?24:null),channel:channel?channel[1].toLowerCase():null,min_views:views?Number(views[1].replace(/[,._]/g,'')):0}; let rows=$input.all().map(i=>i.json).filter(r=>r.message_id&&r.message_url).sort((a,b)=>new Date(b.published_at)-new Date(a.published_at)); if(plan.hours){const cutoff=Date.now()-plan.hours*3600000;rows=rows.filter(r=>new Date(r.published_at).getTime()>=cutoff);} if(plan.channel)rows=rows.filter(r=>String(r.channel_username||'').toLowerCase()===plan.channel); if(plan.min_views)rows=rows.filter(r=>Number(r.views||0)>=plan.min_views); const filtered_count=rows.length; const cap=plan.last_n||(plan.hours||plan.channel||plan.min_views?100:40); rows=rows.slice(0,cap); if(!rows.length)return [{json:{qa_state:'no_context',chat_id:p.chat_id,reply:'No stored posts matched the question filters.'}}]; const context=rows.map((r,i)=>({id:i+1,channel:r.channel_username,text:(r.text||'').slice(0,600),summary:(r.summary||'').slice(0,400),topic:r.topic||'',published_at:r.published_at,views:Number(r.views||0),url:r.message_url})); const payload={question,plan,candidate_count:context.length,truncated:filtered_count>context.length,context}; return [{json:{qa_state:'call',chat_id:p.chat_id,question,plan,context,candidate_count:context.length,filtered_count,truncated:filtered_count>context.length,request:{model:$('Runtime Config').first().json.openrouter_model,temperature:0.1,reasoning:{effort:'none'},response_format:{type:'json_object'},messages:[{role:'system',content:'\\u0641\\u0642\\u0637 \\u0627\\u0632 context \\u067e\\u0627\\u0633\\u062e \\u0628\\u062f\\u0647. \\u0641\\u06cc\\u0644\\u062a\\u0631\\u0647\\u0627\\u06cc plan \\u0642\\u0628\\u0644\\u0627\\u064b \\u062a\\u0648\\u0633\\u0637 \\u0628\\u0631\\u0646\\u0627\\u0645\\u0647 \\u0627\\u0639\\u0645\\u0627\\u0644 \\u0634\\u062f\\u0647\\u200c\\u0627\\u0646\\u062f. \\u0647\\u0645\\u0647 \\u067e\\u06cc\\u0627\\u0645\\u200c\\u0647\\u0627\\u06cc \\u0645\\u0631\\u062a\\u0628\\u0637 \\u0628\\u0627 \\u0645\\u0648\\u0636\\u0648\\u0639 \\u0633\\u0624\\u0627\\u0644 \\u0631\\u0627 \\u062f\\u0631 matched_source_ids \\u0628\\u0631\\u06af\\u0631\\u062f\\u0627\\u0646 \\u0648 \\u062d\\u062f\\u0627\\u06a9\\u062b\\u0631 \\u06f8 \\u0645\\u0646\\u0628\\u0639 \\u0627\\u0635\\u0644\\u06cc \\u0631\\u0627 \\u062f\\u0631 source_ids \\u0628\\u062f\\u0647. \\u0628\\u0631\\u0627\\u06cc task=count \\u0634\\u0645\\u0627\\u0631\\u0634 \\u0631\\u0627 \\u062d\\u062f\\u0633 \\u0646\\u0632\\u0646\\u061b \\u0641\\u0642\\u0637 \\u0634\\u0646\\u0627\\u0633\\u0647 \\u0647\\u0645\\u0647 \\u0645\\u0648\\u0627\\u0631\\u062f \\u0645\\u0631\\u062a\\u0628\\u0637 \\u0631\\u0627 \\u0628\\u062f\\u0647 \\u062a\\u0627 \\u0628\\u0631\\u0646\\u0627\\u0645\\u0647 \\u0628\\u0634\\u0645\\u0627\\u0631\\u062f. \\u0628\\u0631\\u0627\\u06cc task=summarize \\u06cc\\u06a9 \\u062e\\u0644\\u0627\\u0635\\u0647 \\u0641\\u0627\\u0631\\u0633\\u06cc \\u0641\\u0634\\u0631\\u062f\\u0647 \\u0628\\u0633\\u0627\\u0632. \\u0641\\u0642\\u0637 JSON: {has_answer:boolean,answer:string,matched_source_ids:number[],source_ids:number[]}. \\u0634\\u0646\\u0627\\u0633\\u0647 \\u062e\\u0627\\u0631\\u062c context \\u0646\\u0633\\u0627\\u0632.'},{role:'user',content:JSON.stringify(payload)}]}}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
240
],
"id": "00000000-0000-4000-8000-000000000024",
"name": "Build QA Request"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.qa_state }}",
"rightValue": "call",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "call"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.qa_state }}",
"rightValue": "no_context",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "no_context"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.3,
"position": [
140,
240
],
"id": "00000000-0000-4000-8000-000000000025",
"name": "Route QA"
},
{
"parameters": {
"method": "POST",
"url": "https://openrouter.ai/api/v1/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"specifyHeaders": "keypair",
"headerParameters": {
"parameters": [
{
"name": "Accept-Encoding",
"value": "identity"
}
]
},
"sendBody": true,
"contentType": "json",
"specifyBody": "json",
"jsonBody": "={{ $json.request }}",
"options": {
"timeout": 30000,
"response": {
"response": {
"neverError": true,
"responseFormat": "json"
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.5,
"position": [
380,
200
],
"id": "00000000-0000-4000-8000-000000000026",
"name": "OpenRouter QA",
"onError": "continueRegularOutput"
},
{
"parameters": {
"jsCode": "const req=$('Build QA Request').first().json; const question=req.question||String($('Parse Command').first().json.question||'').replace(/\\u0645\\u0647\\u0646/g,'\\u0645\\u0647\\u0645').trim(); const latest=/\\u0622\\u062e\\u0631\\u06cc\\u0646\\s+\\u067e\\u06cc\\u0627\\u0645/.test(question); const fallback=()=>{const first=req.context?.[0];if(latest&&first){const text=String(first.summary||first.text||'').trim().slice(0,1200);return [{json:{chat_id:req.chat_id,reply:'The latest post is about:\\n'+text+'\\n\\nSource:\\n'+first.url}}];}return [{json:{chat_id:req.chat_id,reply:$json.error?'The AI service is temporarily unavailable. Please try again later.':'There is not enough information in the stored posts.'}}];}; if($json.error)return fallback(); const message=$json.choices?.[0]?.message||{}; let raw=message.content||message.reasoning||$json.output_text||''; if(Array.isArray(raw))raw=raw.map(x=>x?.text||x?.content||'').join(''); let out=typeof raw==='object'&&raw?raw:null; if(!out&&typeof raw==='string'){raw=raw.trim().replace(/^```(?:json)?\\s*/i,'').replace(/\\s*```$/,'');try{out=JSON.parse(raw);}catch{const a=raw.indexOf('{'),b=raw.lastIndexOf('}');if(a>=0&&b>a)try{out=JSON.parse(raw.slice(a,b+1));}catch{}}} if(!out)return fallback(); const valid=values=>[...new Set(Array.isArray(values)?values:[])].map(Number).filter(x=>Number.isInteger(x)&&req.context[x-1]); const matches=valid(out.matched_source_ids||out.source_ids); const sources=valid(out.source_ids||matches).slice(0,8); const links=sources.map(x=>req.context[x-1].url); const note=req.truncated?'\\n\\nNote: Only '+req.candidate_count+' newer posts were checked to control API usage.':''; if(req.plan?.task==='count'){const detail=matches.length&&out.answer?'\\n'+String(out.answer).slice(0,1800):'';return [{json:{chat_id:req.chat_id,reply:'Related posts: '+matches.length+' out of '+req.candidate_count+' checked posts.'+detail+(links.length?'\\n\\nSample sources:\\n'+links.join('\\n'):'')+note}}];} if(req.plan?.task==='summarize'){if(!matches.length)return [{json:{chat_id:req.chat_id,reply:'No related posts were found in the requested scope.'+note}}];if(!out.answer)return fallback();return [{json:{chat_id:req.chat_id,reply:String(out.answer).slice(0,2800)+(links.length?'\\n\\nSources:\\n'+links.join('\\n'):'')+note}}];} if(!out.has_answer||!out.answer||!links.length)return fallback(); return [{json:{chat_id:req.chat_id,reply:String(out.answer).slice(0,2800)+'\\n\\nSources:\\n'+links.join('\\n')+note}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
620,
200
],
"id": "00000000-0000-4000-8000-000000000027",
"name": "Format QA Reply"
},
{
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "messages",
"mode": "name"
},
"matchType": "allConditions",
"returnAll": true,
"orderBy": true,
"orderByColumn": "published_at",
"orderByDirection": "DESC"
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
420
],
"id": "00000000-0000-4000-8000-000000000028",
"name": "Get Digest Messages",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const cutoff=Date.now()-24*3600000; const rows=$input.all().map(i=>i.json).filter(r=>r.message_id&&new Date(r.published_at).getTime()>=cutoff).sort((a,b)=>Number(b.importance_score||0)-Number(a.importance_score||0)).slice(0,10); const body=rows.length?'Latest 24-hour digest:\\n\\n'+rows.map(r=>'- ['+(r.topic||'General')+'] '+(r.summary||r.text||'[Post without text]').slice(0,260)+'\\n'+r.message_url).join('\\n\\n'):'No posts were stored in the last 24 hours.'; return [{json:{chat_id:p.chat_id,reply:body}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
420
],
"id": "00000000-0000-4000-8000-000000000029",
"name": "Format On-demand Digest"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const alert_id=Date.now().toString(36)+'-'+Math.random().toString(36).slice(2,10); return [{json:{alert_id,chat_id:p.chat_id,channel_username:'*',keyword:p.keyword,status:'active',created_at:new Date().toISOString()}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-380,
560
],
"id": "00000000-0000-4000-8000-000000000030",
"name": "Prepare Alert"
},
{
"parameters": {
"resource": "row",
"operation": "insert",
"dataTableId": {
"__rl": true,
"value": "alerts",
"mode": "name"
},
"matchType": "allConditions",
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-100,
560
],
"id": "00000000-0000-4000-8000-000000000031",
"name": "Insert Alert"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'Alert created for keyword: '+p.keyword+'\\nAlert ID: '+$json.alert_id}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
140,
560
],
"id": "00000000-0000-4000-8000-000000000032",
"name": "Alert Added Reply"
},
{
"parameters": {
"resource": "row",
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "alerts",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "chat_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.chat_id }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
},
"returnAll": true
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
700
],
"id": "00000000-0000-4000-8000-000000000033",
"name": "Get User Alerts",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; const rows=$input.all().map(i=>i.json).filter(r=>r.alert_id); return [{json:{chat_id:p.chat_id,reply:rows.length?'Active alerts:\\n'+rows.map(r=>'- '+r.alert_id+' - '+r.keyword).join('\\n'):'You have no active alerts.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
700
],
"id": "00000000-0000-4000-8000-000000000034",
"name": "Format Alert List"
},
{
"parameters": {
"resource": "row",
"operation": "rowExists",
"dataTableId": {
"__rl": true,
"value": "alerts",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "alert_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.alert_id }}"
},
{
"keyName": "chat_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.chat_id }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
840
],
"id": "00000000-0000-4000-8000-000000000035",
"name": "Alert Exists?"
},
{
"parameters": {
"resource": "row",
"operation": "rowNotExists",
"dataTableId": {
"__rl": true,
"value": "alerts",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "alert_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.alert_id }}"
},
{
"keyName": "chat_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.chat_id }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
-380,
940
],
"id": "00000000-0000-4000-8000-000000000036",
"name": "Alert Missing?"
},
{
"parameters": {
"jsCode": "return [{json:{status:'inactive'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
840
],
"id": "00000000-0000-4000-8000-000000000037",
"name": "Prepare Alert Remove"
},
{
"parameters": {
"resource": "row",
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "alerts",
"mode": "name"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "alert_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.alert_id }}"
},
{
"keyName": "chat_id",
"condition": "eq",
"keyValue": "={{ $('Parse Command').first().json.chat_id }}"
},
{
"keyName": "status",
"condition": "eq",
"keyValue": "active"
}
]
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
140,
840
],
"id": "00000000-0000-4000-8000-000000000038",
"name": "Deactivate Alert"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'Alert '+p.alert_id+' was removed.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
380,
840
],
"id": "00000000-0000-4000-8000-000000000039",
"name": "Alert Removed Reply"
},
{
"parameters": {
"jsCode": "const p=$('Parse Command').first().json; return [{json:{chat_id:p.chat_id,reply:'No active alert was found with this ID.'}}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-100,
940
],
"id": "00000000-0000-4000-8000-000000000040",
"name": "Alert Missing Reply"
}
],
"connections": {
"Telegram Trigger": {
"main": [
[
{
"node": "Runtime Config",
"type": "main",
"index": 0
}
]
]
},
"Runtime Config": {
"main": [
[
{
"node": "Parse Command",
"type": "main",
"index": 0
}
]
]
},
"Parse Command": {
"main": [
[
{
"node": "Route Command",
"type": "main",
"index": 0
}
]
]
},
"Route Command": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
],
[
{
"node": "Subscription Exists?",
"type": "main",
"index": 0
},
{
"node": "Subscription New?",
"type": "main",
"index": 0
}
],
[
{
"node": "Active Subscription Exists?",
"type": "main",
"index": 0
},
{
"node": "Active Subscription Missing?",
"type": "main",
"index": 0
}
],
[
{
"node": "Get User Subscriptions",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Channel Messages",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Recent Context",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Digest Messages",
"type": "main",
"index": 0
}
],
[
{
"node": "Prepare Alert",
"type": "main",
"index": 0
}
],
[
{
"node": "Get User Alerts",
"type": "main",
"index": 0
}
],
[
{
"node": "Alert Exists?",
"type": "main",
"index": 0
},
{
"node": "Alert Missing?",
"type": "main",
"index": 0
}
]
]
},
"Subscription Exists?": {
"main": [
[
{
"node": "Duplicate Subscription Reply",
"type": "main",
"index": 0
}
]
]
},
"Duplicate Subscription Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Subscription New?": {
"main": [
[
{
"node": "Prepare Subscription",
"type": "main",
"index": 0
}
]
]
},
"Prepare Subscription": {
"main": [
[
{
"node": "Insert Subscription",
"type": "main",
"index": 0
}
]
]
},
"Insert Subscription": {
"main": [
[
{
"node": "Added Reply",
"type": "main",
"index": 0
}
]
]
},
"Added Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Active Subscription Exists?": {
"main": [
[
{
"node": "Prepare Remove",
"type": "main",
"index": 0
}
]
]
},
"Prepare Remove": {
"main": [
[
{
"node": "Deactivate Subscription",
"type": "main",
"index": 0
}
]
]
},
"Deactivate Subscription": {
"main": [
[
{
"node": "Removed Reply",
"type": "main",
"index": 0
}
]
]
},
"Removed Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Active Subscription Missing?": {
"main": [
[
{
"node": "Missing Subscription Reply",
"type": "main",
"index": 0
}
]
]
},
"Missing Subscription Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Get User Subscriptions": {
"main": [
[
{
"node": "Format Subscription List",
"type": "main",
"index": 0
}
]
]
},
"Format Subscription List": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Get Channel Messages": {
"main": [
[
{
"node": "Format Latest",
"type": "main",
"index": 0
}
]
]
},
"Format Latest": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Get Recent Context": {
"main": [
[
{
"node": "Build QA Request",
"type": "main",
"index": 0
}
]
]
},
"Build QA Request": {
"main": [
[
{
"node": "Route QA",
"type": "main",
"index": 0
}
]
]
},
"Route QA": {
"main": [
[
{
"node": "OpenRouter QA",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"OpenRouter QA": {
"main": [
[
{
"node": "Format QA Reply",
"type": "main",
"index": 0
}
]
]
},
"Format QA Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Get Digest Messages": {
"main": [
[
{
"node": "Format On-demand Digest",
"type": "main",
"index": 0
}
]
]
},
"Format On-demand Digest": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Prepare Alert": {
"main": [
[
{
"node": "Insert Alert",
"type": "main",
"index": 0
}
]
]
},
"Insert Alert": {
"main": [
[
{
"node": "Alert Added Reply",
"type": "main",
"index": 0
}
]
]
},
"Alert Added Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Get User Alerts": {
"main": [
[
{
"node": "Format Alert List",
"type": "main",
"index": 0
}
]
]
},
"Format Alert List": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Alert Exists?": {
"main": [
[
{
"node": "Prepare Alert Remove",
"type": "main",
"index": 0
}
]
]
},
"Prepare Alert Remove": {
"main": [
[
{
"node": "Deactivate Alert",
"type": "main",
"index": 0
}
]
]
},
"Deactivate Alert": {
"main": [
[
{
"node": "Alert Removed Reply",
"type": "main",
"index": 0
}
]
]
},
"Alert Removed Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
},
"Alert Missing?": {
"main": [
[
{
"node": "Alert Missing Reply",
"type": "main",
"index": 0
}
]
]
},
"Alert Missing Reply": {
"main": [
[
{
"node": "Send Telegram Reply",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"timezone": "Asia/Tehran",
"saveDataErrorExecution": "all",
"saveDataSuccessExecution": "none"
},
"versionId": "00000000-0000-4000-8000-000000000041",
"meta": {
"templateCredsSetupCompleted": false
},
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Telegram Intelligence Agent — Bot Control. Uses telegramTrigger, telegram, dataTable, httpRequest. Event-driven trigger; 39 nodes.
Source: https://github.com/amir-9473/telegram-intelligence-agent/blob/main/n8n/workflows/01_bot_control.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.
This is a Telegram AI-to-Human Handover System that seamlessly transitions customer support conversations between an AI agent and human operators: AI-First Response: When users message the Telegram bo
This n8n template automates the collection, storage, and safety analysis of Facebook posts while simultaneously providing an interactive AI assistant on Telegram.
AI Social Media Automation for Multiple Platforms using Blotato. Uses telegramTrigger, @blotato/n8n-nodes-blotato, telegram, httpRequest. Event-driven trigger; 52 nodes.
Memorybufferwindow Workflow. Uses telegramTrigger, telegram, executeWorkflowTrigger, httpRequest. Event-driven trigger; 35 nodes.
🎯 Telegram Lead Magnet - Subscription Gate with Upsell Branch. Uses telegram, httpRequest, telegramTrigger. Event-driven trigger; 23 nodes.