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": "AI Telegram Bot (Parent/Customer Assistant)",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "inbound-telegram",
"responseMode": "lastNode",
"options": {}
},
"id": "node-webhook",
"name": "Inbound from App",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-960,
0
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "c1",
"name": "telegram_bot_token",
"value": "YOUR_TELEGRAM_BOT_TOKEN",
"type": "string"
},
{
"id": "c2",
"name": "gemini_api_key",
"value": "YOUR_GEMINI_API_KEY",
"type": "string"
},
{
"id": "c3",
"name": "telegram_admin_chat_id",
"value": "YOUR_ADMIN_TELEGRAM_CHAT_ID",
"type": "string"
},
{
"id": "c4",
"name": "telegram_group_link",
"value": "YOUR_TELEGRAM_GROUP_INVITE_LINK",
"type": "string"
},
{
"id": "c5",
"name": "admin_phone",
"value": "YOUR_ADMIN_PHONE_NUMBER",
"type": "string"
},
{
"id": "c6",
"name": "admin_email",
"value": "YOUR_ADMIN_EMAIL",
"type": "string"
},
{
"id": "c7",
"name": "n8n_webhook_secret",
"value": "YOUR_WEBHOOK_SECRET",
"type": "string"
}
]
},
"options": {}
},
"id": "node-config",
"name": "Config",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-736,
0
]
},
{
"parameters": {
"jsCode": "const body = $('Inbound from App').item.json.body || $('Inbound from App').item.json;\nconst cfg = $('Config').item.json;\n\nif (cfg.n8n_webhook_secret && body.webhookSecret && body.webhookSecret !== cfg.n8n_webhook_secret) {\n return { json: { skip: true, reason: 'bad-secret' } };\n}\n\nconst chatId = body.chatId;\nconst text = (body.text || '').trim();\nconst from = body.from || {};\nconst fromName = [from.firstName, from.lastName].filter(Boolean).join(' ') || 'there';\nconst username = from.username ? '@' + from.username : '';\n\nif (!chatId || !text) {\n return { json: { skip: true, reason: 'empty' } };\n}\n\nreturn { json: { skip: false, chatId, text, fromName, username, userId: from.id } };"
},
"id": "node-parse",
"name": "Parse Forwarded Message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-512,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false
},
"conditions": [
{
"id": "skip-check",
"leftValue": "={{ $json.skip }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "notEqual"
}
}
]
},
"options": {}
},
"id": "node-skipif",
"name": "Has Message?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
-288,
0
]
},
{
"parameters": {
"method": "POST",
"url": "=https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "x-goog-api-key",
"value": "={{ $('Config').item.json.gemini_api_key }}"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ contents: [{ parts: [{ text: 'You are the official AI assistant for [YOUR ORGANIZATION NAME]. Your job is to help users with inquiries in a warm, professional tone.\\n\\n=== ORGANIZATION FACTS ===\\nLocation: [YOUR LOCATION]\\nContact phone: ' + $('Config').item.json.admin_phone + '\\nContact email: ' + $('Config').item.json.admin_email + '\\nCommunity group: ' + $('Config').item.json.telegram_group_link + '\\n\\n[YOUR PROGRAMS/SERVICES AND PRICING HERE]\\n\\nTraining hours: [YOUR HOURS]\\nWeb: [YOUR WEBSITE URL]\\n\\n=== YOUR TASK ===\\nClassify the user message into ONE of:\\n- info (general question about services, programs, fees, schedule, location)\\n- contact (user wants to speak with a human / get phone/email)\\n- trial (user wants to book or ask about a free trial)\\n- group (user wants to join the community group)\\n- other (greetings, off-topic)\\n\\nFor intent=trial, also try to extract: child_name, child_age, parent_name, preferred_date, notes. If any field is missing, ask for it in your reply. Only mark trial_complete=true when you have child_name + child_age + parent_name.\\n\\nReturn STRICT JSON (no markdown fences):\\n{\\n \"intent\": \"info|contact|trial|group|other\",\\n \"reply\": \"<your reply to the user, HTML-safe, use Telegram HTML: <b>bold</b> <i>italic</i> - no other tags>\",\\n \"trial_complete\": <bool>,\\n \"trial_details\": { \"child_name\": \"\", \"child_age\": \"\", \"parent_name\": \"\", \"preferred_date\": \"\", \"notes\": \"\" }\\n}\\n\\nUser name: ' + $json.fromName + '\\nUser message: ' + $json.text }] }], generationConfig: { temperature: 0.3, maxOutputTokens: 600, responseMimeType: \"application/json\" } }) }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "node-gemini",
"name": "Gemini \u2014 Understand & Reply",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-64,
0
]
},
{
"parameters": {
"jsCode": "const resp = $('Gemini \u2014 Understand & Reply').item.json;\nconst user = $('Parse Forwarded Message').item.json;\nconst cfg = $('Config').item.json;\n\nlet raw = '';\ntry { raw = resp.candidates[0].content.parts[0].text || ''; } catch (e) {}\n\nlet ai;\ntry {\n const cleaned = raw.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n ai = JSON.parse(cleaned);\n} catch (e) {\n ai = { intent: 'other', reply: 'Sorry, I had trouble understanding. Please try again, or reach us at ' + cfg.admin_phone + '.', trial_complete: false, trial_details: {} };\n}\n\nlet reply = ai.reply || '';\nif (ai.intent === 'group') {\n reply += '\\n\\n<b>Join our community group:</b> ' + cfg.telegram_group_link;\n}\nif (ai.intent === 'contact') {\n reply += '\\n\\n\ud83d\udcde ' + cfg.admin_phone + '\\n\u2709\ufe0f ' + cfg.admin_email;\n}\n\nreturn {\n json: {\n chatId: user.chatId,\n userName: user.fromName,\n userHandle: user.username,\n intent: ai.intent,\n reply,\n trial_complete: !!ai.trial_complete,\n trial_details: ai.trial_details || {}\n }\n};"
},
"id": "node-buildreply",
"name": "Build Reply",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
160,
0
]
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ chat_id: $json.chatId, text: $json.reply, parse_mode: 'HTML', disable_web_page_preview: false }) }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "node-sendreply",
"name": "Reply to User",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
384,
0
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false
},
"conditions": [
{
"id": "is-trial",
"leftValue": "={{ $json.intent }}",
"rightValue": "trial",
"operator": {
"type": "string",
"operation": "equals"
}
},
{
"id": "is-complete",
"leftValue": "={{ $json.trial_complete }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "node-if-trial",
"name": "Trial Complete?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
608,
0
]
},
{
"parameters": {
"method": "POST",
"url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ chat_id: $('Config').item.json.telegram_admin_chat_id, text: '\u26bd <b>New Trial Request (via Bot)</b>\\n\\n<b>Player:</b> ' + ($json.trial_details.child_name || '-') + ' (age ' + ($json.trial_details.child_age || '-') + ')\\n<b>Parent:</b> ' + ($json.trial_details.parent_name || '-') + '\\n<b>User:</b> ' + $json.userName + ' ' + $json.userHandle + '\\n<b>Chat ID:</b> ' + $json.chatId + '\\n<b>Preferred date:</b> ' + ($json.trial_details.preferred_date || 'Not specified') + '\\n<b>Notes:</b> ' + ($json.trial_details.notes || 'None'), parse_mode: 'HTML' }) }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "node-notify-admin",
"name": "Forward Trial to Admin",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
832,
-128
]
}
],
"connections": {
"Inbound from App": {
"main": [
[
{
"node": "Config",
"type": "main",
"index": 0
}
]
]
},
"Config": {
"main": [
[
{
"node": "Parse Forwarded Message",
"type": "main",
"index": 0
}
]
]
},
"Parse Forwarded Message": {
"main": [
[
{
"node": "Has Message?",
"type": "main",
"index": 0
}
]
]
},
"Has Message?": {
"main": [
[
{
"node": "Gemini \u2014 Understand & Reply",
"type": "main",
"index": 0
}
],
[]
]
},
"Gemini \u2014 Understand & Reply": {
"main": [
[
{
"node": "Build Reply",
"type": "main",
"index": 0
}
]
]
},
"Build Reply": {
"main": [
[
{
"node": "Reply to User",
"type": "main",
"index": 0
}
]
]
},
"Reply to User": {
"main": [
[
{
"node": "Trial Complete?",
"type": "main",
"index": 0
}
]
]
},
"Trial Complete?": {
"main": [
[
{
"node": "Forward Trial to Admin",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
},
"active": false,
"tags": [
{
"name": "AI"
},
{
"name": "Telegram"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AI Telegram Bot (Parent/Customer Assistant). Uses httpRequest. Webhook trigger; 9 nodes.
Source: https://github.com/hasancoded/n8n-workflow-templates/blob/main/ai-telegram-bot.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.
Advanced Slackbot With N8N. Uses slack, httpRequest, stickyNote, executeWorkflow. Webhook trigger; 34 nodes.
Slackbots are super powerful. At n8n, we have been using them to get a lot done.. But it can become hard to manage and maintain many different operations that a workflow can do.
Standup Bot 4 4 Worker. Uses mattermost, httpRequest, noOp, executeWorkflow. Webhook trigger; 29 nodes.
This is the fourth workflow for the Mattermost Standup Bot. This workflow sends the team a message every morning to ask them three standup questions. What have you accomplished since your last report?
SmartPoll Automator is an n8n-powered workflow that automatically creates and publishes polls in Telegram. It helps teams, communities, and businesses run polls without manual work.