This workflow follows the Chainllm → 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 →
{
"nodes": [
{
"parameters": {
"updates": [
"callback_query",
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.1,
"position": [
8720,
3648
],
"id": "756266fc-787c-4fe7-b908-2d153548989e",
"name": "Telegram Trigger",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [
8720,
3792
],
"id": "dd0f0bb0-9a5c-4579-98ad-e7cfb4b53407",
"name": "Chat Trigger"
},
{
"parameters": {},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
8720,
3936
],
"id": "ewt00001-0001-0001-0001-000000000001",
"name": "Execute Workflow Trigger"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "whitelist-check",
"leftValue": "={{ String($json.callback_query?.from?.id ?? $json.message?.from?.id ?? '') }}",
"rightValue": "^(YOUR_CHAT_ID_1|YOUR_CHAT_ID_2)$",
"operator": {
"type": "string",
"operation": "regex"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
8928,
3664
],
"id": "21fc2941-9541-40bd-934d-f05ded7688c4",
"name": "Whitelist",
"disabled": true
},
{
"parameters": {
"jsCode": "// Agent registry \u2014 add new agents here, update Classifier Output Parser enum to match\nconst agents = {\n expenses: {\n workflowId: 'jJmiXA2vJbkk3WKX', // YOUR_EXPENSE_REPORT_WORKFLOW_ID\n label: 'Expense Report',\n desc: 'Monthly expense trends and charts from billing ledger',\n ready: true\n },\n learning: {\n workflowId: 'IKA8U9z7bVwCYuhU', // YOUR_LEARNING_NOTES_WORKFLOW_ID\n label: 'Learning Notes',\n desc: 'AI-summarized notes from Notion knowledge base',\n ready: true\n },\n deals: {\n workflowId: '2_Jk_DnmQcnpRdceAsh21', // YOUR_DEAL_FINDER_WORKFLOW_ID\n label: 'Deal Finder',\n desc: 'Product deal-finder and price tracker. Tracks specific product URLs for daily price updates. Researches deals and alternatives from Swiss retailers.',\n ready: true,\n subCommands: [\n 'add <category> <price> <constraints>',\n 'track <url>',\n 'tracked',\n 'untrack <name>',\n 'check_prices',\n 'history <name>',\n 'plot'\n ]\n }\n};\n\n// Pass through trigger data + inject registry\nreturn [{ json: { ...$json, agents } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
9120,
3720
],
"id": "cfg00001-0001-0001-0001-000000000001",
"name": "Config"
},
{
"parameters": {
"jsCode": "const agents = $json.agents;\nconst knownActions = Object.keys(agents).filter(k => agents[k].ready && agents[k].workflowId);\nconst builtinActions = ['help'];\n\nconst cb = $json.callback_query;\nconst msg = $json.message;\nconst chatInput = $json.chatInput;\n\nlet action = 'chat';\nlet chatId = '';\nlet text = '';\n\nif (chatInput) {\n text = chatInput.trim();\n chatId = 'n8n-chat';\n} else if (cb) {\n const data = cb.data || '';\n const extracted = data.includes(':') ? data.split(':')[1] : data;\n chatId = String(cb.message?.chat?.id || '');\n\n if (knownActions.includes(extracted) || builtinActions.includes(extracted)) {\n action = extracted;\n } else {\n text = extracted;\n }\n} else if (msg) {\n chatId = String(msg.chat?.id || '');\n const raw = (msg.text || '').trim();\n if (raw.startsWith('/')) {\n const parts = raw.substring(1).split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n if (knownActions.includes(cmd) || builtinActions.includes(cmd)) {\n action = cmd;\n }\n text = parts.slice(1).join(' ');\n } else {\n text = raw;\n }\n} else if ($json.text) {\n // Execute Workflow Trigger: text + chatId from parent workflow\n text = ($json.text || '').trim();\n chatId = $json.chatId || 'subworkflow';\n}\n\nconst workflowId = agents[action]?.workflowId || '';\nreturn [{ json: { action, chatId, text, workflowId, agents } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
9328,
3720
],
"id": "94110c9a-e70a-4a35-a1fa-055768533bb0",
"name": "Normalize"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "route-help",
"leftValue": "={{ $json.action }}",
"rightValue": "help",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "help"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "route-agent",
"leftValue": "={{ $json.action }}",
"rightValue": "chat",
"operator": {
"type": "string",
"operation": "notEquals"
}
},
{
"id": "route-agent-not-help",
"leftValue": "={{ $json.action }}",
"rightValue": "help",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "agent"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "route-chat",
"leftValue": "={{ $json.action }}",
"rightValue": "chat",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "chat"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
9536,
3680
],
"id": "5e349338-c82d-4cf6-a3a1-679dad5456c9",
"name": "Route"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "={{ $json.workflowId }}",
"mode": "id"
},
"options": {}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.2,
"onError": "continueOnFail",
"position": [
9760,
3600
],
"id": "a0e8c921-08ea-4f20-859b-3e1f6a2076b6",
"name": "Run Skill"
},
{
"parameters": {
"promptType": "define",
"text": "=You are a routing agent. Analyze the user's input and conversation context, then route to the best handler.\n\nAvailable agents (use for domain-specific tasks):\n{{ Object.entries($json.agents).map(([k,v]) => '- ' + k + ': ' + v.desc + (v.ready ? '' : ' [coming soon \u2014 tell user this is not available yet]')).join('\\n') }}\n\nAvailable LLM backends (use for general queries):\n- groq_reasoning: AI reasoning, analysis, creative writing, coding, complex problem solving\n- brave_search: Simple factual lookups, \"what is\", \"who is\", basic search queries\n- perplexity: Research, comparisons, investigations, comprehensive studies\n\nUser Input: {{ $json.text }}\n\nRoute to the most specific handler. Prefer agents over LLM backends when the query clearly matches an agent's domain.",
"hasOutputParser": true,
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
9760,
3880
],
"id": "de46fe69-de1e-41a7-b3c2-332c87038e99",
"name": "AI Classifier"
},
{
"parameters": {
"model": "openai/gpt-oss-120b",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGroq",
"typeVersion": 1,
"position": [
9760,
4100
],
"id": "bb5dc33a-944e-437a-878a-bfdf75fd2572",
"name": "Groq Classifier LLM",
"credentials": {
"groqApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"schemaType": "manual",
"inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"route_type\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"enum\": [\"expenses\", \"learning\", \"deals\", \"groq_reasoning\", \"brave_search\", \"perplexity\"],\n\t\t\t\"description\": \"Which handler should process this request\"\n\t\t},\n\t\t\"query\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"The original user query/input\"\n\t\t},\n\t\t\"reasoning\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"Brief explanation of why this route was chosen\"\n\t\t}\n\t},\n\t\"required\": [\"route_type\", \"query\", \"reasoning\"]\n}"
},
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"typeVersion": 1.3,
"position": [
9888,
4100
],
"id": "94b2eb32-3622-4fb6-a45d-80826290b229",
"name": "Classifier Output Parser"
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Normalize').first().json.chatId }}",
"contextWindowLength": 10
},
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1.3,
"position": [
9632,
4100
],
"id": "mem00001-0001-0001-0001-000000000001",
"name": "Router Memory",
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $json.output.route_type }}",
"rightValue": "groq_reasoning",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "groq"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $json.output.route_type }}",
"rightValue": "brave_search",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "brave"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $json.output.route_type }}",
"rightValue": "perplexity",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "perplexity"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
10000,
3880
],
"id": "1cdc9c5d-7fa2-4d08-b8c0-2f2fd80e967f",
"name": "LLM Route"
},
{
"parameters": {
"jsCode": "const agents = $('Config').first().json.agents;\nconst routeType = $json.output.route_type;\nconst agent = agents[routeType];\nconst chatId = $('Normalize').first().json.chatId;\nconst text = $('Normalize').first().json.text;\n\nif (!agent || !agent.ready || !agent.workflowId) {\n return [{ json: {\n response: `I don't have the ${agent?.label || routeType} capability yet.`,\n chatId\n }}];\n}\n\nreturn [{ json: { workflowId: agent.workflowId, chatId, text, action: routeType } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
10240,
3640
],
"id": "res00001-0001-0001-0001-000000000001",
"name": "Resolve Agent"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "={{ $json.workflowId }}",
"mode": "id"
},
"options": {}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.2,
"onError": "continueOnFail",
"position": [
10464,
3640
],
"id": "ewa00001-0001-0001-0001-000000000001",
"name": "Run Skill (AI)"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $node['AI Classifier'].json.output.query }}",
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
10240,
3800
],
"id": "035f3fed-c25a-4a27-977c-700f8545101b",
"name": "Groq Reasoning"
},
{
"parameters": {
"model": "meta-llama/llama-4-maverick-17b-128e-instruct",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGroq",
"typeVersion": 1,
"position": [
10240,
3980
],
"id": "929c9914-1217-4860-b08c-8259cad0e44f",
"name": "Groq Reasoning LLM",
"credentials": {
"groqApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "https://api.search.brave.com/res/v1/web/search",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $node['AI Classifier'].json.output.query }}"
},
{
"name": "count",
"value": "5"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "application/json"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
10240,
4080
],
"id": "41b1dac7-daa6-4486-aabe-f9142943c3fe",
"name": "Brave Search",
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"messages": {
"message": [
{
"content": "={{ $node['AI Classifier'].json.output.query }}"
}
]
},
"options": {},
"requestOptions": {}
},
"type": "n8n-nodes-base.perplexity",
"typeVersion": 1,
"position": [
10240,
4280
],
"id": "daf3c0c5-8ffa-40d5-ab86-9516fe0b10a3",
"name": "Perplexity Research"
},
{
"parameters": {
"jsCode": "// Format all LLM route responses into unified output\nconst data = $input.first().json;\nconst classifier = $node['AI Classifier'].json.output;\nconst chatId = $node['Normalize'].json.chatId;\n\nlet response = '';\n\n// Helper to strip HTML entities/tags from Brave API responses\nconst clean = (s) => s\n .replace(/<[^>]+>/g, '')\n .replace(/&/g, '&')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/ /g, ' ');\n\nif (data.web && data.web.results !== undefined) {\n // Route 1: Brave Search\n const results = data.web.results || [];\n if (results.length > 0) {\n const top = results.slice(0, 3);\n response = top.map((item, i) => {\n const desc = clean(item.description || '').slice(0, 80);\n return `${i + 1}. [${clean(item.title)}](${item.url})\\n ${desc}`;\n }).join('\\n\\n');\n } else {\n response = 'No search results found.';\n }\n} else if (data.choices && data.choices[0]) {\n // Route 2: Perplexity\n response = data.choices[0].message.content || 'No research results.';\n} else {\n // Route 0: Groq Reasoning\n response = data.text || data.response || 'No response generated.';\n}\n\nreturn [{ json: { response, chatId } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
10480,
4080
],
"id": "a3a5ce05-f339-423b-b35e-e11d37ee90d7",
"name": "Format Response"
},
{
"parameters": {
"chatId": "={{ $json.chatId }}",
"text": "={{ $json.response }}",
"additionalFields": {
"parse_mode": "Markdown"
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
10704,
4080
],
"id": "85d63d7d-2691-4d12-a879-21c6783cd497",
"name": "Send Reply",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Guard: only forward if subworkflow returned a response.\n// Subworkflows that send their own Telegram replies return no 'response' field.\nconst data = $input.first().json || {};\nconst chatId = data.chatId || $('Normalize').first().json.chatId;\n\n// continueOnFail error payload \u2014 reply with friendly message, don't cascade\nif (data.error) {\n return [{ json: { chatId, response: 'Sorry, this feature is temporarily unavailable. Please try again later.' } }];\n}\n\nconst response = data.response || '';\n\nif (!response) {\n // Subworkflow handled its own reply \u2014 nothing to forward\n return [];\n}\n\nreturn [{ json: { chatId, response } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
10480,
3600
],
"id": "fsr00001-0001-0001-0001-000000000001",
"name": "Format Skill Response"
},
{
"parameters": {
"jsCode": "// Generate dynamic help message from agents registry\nconst agents = $json.agents;\nconst chatId = $json.chatId;\n\nconst sections = [];\nfor (const [key, agent] of Object.entries(agents)) {\n if (!agent.ready) continue;\n sections.push(` /${key} \u2014 ${agent.desc}`);\n if (agent.subCommands) {\n for (const sub of agent.subCommands) {\n sections.push(` /${key} ${sub}`);\n }\n }\n}\n\nconst response = `*Available commands:*\\n\\n${sections.join('\\n')}\\n\\n /help \u2014 This message\\n\\nOr just send me a question in plain text.`;\nreturn [{ json: { chatId, response } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
9760,
3480
],
"id": "hlp00001-0001-0001-0001-000000000001",
"name": "Build Help"
},
{
"parameters": {
"content": "## Menu Handler v2 \u2014 Config-Driven + Memory\n\nHub-and-spoke with intelligent routing.\n\n### Entry Points\n- Telegram Trigger (buttons + messages)\n- Chat Trigger (MCP/programmatic)\n- Execute Workflow Trigger (subworkflow calls)\n\n### 1. Agent Registry (Config node)\nAdd new agents by editing the Config node only. No other changes needed\nfor button/command routing. For AI routing, also add the key to the\nClassifier Output Parser enum.\n\n### 2. Conversation Memory\nRouter Memory (Postgres) gives the AI Classifier context across messages.\nFollow-up questions route correctly.\n\n### 3. Unified Routing\nThe AI Classifier routes to both agents (expenses, learning, deals)\nAND LLM backends (Groq, Brave, Perplexity).\n\n### Setup\nSee setup-guide.md for full post-import checklist.",
"height": 600,
"width": 500
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
8224,
3648
],
"id": "4502a13c-86c5-4d27-8247-d390de6580cb",
"name": "Sticky Note - Overview"
},
{
"parameters": {
"content": "If stopped here \u2192\n[credentials-guide.md](YOUR_GITHUB_REPO_URL/blob/main/projects/n8n/credentials-guide.md#brave-search)",
"height": 80,
"width": 150
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
10200,
4040
],
"id": "b7e2c1a0-3f44-4e8d-9a12-5d6e8f0b1c2d",
"name": "Sticky Note - Brave Setup"
},
{
"parameters": {
"content": "chatId: $json.chatId\ntext: $json.text\naction: $json.action\nworkflowId: $json.workflowId\nonError: continueOnFail\n\u2192 errors \u2192 Format Skill Response",
"height": 150,
"width": 200,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
9720,
3540
],
"id": "stn00001-0001-0001-0001-000000000001",
"name": "Sticky Note - Run Skill Params"
},
{
"parameters": {
"content": "chatId: $json.chatId\ntext: $json.text\naction: $json.action\nworkflowId: $json.workflowId",
"height": 120,
"width": 200,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
10424,
3600
],
"id": "stn00002-0001-0001-0001-000000000001",
"name": "Sticky Note - Run Skill AI Params"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "agent-available",
"leftValue": "={{ $json.workflowId }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isNotEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
10352,
3640
],
"id": "ifa00001-0001-0001-0001-000000000001",
"name": "Agent Available?"
}
],
"connections": {
"Telegram Trigger": {
"main": [
[
{
"node": "Whitelist",
"type": "main",
"index": 0
}
]
]
},
"Whitelist": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Chat Trigger": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Config": {
"main": [
[
{
"node": "Normalize",
"type": "main",
"index": 0
}
]
]
},
"Normalize": {
"main": [
[
{
"node": "Route",
"type": "main",
"index": 0
}
]
]
},
"Route": {
"main": [
[
{
"node": "Build Help",
"type": "main",
"index": 0
}
],
[
{
"node": "Run Skill",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Classifier",
"type": "main",
"index": 0
}
]
]
},
"AI Classifier": {
"main": [
[
{
"node": "LLM Route",
"type": "main",
"index": 0
}
]
]
},
"Groq Classifier LLM": {
"ai_languageModel": [
[
{
"node": "AI Classifier",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Classifier Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Classifier",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Router Memory": {
"ai_memory": [
[
{
"node": "AI Classifier",
"type": "ai_memory",
"index": 0
}
]
]
},
"LLM Route": {
"main": [
[
{
"node": "Groq Reasoning",
"type": "main",
"index": 0
}
],
[
{
"node": "Brave Search",
"type": "main",
"index": 0
}
],
[
{
"node": "Perplexity Research",
"type": "main",
"index": 0
}
],
[
{
"node": "Resolve Agent",
"type": "main",
"index": 0
}
]
]
},
"Resolve Agent": {
"main": [
[
{
"node": "Agent Available?",
"type": "main",
"index": 0
}
]
]
},
"Agent Available?": {
"main": [
[
{
"node": "Run Skill (AI)",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Groq Reasoning": {
"main": [
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Groq Reasoning LLM": {
"ai_languageModel": [
[
{
"node": "Groq Reasoning",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Brave Search": {
"main": [
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Perplexity Research": {
"main": [
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Format Response": {
"main": [
[
{
"node": "Send Reply",
"type": "main",
"index": 0
}
]
]
},
"Run Skill": {
"main": [
[
{
"node": "Format Skill Response",
"type": "main",
"index": 0
}
]
]
},
"Run Skill (AI)": {
"main": [
[
{
"node": "Format Skill Response",
"type": "main",
"index": 0
}
]
]
},
"Format Skill Response": {
"main": [
[
{
"node": "Send Reply",
"type": "main",
"index": 0
}
]
]
},
"Build Help": {
"main": [
[
{
"node": "Send Reply",
"type": "main",
"index": 0
}
]
]
}
},
"meta": {
"templateCredsSetupCompleted": true
}
}
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.
groqApihttpHeaderAuthpostgrestelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Menu-Handler. Uses telegramTrigger, chatTrigger, executeWorkflowTrigger, chainLlm. Event-driven trigger; 28 nodes.
Source: https://github.com/runfish5/micro-services/blob/main/projects/n8n/10_steward/workflows/menu-handler.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 comprehensive N8N automation template revolutionizes content creation by delivering a complete end-to-end solution for AI-powered blog generation. Transform simple ideas into fully SEO-optimized,
Telegram Code. Uses lmChatOpenAi, outputParserAutofixing, outputParserStructured, telegramTrigger. Event-driven trigger; 43 nodes.
Telegram Code. Uses lmChatOpenAi, outputParserAutofixing, outputParserStructured, telegramTrigger. Event-driven trigger; 43 nodes.
SRT Translator. Uses formTrigger, executeWorkflowTrigger, form, telegramTrigger. Event-driven trigger; 34 nodes.
Effortlessly track your expenses with MoneyMate, an n8n workflow that transforms receipts into organized financial insights.