AutomationFlowsSlack & Telegram › AI Telegram Bot Assistant for Parents & Customers

AI Telegram Bot Assistant for Parents & Customers

Original n8n title: AI Telegram Bot (parent/customer Assistant)

AI Telegram Bot (Parent/Customer Assistant). Uses httpRequest. Webhook trigger; 9 nodes.

Webhook trigger★★★★☆ complexity9 nodesHTTP Request
Slack & Telegram Trigger: Webhook Nodes: 9 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "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"
    }
  ]
}
Pro

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 →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

Advanced Slackbot With N8N. Uses slack, httpRequest, stickyNote, executeWorkflow. Webhook trigger; 34 nodes.

Slack, HTTP Request, Execute Workflow Trigger +1
Slack & Telegram

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.

Slack, HTTP Request, Execute Workflow Trigger +1
Slack & Telegram

Standup Bot 4 4 Worker. Uses mattermost, httpRequest, noOp, executeWorkflow. Webhook trigger; 29 nodes.

Mattermost, HTTP Request
Slack & Telegram

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?

Mattermost, HTTP Request
Slack & Telegram

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.

HTTP Request