Skip to content

Instantly share code, notes, and snippets.

@oceanflowai
Created December 21, 2025 10:03
Show Gist options
  • Select an option

  • Save oceanflowai/4bb7400b49b3941e781c7acc847b4501 to your computer and use it in GitHub Desktop.

Select an option

Save oceanflowai/4bb7400b49b3941e781c7acc847b4501 to your computer and use it in GitHub Desktop.
Human In The Loop Implementation with Telegram

Note: This workflow uses n8n Data Tables. To make it work, create a table named customer_data with the following columns: chatId (String) sessionState (String) notificationStatus (String)

{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
400,
912
],
"id": "ad37a38c-823d-443c-bfea-fde5fb959517",
"name": "No Operation, do nothing"
},
{
"parameters": {
"content": "## User Validation",
"height": 624,
"width": 1120,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
528
],
"typeVersion": 1,
"id": "fdd73572-a1e3-42d9-9f2b-43333049de66",
"name": "Sticky Note3"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose",
"version": 2
},
"conditions": [
{
"id": "cd5c3565-fd9b-4515-bcab-5253514e7429",
"leftValue": "={{ $json }}",
"rightValue": "={{ 0 }}",
"operator": {
"type": "object",
"operation": "notEmpty",
"singleValue": true
}
}
],
"combinator": "and"
},
"looseTypeValidation": true,
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
624,
672
],
"id": "30439013-d06a-4002-8ef0-aa3942490ba9",
"name": "User exists?"
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
-48,
784
],
"id": "9329c8fa-ef9d-4e83-80db-b3a68a15e947",
"name": "Telegram Trigger",
"webhookId": "47f1bf80-f618-4922-a3a0-7d7c427aebe9",
"credentials": {
"telegramApi": {
"id": "cTvKlwYFtIOGlHBo",
"name": "Telegram account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"id": "msg-check",
"leftValue": "={{ $json.message.text }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
176,
784
],
"id": "e322bb46-86f1-43bc-8655-75944fe0dcb0",
"name": "text?"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $('getUsers').item.json.sessionState }}",
"rightValue": "AI",
"operator": {
"type": "string",
"operation": "equals"
},
"id": "a0a3d893-e65c-44c5-ade1-bc20538de5c9"
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "AI Mode"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"leftValue": "={{ $('getUsers').item.json.sessionState }}",
"rightValue": "HUMAN",
"operator": {
"type": "string",
"operation": "equals"
},
"id": "e069bfe6-3ebf-4159-a328-432b17fe1383"
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Human Mode"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
848,
672
],
"id": "9d05fe81-0d2a-48a2-83fa-7d23e28ca09e",
"name": "Route by Session State"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Telegram Trigger').item.json.message.text }}",
"options": {
"systemMessage": "=# IDENTITY & ROLE\nYou are a professional dental clinic assistant designed to help patients with their dental care inquiries. Your role is to provide accurate, helpful, and empathetic responses while maintaining strict boundaries.\n\n# OUTPUT FORMAT\n**CRITICAL**: You must **ALWAYS** generate your output as a valid JSON object. Do not include markdown formatting (like ```json) or any text outside the JSON block.\n\n**JSON Structure:**\n{\n \"response\": \"Your actual reply to the user goes here.\",\n \"handoff\": boolean\n}\n\n# HUMAN HANDOFF LOGIC\nDetermine the value of the \"handoff\" boolean based on the user's input.\n\n**Set \"handoff\": true if:**\n- User explicitly requests to speak with a human/staff member\n- Medical emergencies or urgent situations\n- User expresses frustration, anger, or dissatisfaction\n- Complex medical questions beyond your knowledge\n- User requests escalation to manager/supervisor\n\n**Set \"handoff\": false if:**\n- The query is a standard inquiry, appointment request, or general chat handled successfully by you.\n\n# TOOLS AVAILABLE\n\n## Tool: Pinecone Vector Store\n- **Usage**: Query this tool to answer dental clinic questions about services, pricing, procedures, or policies.\n- **Constraints**: \n - Do not make up information; base the text in your \"response\" field ONLY on retrieved data.\n - If no results are found, your \"response\" should state: \"I don't have that specific information in my knowledge base. I'd recommend calling our clinic or scheduling a consultation.\"\n\n# RESPONSE GUIDELINES\n- **Content**: Place your natural language reply inside the \"response\" JSON field.\n- **Conciseness**: Keep the response under 150 words using simple, clear language.\n- **Medical Safety**: Do not provide diagnoses. Always recommend consulting a dentist for specific concerns.\n- **Closing**: Always end the \"response\" text with an invitation to schedule an appointment.\n\n# CONTEXT AWARENESS\n- The current date and time is: {{ $now }}\n- Use dollar pricing when relevant."
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3,
"position": [
1152,
656
],
"id": "f3c2f73b-a1be-4df5-830a-c0076f24023e",
"name": "AI Agent"
},
{
"parameters": {
"content": "## AI Response",
"height": 624,
"width": 592,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
1056,
528
],
"typeVersion": 1,
"id": "180fe3ea-8fdf-4670-a1aa-3ebaf7874dd5",
"name": "Sticky Note"
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
},
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"typeVersion": 1.3,
"position": [
1216,
864
],
"id": "e644a182-438c-4875-b315-340b72436482",
"name": "Simple Memory"
},
{
"parameters": {
"mode": "retrieve-as-tool",
"toolDescription": "List of Frequently Asked Questions ",
"pineconeIndex": {
"__rl": true,
"value": "faq",
"mode": "list",
"cachedResultName": "faq"
},
"topK": 3,
"options": {
"pineconeNamespace": "faq"
}
},
"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
"typeVersion": 1.3,
"position": [
1344,
864
],
"id": "fd232b9a-48d7-4ce3-a12e-7e1d1b961bcb",
"name": "Pinecone Vector Store",
"credentials": {
"pineconeApi": {
"id": "bUYUwybh4wJt4RHu",
"name": "PineconeApi account"
}
}
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"text": "={{ JSON.parse($('AI Agent').item.json.output).response }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1472,
656
],
"id": "1cf6100b-785e-41b1-8287-ef4add25497d",
"name": "sendMessage",
"webhookId": "a8e09532-edfa-41cf-b98c-d1f3e16de86f",
"credentials": {
"telegramApi": {
"id": "cTvKlwYFtIOGlHBo",
"name": "Telegram account"
}
}
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"filters": {
"conditions": [
{
"keyName": "chatId",
"keyValue": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
}
]
}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
400,
672
],
"id": "d857affe-f093-49a8-a665-5a480c9f8f39",
"name": "getUsers",
"alwaysOutputData": true
},
{
"parameters": {
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"sessionState": "AI",
"notificationStatus": "NA"
},
"matchingColumns": [],
"schema": [
{
"id": "chatId",
"displayName": "chatId",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "sessionState",
"displayName": "sessionState",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "notificationStatus",
"displayName": "notificationStatus",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
848,
864
],
"id": "dd4d96c3-5d72-407f-bd2a-9d1f5db1f810",
"name": "createUser"
},
{
"parameters": {
"content": "## Check Handoff Status\n",
"height": 624,
"width": 1104,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
528
],
"typeVersion": 1,
"id": "2d1b507d-58fa-4c7c-9ce7-cdc781ee2628",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "## Send Notif --- Link Receptionist number to notify staff\n** Add multiple send message nodes to send message to multiple receptionists**\n",
"height": 240,
"width": 640,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"position": [
2112,
592
],
"typeVersion": 1,
"id": "ddb780cd-0ad9-4d34-b58f-2a0c69e0d569",
"name": "Sticky Note5"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "check-handoff-flag",
"leftValue": "={{ JSON.parse($('AI Agent').item.json.output).handoff }}",
"rightValue": "true",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1712,
656
],
"id": "d756afb6-a60c-42ab-b586-1120c4cec4e3",
"name": "Route to Human?"
},
{
"parameters": {
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"filters": {
"conditions": [
{
"keyName": "chatId",
"keyValue": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"notificationStatus": "SENT"
},
"matchingColumns": [],
"schema": [
{
"id": "chatId",
"displayName": "chatId",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
},
{
"id": "sessionState",
"displayName": "sessionState",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
},
{
"id": "notificationStatus",
"displayName": "notificationStatus",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
2496,
672
],
"id": "64c8b5a3-1778-419e-bc60-6fd34374063c",
"name": "updateNotificationSent"
},
{
"parameters": {
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"filters": {
"conditions": [
{
"keyName": "chatId",
"keyValue": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"sessionState": "HUMAN"
},
"matchingColumns": [],
"schema": [
{
"id": "chatId",
"displayName": "chatId",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
},
{
"id": "sessionState",
"displayName": "sessionState",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "notificationStatus",
"displayName": "notificationStatus",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
1968,
656
],
"id": "5bee7e4f-21d8-43d0-8d92-5afbea1dea2c",
"name": "updateSessionState"
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
"text": "={{ $('Telegram Trigger').item.json.message.from.username }} needs assistance",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
2192,
672
],
"id": "a023ea29-24d6-4922-b0ef-4cd6422c31e9",
"name": "notifyStaff",
"webhookId": "a1145a93-0137-4456-8c29-2d8860460085",
"credentials": {
"telegramApi": {
"id": "cTvKlwYFtIOGlHBo",
"name": "Telegram account"
}
}
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1.2,
"position": [
1344,
1024
],
"id": "780eb89d-0412-4dd8-aec7-23c8901dba2d",
"name": "Embeddings OpenAI",
"credentials": {
"openAiApi": {
"id": "gjClFX0KozbOZcCw",
"name": "OpenAi account"
}
}
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4o",
"mode": "list",
"cachedResultName": "gpt-4o"
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
1104,
848
],
"id": "8f910c34-2663-4a6b-bfa8-843b724b5375",
"name": "openai",
"credentials": {
"openAiApi": {
"id": "gjClFX0KozbOZcCw",
"name": "OpenAi account"
}
}
},
{
"parameters": {
"operation": "update",
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"matchType": "allConditions",
"filters": {
"conditions": [
{
"keyName": "chatId",
"keyValue": "={{ $json.chatId }}"
}
]
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"sessionState": "AI",
"notificationStatus": "NA"
},
"matchingColumns": [],
"schema": [
{
"id": "chatId",
"displayName": "chatId",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": true
},
{
"id": "sessionState",
"displayName": "sessionState",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "notificationStatus",
"displayName": "notificationStatus",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
1600,
1280
],
"id": "807d5129-3b17-490c-af74-09700d375fad",
"name": "Change Session State to AI"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose",
"version": 2
},
"conditions": [
{
"id": "fe3f3c08-60fb-4ed6-878c-ec4d02cb4fe5",
"leftValue": "={{ new Date($json.updatedAt).getTime() + 1 < $now.toMillis() }}",
"rightValue": "={{$now}}",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"looseTypeValidation": true,
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1344,
1296
],
"id": "1291e206-49d2-4a04-a892-9313514d2932",
"name": "sessionState Expired?"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "HzWmquuNap3sX73X",
"mode": "list",
"cachedResultName": "customer_data",
"cachedResultUrl": "/projects/8vh2OLJ8oWoWiVpS/datatables/HzWmquuNap3sX73X"
},
"filters": {
"conditions": [
{
"keyName": "sessionState",
"keyValue": "HUMAN"
}
]
},
"returnAll": true
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
1152,
1296
],
"id": "7a87781f-c559-4ee7-9909-a6e3a0878b54",
"name": "Get User Info"
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 10
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
944,
1296
],
"id": "a4a4b9d2-2558-4f5e-b8e8-e399505a2ede",
"name": "Schedule Trigger"
},
{
"parameters": {
"content": "## Route back to AI after time expiry - Issue resolved\n",
"height": 240,
"width": 960,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
1216
],
"typeVersion": 1,
"id": "9e13155f-57c7-48cd-a05a-81a3b538e53d",
"name": "Sticky Note6"
}
],
"connections": {
"User exists?": {
"main": [
[
{
"node": "Route by Session State",
"type": "main",
"index": 0
}
],
[
{
"node": "createUser",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "text?",
"type": "main",
"index": 0
}
]
]
},
"text?": {
"main": [
[
{
"node": "getUsers",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Route by Session State": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "sendMessage",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Pinecone Vector Store": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"sendMessage": {
"main": [
[
{
"node": "Route to Human?",
"type": "main",
"index": 0
}
]
]
},
"getUsers": {
"main": [
[
{
"node": "User exists?",
"type": "main",
"index": 0
}
]
]
},
"createUser": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Route to Human?": {
"main": [
[
{
"node": "updateSessionState",
"type": "main",
"index": 0
}
]
]
},
"updateSessionState": {
"main": [
[
{
"node": "notifyStaff",
"type": "main",
"index": 0
}
]
]
},
"notifyStaff": {
"main": [
[
{
"node": "updateNotificationSent",
"type": "main",
"index": 0
}
]
]
},
"Embeddings OpenAI": {
"ai_embedding": [
[
{
"node": "Pinecone Vector Store",
"type": "ai_embedding",
"index": 0
}
]
]
},
"openai": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"sessionState Expired?": {
"main": [
[
{
"node": "Change Session State to AI",
"type": "main",
"index": 0
}
]
]
},
"Get User Info": {
"main": [
[
{
"node": "sessionState Expired?",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get User Info",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "5ac9c1a74f48092d46e5fa8e52cb9775cdb881c2caff3b8f05b7258dbb3d9ded"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment