AutomationFlowsAI & RAG › Sales Lead Qualifier

Sales Lead Qualifier

Sales Lead Qualifier. Uses telegramTrigger, googleSheets, telegram, googleGemini. Event-driven trigger; 41 nodes.

Event trigger★★★★★ complexityAI-powered41 nodesTelegram TriggerGoogle SheetsTelegramGoogle GeminiHTTP RequestGoogle Calendar
AI & RAG Trigger: Event Nodes: 41 Complexity: ★★★★★ AI nodes: yes Added:

This workflow follows the Google Calendar → Google Sheets 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 →

Download .json
{
  "name": "Sales Lead Qualifier",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message",
          "callback_query"
        ],
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "id": "bb25e52a-0978-4cc2-ac25-0481cc3c0d1e",
      "name": "Telegram Trigger",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "https://docs.google.com/spreadsheets/d/1B2_NFRSRoZYwfn6mU9i2FL_-KborBkg6JWdDmhJYpaw/edit",
          "mode": "url"
        },
        "sheetName": {
          "__rl": true,
          "value": 1644959373,
          "mode": "list",
          "cachedResultName": "Data",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B2_NFRSRoZYwfn6mU9i2FL_-KborBkg6JWdDmhJYpaw/edit#gid=1644959373"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Name": "={{ $json.name }}",
            "chat_id": "={{ $json.chat_id }}",
            "Company": "={{ $json.company }}",
            "Message": "={{ $json.original_text }}",
            "Enrichment_source": "={{ $json.enrichment_source }}",
            "teleg_username": "=@{{ $json.sender_username }}",
            "Generated Response": "={{ $json.generated_response }}",
            "Timestamp": "={{ $now.format('yyyy-MM-dd HH:mm:ss') }}",
            "\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)": "={{ $json.category }}",
            "\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c(Urgency)": "={{ $json.urgency }}",
            "\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435(Intend)": "={{ $json.intent }}",
            "\u0434\u043e\u043f. \u0414\u0430\u0442\u0430(Enrichment)": "={{ $json.enrichment }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Timestamp",
              "displayName": "Timestamp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Name",
              "displayName": "Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Company",
              "displayName": "Company",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)",
              "displayName": "\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c(Urgency)",
              "displayName": "\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c(Urgency)",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435(Intend)",
              "displayName": "\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435(Intend)",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Message",
              "displayName": "Message",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "\u0434\u043e\u043f. \u0414\u0430\u0442\u0430(Enrichment)",
              "displayName": "\u0434\u043e\u043f. \u0414\u0430\u0442\u0430(Enrichment)",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Enrichment_source",
              "displayName": "Enrichment_source",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "chat_id",
              "displayName": "chat_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "teleg_username",
              "displayName": "teleg_username",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Generated Response",
              "displayName": "Generated Response",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2720,
        96
      ],
      "id": "69e9ddcc-8b2b-4840-a0f0-25317718fc8b",
      "name": "Append row in sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "=1619231316",
        "text": "=\ud83d\udd14 \u041d\u043e\u0432\u044b\u0439 \u043b\u0438\u0434 (\u0430\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u2705)\n\n\ud83d\udc64 \u041a\u043b\u0438\u0435\u043d\u0442: {{ $('Auto Respond?').item.json.Name }}\n\ud83c\udfe2 \u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f: {{ $('Auto Respond?').item.json['\u0434\u043e\u043f. \u0414\u0430\u0442\u0430(Enrichment)']}}\n\ud83d\udcca \u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430: {{ $('Auto Respond?').item.json['\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)'] }}\n\ud83d\udd25\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c: {{ $json['\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c(Urgency)'] }}\n\ud83c\udfaf\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435: {{ $json[\"\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435(Intend)\"] }}\n\n\ud83d\udcac \u041a\u043b\u0438\u0435\u043d\u0442:{{ $('Auto Respond?').item.json['Message'] }}\n\n\u2709\ufe0f \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e: {{ $('Auto Respond?').item.json['Generated Response'] }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3408,
        96
      ],
      "id": "90636008-e2c8-4927-b20f-8817ec1d21a7",
      "name": "Message to Managers",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-3.1-flash-lite-preview",
          "mode": "list",
          "cachedResultName": "models/gemini-3.1-flash-lite-preview"
        },
        "messages": {
          "values": [
            {
              "content": "=You are an expert sales lead qualifier for Big Dream Lab, an educational company in Astana, Kazakhstan specializing in: Unity 3D game development, Unreal Engine 5, UI/UX design, 3D modeling and animation, Product Management, and AR/VR development. They also offer corporate training programs and partner with Tech Orda government grant program.\n\nWrite a personalized response to this potential client. RESPOND IN THE SAME LANGUAGE AS THE CLIENT'S MESSAGE.\n\nCLIENT'S MESSAGE: {{ $('Telegram Trigger').first().json.message.text }}\n\nLEAD ANALYSIS: {{ $json.candidates[0].content.parts[0].text }}\n\nRULES:\n- NEVER suggest specific dates or times like \"\u0432 \u0447\u0435\u0442\u0432\u0435\u0440\u0433 \u0432 11:00\" or \"\u0437\u0430\u0432\u0442\u0440\u0430 \u0432 15:00\". Instead ask \"\u041a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u043e\u0437\u0432\u043e\u043d\u0438\u0442\u044c\u0441\u044f?\" or \"\u041f\u043e\u0434\u0441\u043a\u0430\u0436\u0438\u0442\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430?\"\n- If category is \"hot\": be enthusiastin and mention specific solutions\n- If category is \"warm\": be helpful, answer their likely questions, gently push toward a call\n- If category is \"cold\": be friendly, provide general info, invite to a free webinar\n- Keep it under 100 words\n- Address client by name\n- If company is mentioned, reference it naturally\n- End with a clear call-to-action\n- RESPOND IN THE SAME LANGUAGE AS THE CLIENT'S MESSAGE\n\nRETURN ONLY the message text. No JSON, no formatting, no quotes."
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1.1,
      "position": [
        2192,
        96
      ],
      "id": "e29c53a1-fd63-431b-b960-5dc3430d8963",
      "name": "respond for user",
      "retryOnFail": false,
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-3.1-flash-lite-preview",
          "mode": "list",
          "cachedResultName": "models/gemini-3.1-flash-lite-preview"
        },
        "messages": {
          "values": [
            {
              "content": "=You are an expert sales lead qualifier for Big Dream Lab, an educational company in Astana, Kazakhstan specializing in: Unity 3D game development, Unreal Engine 5, UI/UX design, 3D modeling and animation, Product Management, and AR/VR development. They also offer corporate training programs and partner with Tech Orda government grant program.\n\nYour task: Analyze the incoming message from a potential client and return a structured JSON.\n\nINCOMING MESSAGE:\n\"{{ $json.message_text }}\"\n\nSENDER INFO:\n- Name: {{ $json.first_name }}\n- Username:{{ $json.username }}\n\nCLASSIFY the lead into ONE of these categories:\n- \"hot\" \u2014 clear buying intent, specific product interest, ready to discuss terms, mentions company/budget/timeline\n- \"warm\" \u2014 genuine interest but still exploring, asks general questions, comparing options\n- \"cold\" \u2014 vague curiosity, just browsing, students with no clear goal, off-topic\n\nEXTRACT the following fields:\n- name: person's name (from message or sender info)\n- company: company name if mentioned, otherwise null. IMPORTANT: normalize the company name to its official name (e.g., \"\u043a\u0430\u0441\u043f\u0438\" \u2192 \"Kaspi Bank\", \"\u0445\u0430\u043b\u044b\u043a\" \u2192 \"Halyk Bank\", \"\u043a\u0430\u0437\u043f\u043e\u0447\u0442\u0430\" \u2192 \"Kazpost\")\n- category: \"hot\" | \"warm\" | \"cold\"\n- intent: one short sentence describing what they want (in Russian)\n- urgency: \"high\" | \"medium\" | \"low\"\n- reasoning: 1-2 sentences explaining your classification (in English)\n\nRETURN ONLY valid JSON in this exact format, no markdown, no extra text:\n{\n  \"name\": \"...\",\n  \"company\": \"...\" or null,\n  \"category\": \"hot\" | \"warm\" | \"cold\",\n  \"intent\": \"...\",\n  \"urgency\": \"high\" | \"medium\" | \"low\",\n  \"reasoning\": \"...\"\n}"
            }
          ]
        },
        "simplify": false,
        "jsonOutput": true,
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1.1,
      "position": [
        1856,
        96
      ],
      "id": "7bf432ff-17cf-4f5f-a395-95ae312b2892",
      "name": "field extracter",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.response_text }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        656,
        -304
      ],
      "id": "faee0abd-5c7c-4ea0-b170-e671b89fe7a3",
      "name": "Send a text message",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nif (!staticData.auto_respond) staticData.auto_respond = 'on';\nif (!staticData.notify_filter) staticData.notify_filter = 'all';\n\nconst previousData = $input.all()[0].json;\nconst category = (previousData['\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)'] || previousData.category || '').toLowerCase();\nconst filter = staticData.notify_filter;\n\nlet shouldNotify = true;\nif (filter === 'all') {\n  shouldNotify = true;\n} else if (filter.includes(',')) {\n  shouldNotify = filter.split(',').includes(category);\n} else {\n  shouldNotify = filter === category;\n}\n\nreturn [{\n  json: {\n    ...previousData,\n    auto_respond: staticData.auto_respond,\n    should_notify: shouldNotify\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2720,
        288
      ],
      "id": "83cf65fe-e112-49ff-bd26-40c359bdaa1d",
      "name": "Check Auto Respond"
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst text = $json.message.text.trim();\nconst chatId = $json.message.chat.id;\n\nif (!staticData.auto_respond) staticData.auto_respond = 'on';\nif (!staticData.notify_filter) staticData.notify_filter = 'all';\n\nlet responseText = '';\n\nif (text === '/on') {\n  staticData.auto_respond = 'on';\n  responseText = '\u2699\ufe0f \u0410\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442: \u0412\u041a\u041b\u042e\u0427\u0401\u041d \u2705\\n\\n\u041a\u043b\u0438\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.';\n\n} else if (text === '/off') {\n  staticData.auto_respond = 'off';\n  responseText = '\u2699\ufe0f \u0410\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442: \u0412\u042b\u041a\u041b\u042e\u0427\u0415\u041d \ud83d\udd34\\n\\n\u0412\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f.';\n\n} else if (text === '/status') {\n  const mode = staticData.auto_respond === 'on' ? '\u2705 \u0412\u041a\u041b\u042e\u0427\u0401\u041d' : '\ud83d\udd34 \u0412\u042b\u041a\u041b\u042e\u0427\u0415\u041d';\n  const filter = staticData.notify_filter;\n  responseText = '\u2699\ufe0f \u0422\u0435\u043a\u0443\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:\\n\\n\ud83d\udce8 \u0410\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442: ' + mode + '\\n\ud83d\udd14 \u0424\u0438\u043b\u044c\u0442\u0440: ' + filter;\n\n} else if (text.startsWith('/filter_')) {\n  const filter = text.replace('/filter_', '').toLowerCase().trim();\n  if (['hot', 'warm', 'cold', 'hot_warm', 'all'].includes(filter)) {\n    const saveFilter = filter.replace('_', ',');\n    staticData.notify_filter = saveFilter;\n    responseText = '\ud83d\udd14 \u0424\u0438\u043b\u044c\u0442\u0440 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439: ' + saveFilter;\n  } else {\n    responseText = '\u2753 \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440.\\n/filter_hot\\n/filter_hot_warm\\n/filter_all';\n  }\n\n} else {\n  responseText = '\u2753 \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430.\\n\\n/on \u2014 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442\\n/off \u2014 \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442\\n/status \u2014 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\\n/analytics \u2014 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\\n/filter_hot \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0440\u044f\u0447\u0438\u0435\\n/filter_hot_warm \u2014 \u0433\u043e\u0440\u044f\u0447\u0438\u0435 \u0438 \u0442\u0451\u043f\u043b\u044b\u0435\\n/filter_all \u2014 \u0432\u0441\u0435';\n}\n\nreturn [{\n  json: {\n    chat_id: chatId,\n    response_text: responseText\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        464,
        -304
      ],
      "id": "9818f50e-f5d6-43bb-915a-249544c5f704",
      "name": "Command Handler",
      "notesInFlow": false
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "3475a150-b120-485b-8edd-9b5613cf073a",
              "leftValue": "={{ $json.auto_respond }}",
              "rightValue": "on",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        2912,
        288
      ],
      "id": "bc19aff9-e012-4411-b544-68ccb554c7e3",
      "name": "Auto Respond?"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "6ab53650-7240-47fb-af6b-bd81730f20f8",
              "leftValue": "={{ $json[\"\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)\"] }}",
              "rightValue": "warm",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "ef42119b-dbf9-432e-ae0e-3f30a33d9743",
              "leftValue": "={{ $json[\"\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)\"] }}",
              "rightValue": "hot",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        2912,
        96
      ],
      "id": "d01db5ac-0c51-4953-8472-6646ba47a59f",
      "name": "check for category"
    },
    {
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json['Generated Response'] }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3408,
        240
      ],
      "id": "a02664ae-c288-4a54-bb28-f45fd185e2f6",
      "name": "Auto Send to Client",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "=1619231316",
        "text": "=\ud83d\udd14 \u041d\u043e\u0432\u044b\u0439 \u043b\u0438\u0434 (\u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u23f3)\n\n\ud83d\udc64 \u041a\u043b\u0438\u0435\u043d\u0442: {{ $json.Name }}\n\ud83c\udfe2 \u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f: {{ $json['\u0434\u043e\u043f. \u0414\u0430\u0442\u0430(Enrichment)'] }}\n\ud83d\udcca \u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430: {{ $json['\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)'] }}\n\ud83d\udd25 \u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c: {{ $json[\"\u0421\u0440\u043e\u0447\u043d\u043e\u0441\u0442\u044c(Urgency)\"] }}\n\ud83c\udfaf \u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435: {{ $json[\"\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u0438\u0435(Intend)\"] }}\n\n\ud83d\udcac \u041a\u043b\u0438\u0435\u043d\u0442: {{ $json['Message'] }}\n\n\ud83d\udcdd {{ $('data enricher').item.json.reasoning }}\n\n---GENERATED_RESPONSE---\n{{ $json['Generated Response'] }}\n---END_RESPONSE---",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "\u2705 \u041e\u0434\u043e\u0431\u0440\u0438\u0442\u044c",
                    "additionalFields": {
                      "callback_data": "=approve_{{ $json.chat_id }}"
                    }
                  },
                  {
                    "text": "\u274c \u041e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c",
                    "additionalFields": {
                      "callback_data": "=reject_{{ $json.chat_id }}"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3408,
        384
      ],
      "id": "db9d1714-e681-4e39-adc6-fd6ae01bddf0",
      "name": "Notify Manager Manual",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "approve",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "ebad1c43-e9b4-44c9-a4ee-5f1f2f509444"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "approve"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "c2220389-1daf-4902-8e3e-2ecbf059ac93",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "reject",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "reject"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        672,
        512
      ],
      "id": "e3c07f28-fb0f-48ef-9d36-76bb9360bb2e",
      "name": "Switch"
    },
    {
      "parameters": {
        "chatId": "={{ $json.client_chat_id }}",
        "text": "={{ $json.generated_response }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        960,
        496
      ],
      "id": "2bc5d19d-f65f-4729-8716-3583f34c4be6",
      "name": "Send to Client",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('Switch').item.json.manager_chat_id }}",
        "text": "\u2705 \u041e\u0442\u0432\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0443!",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1584,
        496
      ],
      "id": "82cef387-99f5-4e9c-8b49-3031ed8c1332",
      "name": "Confirm Approve",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "expression",
        "output": "={{ $json.callback_query ? 2 : ($json.message && $json.message.text === '/analytics' ? 3 : ($json.message && $json.message.text && $json.message.text.startsWith('/') ? 0 : 1)) }}",
        "looseTypeValidation": true
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        208,
        -16
      ],
      "id": "ed835abd-b314-48d5-ad7a-4f0357565f3a",
      "name": "Router"
    },
    {
      "parameters": {
        "chatId": "={{ $json.manager_chat_id }}",
        "text": "\u274c \u041b\u0438\u0434 \u043e\u0442\u043a\u043b\u043e\u043d\u0451\u043d.",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        960,
        688
      ],
      "id": "8093e4a1-075d-47e2-be84-9eefed079768",
      "name": "Confirm Reject",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const geminiResponse = $input.first().json.content.parts[0].text.trim().toLowerCase();\nconst telegramData = $('Telegram Trigger').first().json;\n\nconst intent = geminiResponse.includes('lead') ? 'lead' : 'question';\n\nreturn [{\n  json: {\n    intent: intent,\n    message_text: telegramData.message.text,\n    chat_id: telegramData.message.chat.id,\n    first_name: telegramData.message.from.first_name,\n    username: telegramData.message.from.username\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1312,
        192
      ],
      "id": "08cf55ff-4ff5-4322-9d67-ce41947cd12d",
      "name": "Parse Intent"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-2.5-flash",
          "mode": "list",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "messages": {
          "values": [
            {
              "content": "=Classify the following message into exactly ONE category.\n\nMESSAGE: \"{{ $json.message.text }}\"\n\nCategories:\n- \"lead\" \u2014 the person wants to BUY something, hire for training, get corporate education, become a student, enroll in a course. They express INTENT to purchase or interest in becoming a client.\n- \"question\" \u2014 the person asks a QUESTION about courses, pricing, schedule, requirements, grants, company info. They want INFORMATION, not ready to buy yet.\n\nExamples:\n- \"\u0425\u043e\u0447\u0443 \u043a\u0443\u0440\u0441 Python \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Kaspi, 30 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\" \u2192 lead\n- \"\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u043e\u0438\u0442 \u043a\u0443\u0440\u0441 Unity?\" \u2192 question\n- \"\u041a\u043e\u0433\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440?\" \u2192 question\n- \"\u042f HR \u0438\u0437 Halyk Bank, \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\" \u2192 lead\n- \"\u041a\u0430\u043a\u0438\u0435 \u043a\u0443\u0440\u0441\u044b \u0435\u0441\u0442\u044c?\" \u2192 question\n- \"\u0425\u043e\u0447\u0443 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u0443\u0440\u0441 UI/UX\" \u2192 lead\n- \"\u041d\u0443\u0436\u0435\u043d \u043b\u0438 \u043d\u043e\u0443\u0442\u0431\u0443\u043a?\" \u2192 question\n- \"\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0433\u0440\u0430\u043d\u0442 \u0422\u0435\u0445 \u041e\u0440\u0434\u0430?\" \u2192 question\n\nRETURN ONLY ONE WORD: lead or question"
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1.1,
      "position": [
        960,
        192
      ],
      "id": "1e1d6126-177c-4641-997e-5c525df3b5d1",
      "name": "Intent Classifier",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "http://rag:5000/ask",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.message_text }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1872,
        288
      ],
      "id": "186193f2-162e-4c58-9f89-7642b9af8110",
      "name": "HTTP Request"
    },
    {
      "parameters": {
        "chatId": "={{ $('Parse Intent').first().json.chat_id }}",
        "text": "={{ $json.answer }}  ",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2080,
        288
      ],
      "id": "c85170ed-08d7-4c05-b915-9083db425a53",
      "name": "answer to question",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "https://docs.google.com/spreadsheets/d/1B2_NFRSRoZYwfn6mU9i2FL_-KborBkg6JWdDmhJYpaw/edit",
          "mode": "url"
        },
        "sheetName": {
          "__rl": true,
          "value": 1644959373,
          "mode": "list",
          "cachedResultName": "Data",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1B2_NFRSRoZYwfn6mU9i2FL_-KborBkg6JWdDmhJYpaw/edit#gid=1644959373"
        },
        "filtersUI": {
          "values": []
        },
        "combineFilters": "OR",
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        464,
        880
      ],
      "id": "58fde7eb-0e28-4aa7-a20f-ab023dbdc59b",
      "name": "Get row(s) in sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const rows = $input.all().map(item => item.json);\nconst telegramData = $('Telegram Trigger').first().json;\n\nconst now = new Date();\nconst todayStr = now.toISOString().split('T')[0];\nconst yesterday = new Date(now);\nyesterday.setDate(yesterday.getDate() - 1);\nconst yesterdayStr = yesterday.toISOString().split('T')[0];\n\nconst recentRows = rows.filter(row => {\n  const ts = row.Timestamp || '';\n  return ts.startsWith(todayStr) || ts.startsWith(yesterdayStr);\n});\n\n// Course detection by keywords\nconst courseKeywords = {\n  'Unity 3D': ['unity', '\u044e\u043d\u0438\u0442\u0438', 'game dev', 'gamedev', '\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0433\u0440'],\n  'Unreal Engine': ['unreal', '\u0430\u043d\u0440\u0438\u043b', 'ue5', 'ue4'],\n  'UI/UX \u0434\u0438\u0437\u0430\u0439\u043d': ['ui/ux', 'ui ux', 'uiux', '\u0434\u0438\u0437\u0430\u0439\u043d', 'figma', 'ux design'],\n  '3D \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435': ['3d', 'blender', 'maya', '\u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435', '\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f'],\n  'Product Management': ['product management', '\u043f\u0440\u043e\u0434\u0430\u043a\u0442', '\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430'],\n  'AR/VR': ['ar/vr', 'ar vr', 'arvr', '\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c', '\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c'],\n  'Data Science / ML': ['data science', 'ds', 'machine learning', 'ml', 'python', '\u043f\u0438\u0442\u043e\u043d']\n};\n\nfunction detectCourse(message) {\n  const lower = (message || '').toLowerCase();\n  for (const [course, keywords] of Object.entries(courseKeywords)) {\n    for (const kw of keywords) {\n      if (lower.includes(kw)) return course;\n    }\n  }\n  return '\u0414\u0440\u0443\u0433\u043e\u0435';\n}\n\nlet totalHot = 0, totalWarm = 0, totalCold = 0;\nfor (const row of rows) {\n  const cat = (row['\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)'] || '').toLowerCase();\n  if (cat === 'hot') totalHot++;\n  else if (cat === 'warm') totalWarm++;\n  else if (cat === 'cold') totalCold++;\n}\n\nlet recentHot = 0, recentWarm = 0, recentCold = 0;\nconst courseCounts = {};\nconst companies = {};\n\nfor (const row of recentRows) {\n  const cat = (row['\u0422\u0438\u043f \u0437\u0432\u043e\u043d\u043a\u0430(Category)'] || '').toLowerCase();\n  if (cat === 'hot') recentHot++;\n  else if (cat === 'warm') recentWarm++;\n  else if (cat === 'cold') recentCold++;\n\n  const course = detectCourse(row.Message);\n  courseCounts[course] = (courseCounts[course] || 0) + 1;\n\n  const company = row.Company || '';\n  if (company && company !== 'null' && company !== '') {\n    companies[company] = (companies[company] || 0) + 1;\n  }\n}\n\nconst topCourses = Object.entries(courseCounts)\n  .sort((a, b) => b[1] - a[1])\n  .slice(0, 3)\n  .map((c, i) => `${i + 1}. ${c[0]} \u2014 ${c[1]}`)\n  .join('\\n');\n\nconst topCompanies = Object.entries(companies)\n  .sort((a, b) => b[1] - a[1])\n  .slice(0, 3)\n  .map((c, i) => `${i + 1}. ${c[0]} \u2014 ${c[1]}`)\n  .join('\\n');\n\nconst report = `\ud83d\udcca \u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\n\n\ud83d\udcc5 \u0417\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 2 \u0434\u043d\u044f:\n\ud83d\udce5 \u041b\u0438\u0434\u043e\u0432: ${recentRows.length}\n\ud83d\udd25 Hot: ${recentHot} | \ud83d\udfe1 Warm: ${recentWarm} | \ud83d\udd35 Cold: ${recentCold}\n\n\ud83d\udcc5 \u0417\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f:\n\ud83d\udce5 \u041b\u0438\u0434\u043e\u0432: ${rows.length}\n\ud83d\udd25 Hot: ${totalHot} | \ud83d\udfe1 Warm: ${totalWarm} | \ud83d\udd35 Cold: ${totalCold}\n\n\ud83c\udfc6 \u0422\u043e\u043f \u043a\u0443\u0440\u0441\u044b (2 \u0434\u043d\u044f):\n${topCourses || '\u041d\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445'}\n\n\ud83c\udfe2 \u0422\u043e\u043f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 (2 \u0434\u043d\u044f):\n${topCompanies || '\u041d\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445'}`;\n\nreturn [{\n  json: {\n    chat_id: telegramData.message.chat.id,\n    report: report\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        672,
        880
      ],
      "id": "1836062d-e209-4c75-ad03-06158c01b2e6",
      "name": "Code in JavaScript1"
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nif (!staticData.waiting_for_schedule) {\n  staticData.waiting_for_schedule = {};\n}\n\nconst preparedData = $('data prepare for approve').first().json;\nconst clientChatId = String(preparedData.client_chat_id);\nconst managerChatId = String(preparedData.manager_chat_id);\n\nstaticData.waiting_for_schedule[clientChatId] = {\n  waiting: true,\n  manager_chat_id: managerChatId,\n  timestamp: new Date().toISOString()\n};\n\nreturn [$input.all()[0]];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1168,
        496
      ],
      "id": "09e2dc88-06a0-4a70-8594-da4a60a50d27",
      "name": "Save Waiting State"
    },
    {
      "parameters": {
        "chatId": "={{ $json.result.chat.id }}",
        "text": "\u041a\u043e\u0433\u0434\u0430 \u0432\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u043e\u0437\u0432\u043e\u043d\u0438\u0442\u044c\u0441\u044f? \u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0434\u0430\u0442\u0443 \u0438 \u0432\u0440\u0435\u043c\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \"\u0417\u0430\u0432\u0442\u0440\u0430 \u0432 15:00\" \u0438\u043b\u0438 \"\u0412 \u0441\u0440\u0435\u0434\u0443 \u0432 10 \u0443\u0442\u0440\u0430\".",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1376,
        496
      ],
      "id": "f1456e89-6467-485d-b00e-76c2c121e53a",
      "name": "ask for a time",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst chatId = String($json.message.chat.id);\n\n// Debug: \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0432 Static Data\nconst debugInfo = JSON.stringify(staticData.waiting_for_schedule || {});\nconst allKeys = Object.keys(staticData.waiting_for_schedule || {});\n\nconst isWaiting = staticData.waiting_for_schedule && \n                  staticData.waiting_for_schedule[chatId] &&\n                  staticData.waiting_for_schedule[chatId].waiting;\n\nlet managerChatId = '';\nif (isWaiting) {\n  managerChatId = staticData.waiting_for_schedule[chatId].manager_chat_id;\n}\n\nreturn [{\n  json: {\n    ...$json,\n    is_waiting: isWaiting ? true : false,\n    manager_chat_id: managerChatId,\n    debug_chat_id: chatId,\n    debug_keys: allKeys,\n    debug_static: debugInfo\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        464,
        16
      ],
      "id": "a84d5e3e-4e75-46fb-a333-b93c9e37c4a2",
      "name": "check waiting?"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "models/gemini-3.1-flash-lite-preview",
          "mode": "list",
          "cachedResultName": "models/gemini-3.1-flash-lite-preview"
        },
        "messages": {
          "values": [
            {
              "content": "=Extract date and time from this message. Today is {{ $now.format('yyyy-MM-dd') }} and today is {{ $now.format('EEEE') }}.\n\nMESSAGE: \"{{ $json.message.text }}\"\n\nRules:\n- \"\u0417\u0430\u0432\u0442\u0440\u0430 \u0432 15:00\" \u2192 tomorrow's date, 15:00\n- \"\u0412 \u0441\u0440\u0435\u0434\u0443 \u0432 10\" \u2192 next Wednesday, 10:00\n- \"\u041f\u043e\u0441\u043b\u0435\u0437\u0430\u0432\u0442\u0440\u0430 \u0443\u0442\u0440\u043e\u043c\" \u2192 day after tomorrow, 09:00\n- If only date mentioned, default time is 10:00\n- If only time mentioned, default date is tomorrow\n- If cannot parse \u2192 set \"valid\": false\n\nRETURN ONLY JSON:\n{\"date\": \"YYYY-MM-DD\", \"time\": \"HH:MM\", \"valid\": true}\nor\n{\"date\": \"\", \"time\": \"\", \"valid\": false}"
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1.1,
      "position": [
        960,
        -128
      ],
      "id": "3b01c066-c192-4414-ba6b-28f39080289a",
      "name": "Parse a DateTime",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const geminiResponse = $input.first().json.content.parts[0].text;\nconst parsed = JSON.parse(geminiResponse);\nconst telegramData = $('Telegram Trigger').first().json;\nconst chatId = String(telegramData.message.chat.id);\nconst staticData = $getWorkflowStaticData('global');\nconst waitingData = staticData.waiting_for_schedule[chatId];\n\nif (!parsed.valid) {\n  return [{\n    json: {\n      valid: false,\n      chat_id: chatId,\n      manager_chat_id: waitingData.manager_chat_id\n    }\n  }];\n}\n\n// Clear waiting state\ndelete staticData.waiting_for_schedule[chatId];\n\nconst startDateTime = parsed.date + 'T' + parsed.time + ':00';\nconst endHour = String(parseInt(parsed.time.split(':')[0]) + 1).padStart(2, '0');\nconst endDateTime = parsed.date + 'T' + endHour + ':' + parsed.time.split(':')[1] + ':00';\n\nreturn [{\n  json: {\n    valid: true,\n    date: parsed.date,\n    time: parsed.time,\n    start: startDateTime,\n    end: endDateTime,\n    chat_id: chatId,\n    manager_chat_id: 1619231316,\n    client_name: telegramData.message.from.first_name || '\u041a\u043b\u0438\u0435\u043d\u0442'\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1312,
        -128
      ],
      "id": "974b4eff-b927-4c6e-ad3b-192c87cf1401",
      "name": "Prepare Calendar Event"
    },
    {
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "text": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0442\u044c \u0434\u0430\u0442\u0443. \u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0435\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \"20 \u0430\u043f\u0440\u0435\u043b\u044f \u0432 15:00\".",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1856,
        -96
      ],
      "id": "edd0e05d-c1d7-4e6a-8a98-987a922d7339",
      "name": "Ask Again",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "calendar": {
          "__rl": true,
          "value": "0d2d2c0371d0a0ab40dade60d1f12fa11ae78242ba3c81e2e2709764786f347f@group.calendar.google.com",
          "mode": "list",
          "cachedResultName": "\u0432\u0441\u0442\u0440\u0435\u0447\u0438"
        },
        "start": "={{ $json.start }}",
        "end": "={{ $json.end }}",
        "additionalFields": {
          "description": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043e Sales Lead Qualifier Bot",
          "summary": "=\u0417\u0432\u043e\u043d\u043e\u043a \u0441 {{ $json.client_name }}"
        }
      },
      "type": "n8n-nodes-base.googleCalendar",
      "typeVersion": 1.3,
      "position": [
        1856,
        -256
      ],
      "id": "32061aa9-85f7-4341-82b1-bc4125769845",
      "name": "Create Meeting",
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $('check for validity').item.json.chat_id }}",
        "text": "=\u2705 \u0412\u0441\u0442\u0440\u0435\u0447\u0430 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043d\u0430 {{ $('check for validity').item.json.date }} \u0432 {{ $('check for validity').item.json.time }}. \u0416\u0434\u0451\u043c \u0432\u0430\u0441!",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2064,
        -256
      ],
      "id": "9cffb594-2470-44b1-9de0-551fe9869735",
      "name": "Confirm to Client",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $json.result.chat.id }}",
        "text": "=\ud83d\udcc5 \u041d\u043e\u0432\u0430\u044f \u0432\u0441\u0442\u0440\u0435\u0447\u0430! \ud83d\udc64 {{ $json.result.chat.first_name }} \ud83d\udd50 {{ $('check for validity').item.json.date }} \u0432  {{ $('check for validity').item.json.time }}\ud83d\udccd \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 Google Calendar",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2256,
        -256
      ],
      "id": "c07d8c6f-1e18-4265-b1d3-bfd99aee3143",
      "name": "time confirmation to manager",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "d3a03a1b-52b0-4b09-ace2-02a9d5e666de",
              "leftValue": "={{ $json.valid }}",
              "rightValue": "true",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1520,
        -128
      ],
      "id": "bd57af41-d5c5-4928-946d-7304ecae98fd",
      "name": "check for validity"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "520351ed-09e1-4071-b333-e1b35b39d18b",
              "leftValue": "={{ $json.is_waiting }} ",
              "rightValue": "true",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        656,
        16
      ],
      "id": "8262dd7f-72d6-4eec-b158-c52884349bf2",
      "name": "client waiting?"
    },
    {
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.report }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        880,
        880
      ],
      "id": "e4f22270-7973-4dbf-a40a-5e8d5c643aaf",
      "name": "send a report",
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const callbackData = $input.first().json.callback_query.data;\nconst parts = callbackData.split('_');\nconst action = parts[0];\nconst clientChatId = parts.slice(1).join('_');\nconst managerChatId = $input.first().json.callback_query.message.chat.id;\nconst messageText = $input.first().json.callback_query.message.text;\n\nlet generatedResponse = \"\";\nif (messageText.includes(\"---GENERATEDRESPONSE---\")) {\n  generatedResponse = messageText\n    .split(\"---GENERATEDRESPONSE---\")[1]\n    .split(\"---ENDRESPONSE---\")[0]\n    .trim();\n}\n\nreturn [{\n  json: {\n    action: action,\n    client_chat_id: clientChatId,\n    manager_chat_id: managerChatId,\n    generated_response: generatedResponse\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        464,
        512
      ],
      "id": "75ef0a24-2a5b-4e01-a0cf-5211026289b5",
      "name": "data prepare for approve"
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nif (!staticData.waiting_for_schedule) {\n  staticData.waiting_for_schedule = {};\n}\n\nconst codeData = $('data enricher').first().json;\nconst clientChatId = String(codeData.chat_id);\nconst managerChatId = clientChatId;\n\nstaticData.waiting_for_schedule[clientChatId] = {\n  waiting: true,\n  manager_chat_id: managerChatId,\n  timestamp: new Date().toISOString()\n};\n\nreturn [$input.all()[0]];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3616,
        240
      ],
      "id": "7905ec97-ddf4-45dc-9e44-d02ae06e2324",
      "name": "set waiting"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "0e5b163b-d295-44bd-bb18-e1c826bb85a1",
              "leftValue": "={{ $json.should_notify }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        3184,
        400
      ],
      "id": "23344536-5570-41fb-9f49-98bf3ee383a8",
      "name": "should notify?"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "ad08eb74-0bc8-431f-9393-d64f67ff7e2d",
              "leftValue": "={{ $json.should_notify }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        3184,
        112
      ],
      "id": "6b668c3f-749c-49e1-8f19-1914a6ab0865",
      "name": "should notify?1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "e000d542-e62e-48d2-821a-2b729d23f787",
              "leftValue": "={{ $json.intent }}",
              "rightValue": "lead",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1520,
        192
      ],
      "id": "e9940fe3-6f46-45f1-a3cc-bea662c10577",
      "name": "intend identifier"
    },
    {
      "parameters": {
        "jsCode": "const gemini1 = $('field extracter').first().json;\nconst gemini2 = $('respond for user').first().json;\nconst telegramData = $('Telegram Trigger').first().json;\n\nconst parsed = JSON.parse($('field extracter').first().json.candidates[0].content.parts[0].text);\nconst generatedResponse = $input.first().json.content.parts[0].text;\n\n// Known companies database - no need to scrape these\nconst knownCompanies = {\n  \"Kaspi Bank\": {\n    industry: \"Fintech / Digital Banking\",\n    size: \"15,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0430\u044f \u0444\u0438\u043d\u0442\u0435\u0445-\u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430: \u0431\u0430\u043d\u043a\u0438\u043d\u0433, \u043c\u0430\u0440\u043a\u0435\u0442\u043f\u043b\u0435\u0439\u0441, \u043f\u043b\u0430\u0442\u0435\u0436\u0438, \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u044f\",\n    website: \"kaspi.kz\"\n  },\n  \"Halyk Bank\": {\n    industry: \"Banking\",\n    size: \"12,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0438\u0439 \u0431\u0430\u043d\u043a \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430 \u043f\u043e \u0430\u043a\u0442\u0438\u0432\u0430\u043c, \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u043d\u043a\u0438\u043d\u0433 \u0434\u043b\u044f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438 \u044e\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043b\u0438\u0446\",\n    website: \"halykbank.kz\"\n  },\n  \"Kolesa Group\": {\n    industry: \"Tech / Classifieds\",\n    size: \"1,500+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0430\u044f IT-\u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430: Kolesa.kz, Krisha.kz, Market.kz\",\n    website: \"kolesa.group\"\n  },\n  \"Air Astana\": {\n    industry: \"Aviation\",\n    size: \"5,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0430\u0432\u0438\u0430\u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430, \u0444\u043b\u0430\u0433\u043c\u0430\u043d\u0441\u043a\u0438\u0439 \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u0447\u0438\u043a\",\n    website: \"airastana.com\"\n  },\n  \"Freedom Finance\": {\n    industry: \"Fintech / Investments\",\n    size: \"3,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u0418\u043d\u0432\u0435\u0441\u0442\u0438\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f, \u0431\u0440\u043e\u043a\u0435\u0440\u0441\u043a\u0438\u0435 \u0443\u0441\u043b\u0443\u0433\u0438, \u0431\u0430\u043d\u043a\u0438\u043d\u0433, \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u043d\u0438\u0435\",\n    website: \"ffin.kz\"\n  },\n  \"Forte Bank\": {\n    industry: \"Banking\",\n    size: \"4,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u043d\u043a \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430, \u0440\u043e\u0437\u043d\u0438\u0447\u043d\u044b\u0439 \u0438 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0431\u0430\u043d\u043a\u0438\u043d\u0433\",\n    website: \"forte.kz\"\n  },\n  \"Technodom\": {\n    industry: \"Retail / Electronics\",\n    size: \"3,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041a\u0440\u0443\u043f\u043d\u0435\u0439\u0448\u0430\u044f \u0441\u0435\u0442\u044c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0438\u043a\u0438 \u0438 \u0431\u044b\u0442\u043e\u0432\u043e\u0439 \u0442\u0435\u0445\u043d\u0438\u043a\u0438 \u0432 \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0435\",\n    website: \"technodom.kz\"\n  },\n  \"Kazakhtelecom\": {\n    industry: \"Telecom\",\n    size: \"20,000+ \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432\",\n    description: \"\u041d\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u043b\u0435\u043a\u043e\u043c-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u041a\u0430\u0437\u0430\u0445\u0441\u0442\u0430\u043d\u0430\",\n    website: \"telecom.kz\"\n  }\n};\n\n// Check if company is in our known database\nlet enrichment = null;\nlet enrichmentSource = \"none\";\n\nif (parsed.company && knownCompanies[parsed.company]) {\n  const info = knownCompanies[parsed.company];\n  enrichment = `${parsed.company} \u2014 ${info.industry}, ${info.size}. ${info.description}`;\n  enrichmentSource = \"known_database\";\n} else if (parsed.company) {\n  enrichment = `\u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \"${parsed.company}\" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439. \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u043e\u0439 \u0430\u043d\u0430\u043b\u0438\u0437.`;\n  enrichmentSource = \"unknown_needs_research\";\n} else {\n  enrichment = \"\u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430\";\n  enrichmentSource = \"not_provided\";\n}\n\nreturn [{\n  json: {\n    ...parsed,\n    generated_response: generatedResponse,\n    enrichment: enrichment,\n    enrichment_source: enrichmentSource,\n    original_text: telegramData.message.text,\n    chat_id: telegramData.message.chat.id,\n    sender_name: telegramData.message.from.first_name,\n    sender_username: telegramData.message.from.username\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2496,
        96
      ],
      "id": "6a796eaa-48a8-4d92-9b35-fe02a69a87fb",
      "name": "data enricher"
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet": {
      "main": [
        [
          {
            "node": "check for category",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message to Managers": {
      "main": [
        []
      ]
    },
    "respond for user": {
      "main": [
        [
          {
            "node": "data enricher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "field extracter": {
      

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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Sales Lead Qualifier. Uses telegramTrigger, googleSheets, telegram, googleGemini. Event-driven trigger; 41 nodes.

Source: https://github.com/aibarC/sales-lead-qualifier/blob/2b5743e973d0bc4849474ae64938d8534fafa3e3/workflow.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

This workflow is a complete, AI-powered content engine designed to help automation experts build their personal brand on LinkedIn. It transforms a technical n8n workflow (in JSON format) into a polish

Stop And Error, Telegram Trigger, Telegram +4
AI & RAG

Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.

Telegram Trigger, OpenAI, Google Sheets +2
AI & RAG

Most expense tracker apps (like Money Lover, Spendee, or Wallet) have a common friction point: Data Entry. You have to unlock your phone, find the app, wait for it to load, navigate menus, and manuall

Google Sheets, Google Gemini, Telegram +2
AI & RAG

&gt; ⚠️ Disclaimer: This workflow uses Community Nodes and must be run on a self-hosted instance of n8n.

HTTP Request, Telegram Trigger, Telegram +2
AI & RAG

Viral Tik Tok Clone Finder. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 41 nodes.

HTTP Request, Telegram Trigger, OpenAI +2