HR helpdesk AI agent on Telegram
Employees ask about leave, policies and payday on Telegram; the agent answers from your handbook and logs leave requests.
How it works
- An employee asks a question in the HR bot.
- The agent searches your policy sheet and answers from it.
- For leave, it checks their balance, confirms the dates and logs the request.
- It alerts HR about new requests and anything it can't answer.
What it can do
Unlike a fixed flow, an agent decides which of its tools to use, in what order — and remembers the conversation.
- Answers policy questions in Arabic or English from your handbook
- Looks up an employee's leave balance by their Telegram ID
- Logs leave requests with dates, type and reason
- Passes complaints and sensitive topics straight to HR
System prompt
The instructions that shape the agent. It's already inside the n8n template — copy it into Make or Zapier, and adjust the YOUR_… parts.
You are the HR assistant for YOUR_COMPANY on Telegram. Reply in the employee's language (Arabic or English). Be friendly, clear and brief. Today is {{ $now.toFormat('cccc d LLLL yyyy') }}.
The employee's Telegram ID is {{ $('Get message').item.json.userId }}.
Tools:
- "Search policies": our HR handbook (topic, policy). Use it for any question about leave, working hours, remote work, payday, benefits or expenses. Answer only from it.
- "My record": this employee's own record (name, department, manager, leave balances). It only ever returns the person who is asking.
- "Log leave request": logs a leave request. Use only after the employee confirms the type, start date, end date and reason, and after checking their balance.
- "Notify HR": alerts the HR team. Use it for every leave request, and for complaints, harassment, health, salary disputes, resignations, or anything you can't answer.
Rules:
- If "My record" returns nothing, tell the employee they're not registered yet and use "Notify HR".
- Never approve or reject leave. Tell them HR will confirm.
- Never share information about other employees, and never discuss anyone's salary.
- You don't give legal advice. For labour-law questions, say HR will follow up.
- For sensitive topics, don't ask for details: say a person from HR will contact them privately, and use "Notify HR".Safety rules
Built into the prompt and the tools:
- Only shows an employee their own record
- Never approves leave itself; HR decides
- Never gives legal advice or discusses other employees' salaries
Uses your own AI key (Claude, OpenAI or another model). Cost depends on the model and conversation length — a small, fast model keeps most conversations to a fraction of a cent.
Diagram
Code
JavaScript used in the Code step — already included in the template below.
// Keeps only text messages and pulls out who sent it and what they asked.
const msg = $input.first().json.message;
if (!msg?.text) return [];
return [{
json: {
chatId: msg.chat.id,
userId: msg.from.id,
name: [msg.from.first_name, msg.from.last_name].filter(Boolean).join(" "),
question: msg.text,
},
}];Build it
Pick your tool — same automation, step by step.
Copy and paste straight into an n8n canvas (Ctrl+V), or download and use Import from File. Then connect your own credentials and replace every YOUR_… placeholder. AI steps use a Claude model node — swap it for OpenAI, Gemini or Ollama if you prefer.
Show code (344 lines)
{
"name": "HR helpdesk AI agent on Telegram (Flowngn)",
"nodes": [
{
"parameters": {
"content": "## HR helpdesk AI agent on Telegram\nEmployees ask about leave, policies and payday on Telegram; the agent answers from your handbook and logs leave requests.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
"height": 260,
"width": 340
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Setup notes",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-420,
-60
]
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Incoming message",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.1,
"position": [
0,
0
],
"webhookId": "3757cdac-8539-4016-a7ed-1a9451c69357"
},
{
"parameters": {
"jsCode": "// Keeps only text messages and pulls out who sent it and what they asked.\nconst msg = $input.first().json.message;\nif (!msg?.text) return [];\n\nreturn [{\n json: {\n chatId: msg.chat.id,\n userId: msg.from.id,\n name: [msg.from.first_name, msg.from.last_name].filter(Boolean).join(\" \"),\n question: msg.text,\n },\n}];"
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Get message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
300,
0
]
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Get message').item.json.question }}",
"options": {
"systemMessage": "=You are the HR assistant for YOUR_COMPANY on Telegram. Reply in the employee's language (Arabic or English). Be friendly, clear and brief. Today is {{ $now.toFormat('cccc d LLLL yyyy') }}.\n\nThe employee's Telegram ID is {{ $('Get message').item.json.userId }}.\n\nTools:\n- \"Search policies\": our HR handbook (topic, policy). Use it for any question about leave, working hours, remote work, payday, benefits or expenses. Answer only from it.\n- \"My record\": this employee's own record (name, department, manager, leave balances). It only ever returns the person who is asking.\n- \"Log leave request\": logs a leave request. Use only after the employee confirms the type, start date, end date and reason, and after checking their balance.\n- \"Notify HR\": alerts the HR team. Use it for every leave request, and for complaints, harassment, health, salary disputes, resignations, or anything you can't answer.\n\nRules:\n- If \"My record\" returns nothing, tell the employee they're not registered yet and use \"Notify HR\".\n- Never approve or reject leave. Tell them HR will confirm.\n- Never share information about other employees, and never discuss anyone's salary.\n- You don't give legal advice. For labour-law questions, say HR will follow up.\n- For sensitive topics, don't ask for details: say a person from HR will contact them privately, and use \"Notify HR\"."
}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "HR agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.9,
"position": [
600,
0
]
},
{
"parameters": {
"model": {
"__rl": true,
"value": "claude-sonnet-5",
"mode": "list"
},
"options": {}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Claude model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"typeVersion": 1.3,
"position": [
175,
220
]
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Get message').item.json.chatId }}",
"contextWindowLength": 10
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
345,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Returns our HR handbook: topic and policy text.",
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Policies",
"mode": "name"
},
"options": {}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Search policies",
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.5,
"position": [
515,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Returns the record of the employee who is asking: name, department, manager, leave balances.",
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Employees",
"mode": "name"
},
"filtersUI": {
"values": [
{
"lookupColumn": "telegram_id",
"lookupValue": "={{ $('Get message').item.json.userId }}"
}
]
},
"options": {}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "My record",
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.5,
"position": [
685,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Logs a confirmed leave request.",
"operation": "append",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leave requests",
"mode": "name"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"date": "={{ $now.toISO() }}",
"telegram_id": "={{ $('Get message').item.json.userId }}",
"name": "={{ $('Get message').item.json.name }}",
"type": "={{ $fromAI('type', \"annual, sick, unpaid or other\", 'string') }}",
"from": "={{ $fromAI('from', \"First day YYYY-MM-DD\", 'string') }}",
"to": "={{ $fromAI('to', \"Last day YYYY-MM-DD\", 'string') }}",
"reason": "={{ $fromAI('reason', \"Reason, or empty\", 'string') }}",
"status": "pending"
}
},
"options": {}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Log leave request",
"type": "n8n-nodes-base.googleSheetsTool",
"typeVersion": 4.5,
"position": [
855,
220
]
},
{
"parameters": {
"descriptionType": "manual",
"toolDescription": "Alerts the HR team about leave requests, sensitive topics and questions you can't answer.",
"chatId": "YOUR_HR_CHAT_ID",
"text": "={{ $fromAI('message', \"What HR needs to know, including the employee's name\", 'string') }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Notify HR",
"type": "n8n-nodes-base.telegramTool",
"typeVersion": 1.2,
"position": [
1025,
220
]
},
{
"parameters": {
"chatId": "={{ $('Get message').item.json.chatId }}",
"text": "={{ $json.output }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "3757cdac-8539-4016-a7ed-1a9451c69357",
"name": "Reply on Telegram",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
900,
0
]
}
],
"connections": {
"Incoming message": {
"main": [
[
{
"node": "Get message",
"type": "main",
"index": 0
}
]
]
},
"Get message": {
"main": [
[
{
"node": "HR agent",
"type": "main",
"index": 0
}
]
]
},
"HR agent": {
"main": [
[
{
"node": "Reply on Telegram",
"type": "main",
"index": 0
}
]
]
},
"Claude model": {
"ai_languageModel": [
[
{
"node": "HR agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Memory": {
"ai_memory": [
[
{
"node": "HR agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Search policies": {
"ai_tool": [
[
{
"node": "HR agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"My record": {
"ai_tool": [
[
{
"node": "HR agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Log leave request": {
"ai_tool": [
[
{
"node": "HR agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Notify HR": {
"ai_tool": [
[
{
"node": "HR agent",
"type": "ai_tool",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
},
"tags": []
}In Make, create a new scenario and add these modules in order:
- Telegram Bot › Watch Updates
- Tools › Set variable / Iterator + Array aggregator (same logic as the Code step)
- Make AI Agents › Run an agent — give it these tools: “Search policies” (Google Sheets), “My record” (Google Sheets), “Log leave request” (Google Sheets), “Notify HR” (Telegram Bot); paste the system prompt as the agent's instructions
- Telegram Bot › Send a Text Message or a Reply
- Every module run uses Make operations — the free plan includes a monthly quota.
- Make's built-in functions (map, sum, formatDate…) can replace most Code steps; for complex logic use a code module.
- Module and step names can differ slightly as Make and Zapier update their apps.
In Zapier, create a new Zap and add these steps in order:
- Telegram — New Message
- Code by Zapier — Run JavaScript (paste the code from the Code section)
- Zapier Agents — create an agent (or AI by Zapier for a single step) — give it these tools: “Search policies” (Google Sheets), “My record” (Google Sheets), “Log leave request” (Google Sheets), “Notify HR” (Telegram); paste the system prompt as the agent's instructions
- Telegram — Send Message
- Zaps with more than two steps need a paid Zapier plan.
- Webhooks, Filters/Paths and Code by Zapier are premium features on some Zapier plans.
- Code by Zapier runs JavaScript: reuse the code shown above, reading inputs from inputData instead of $json.
- Module and step names can differ slightly as Make and Zapier update their apps.
Tips
- Add each employee's Telegram user ID to the Employees sheet so the agent knows who is asking.
Related flows
WhatsApp sales AI agent (Arabic)
Sells on WhatsApp in the customer's own dialect: checks your catalog, answers questions and takes cash-on-delivery orders.
Order & returns AI agent on WhatsApp (Arabic)
Answers "where's my order?", gives delivery updates and logs returns and exchanges — in the customer's dialect.
Real-estate AI agent on WhatsApp
Understands what clients want, suggests matching listings and books viewings — in Arabic or English.