AutomationFlowsAI & RAG › Voice & Text Control for Home Assistant Using Telegram, Whisper & Gemini

Voice & Text Control for Home Assistant Using Telegram, Whisper & Gemini

ByArkadiusz @akadiusz on n8n.io

This workflow creates a conversational bridge between Telegram / n8n Chat and Home Assistant. It allows users to control smart home devices or request information using natural language (text or voice).

Event trigger★★★★★ complexityAI-powered30 nodesTelegram TriggerTelegramOpenAIMemory Buffer WindowMcp Client ToolAgentGoogle Gemini ChatChat Trigger
AI & RAG Trigger: Event Nodes: 30 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #8411 — we link there as the canonical source.

This workflow follows the Agent → Chat Trigger 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "7e0b01ef-5cf7-4e9f-9aed-8870278982de",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -1392,
        -176
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "827393b8-ce03-4c88-8844-ac02930ef543",
      "name": "Telegram Send",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1328,
        -32
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "HTML"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "15b61fb1-26d0-40e1-8760-d1a458600d37",
      "name": "Reply Router",
      "type": "n8n-nodes-base.if",
      "position": [
        768,
        32
      ],
      "parameters": {
        "options": {
          "ignoreCase": false
        },
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e3b6656-fab8-49d5-9ed0-54bd8b6a8729",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Process messages').item.json.source }}",
              "rightValue": "telegram"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "cef7c350-5225-434e-b81d-27d9ede69b8e",
      "name": "Telegram Message Beautifier",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        -32
      ],
      "parameters": {
        "jsCode": "let text = $json.output;\n\n// 1. Zamie\u0144 **co\u015b** na <b>co\u015b</b>\ntext = text.replace(/\\*\\*(.*?)\\*\\*/g, '<b>$1</b>');\n\n// 2. Zamie\u0144 *   <b>Co\u015b:</b> ... na bullet z boldem\ntext = text.replace(/^\\*\\s+<b>([^<]+):<\\/b>/gm, '\u2022 <b>$1:</b>');\n\n// 3. Zamie\u0144 *   Co\u015b: ... na bullet z boldem (gdy nie ma bolda)\ntext = text.replace(/^\\*\\s+([^:]+):/gm, '\u2022 <b>$1:</b>');\n\n// 4. Zamie\u0144 `code` na <code>\ntext = text.replace(/`([^`]+)`/g, '<code>$1</code>');\n\n// 5. Zamie\u0144 podw\u00f3jne nowe linie na pojedyncze (\u017ceby nie by\u0142o za du\u017cych przerw)\ntext = text.replace(/\\n{3,}/g, '\\n\\n');\n\n// 6. (Opcjonalnie) Zamie\u0144 linki [tekst](url) na <a href=\"url\">tekst</a>\ntext = text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\">$1</a>');\n\n// 7. Chunking\nconst chunkSize = 4096;\nconst chunks = [];\nfor (let i = 0; i < text.length; i += chunkSize) {\n  chunks.push({ text: text.substring(i, i + chunkSize) });\n}\n\nreturn chunks;"
      },
      "typeVersion": 2
    },
    {
      "id": "46595cbb-4be2-4561-90b5-d1d3b5602a25",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        144
      ],
      "parameters": {
        "options": {},
        "respondWith": "text",
        "responseBody": "={{ $json.output }}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "b729b4fc-c986-4773-bef2-f49ab4a1b895",
      "name": "Transcription to ChatInput",
      "type": "n8n-nodes-base.set",
      "position": [
        -256,
        -176
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "chatInput",
              "stringValue": "={{ $json.text }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "154315db-df92-449d-9930-94139e8012e9",
      "name": "Get Voice File",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -544,
        -176
      ],
      "parameters": {
        "fileId": "={{ $json.message.voice.file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "0748b3dd-b6fc-4a12-b433-a7d09c65cc7f",
      "name": "Voice or Text",
      "type": "n8n-nodes-base.set",
      "position": [
        -992,
        -64
      ],
      "parameters": {
        "fields": {
          "values": [
            {
              "name": "text",
              "stringValue": "={{ $json?.message?.text || \"\" }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "d99898a9-6619-422d-928c-d371812c1f5e",
      "name": "Speech to Text",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -400,
        -176
      ],
      "parameters": {
        "options": {},
        "resource": "audio",
        "operation": "transcribe"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "acfc8962-6ae2-4ddb-9429-2bfc50e04eb2",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -832,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a0bf9719-4272-46f6-ab3b-eda6f7b44fd8",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.message.text }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fafce53a-2570-4ae9-b92c-029485cf3890",
      "name": "Process messages",
      "type": "n8n-nodes-base.code",
      "position": [
        16,
        32
      ],
      "parameters": {
        "jsCode": "// Helper: bezpieczne czytanie z innych nod\u00f3w\nfunction safe(getter, fallback = undefined) {\n  try {\n    const v = getter();\n    return v === undefined || v === null ? fallback : v;\n  } catch (e) {\n    return fallback;\n  }\n}\n\n// Spr\u00f3buj pobra\u0107 oba \u017ar\u00f3d\u0142a, ale bez crasha:\nconst tgMsg   = safe(() => $('Telegram Trigger').item.json.message, null);\nconst chatEvt = safe(() => $('When chat message received').item.json, null);\n\n// Pick-first\nconst pick = (...arr) => arr.find(v => typeof v === 'string' && v.trim()) || '';\n\n// Tekst z r\u00f3\u017cnych miejsc (STT -> chatInput, tekst, itd.)\nconst inputText = pick(\n  $json.inputText,\n  $json.chatInput,\n  $json.text,\n  $json.message?.text,\n  tgMsg?.text,\n  chatEvt?.message,\n  chatEvt?.input,\n  chatEvt?.text\n);\n\n// \u0179r\u00f3d\u0142o\nlet source = 'chat';\nif (tgMsg) source = 'telegram';\nelse if (chatEvt) source = 'n8n-chat';\n\n// SessionId\nlet sessionId = 'unknown';\nif (tgMsg) {\n  sessionId = String(tgMsg.chat?.id ?? tgMsg.from?.id ?? 'telegram-unknown');\n} else if (chatEvt) {\n  sessionId = String(\n    chatEvt.sessionId ?? chatEvt.chatId ?? chatEvt.connectionId ?? chatEvt.userId ?? 'n8n-chat-unknown'\n  );\n} else if ($json.chatId) {\n  sessionId = String($json.chatId);\n}\n\n// Voice flag (na przysz\u0142o\u015b\u0107)\nconst isVoice = Boolean(safe(() => $('Telegram Trigger').item.json.message.voice.file_id, null));\n\nreturn [{\n  json: {\n    inputText: inputText.trim(),\n    source,\n    sessionId,\n    isVoice\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "55de43ac-f154-4025-9f31-78b8466a497f",
      "name": "Bot Is typing",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -992,
        -256
      ],
      "parameters": {
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "operation": "sendChatAction"
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "58b26df3-00e6-48c6-bd1a-209dd6c63ec3",
      "name": "Simple Memory1",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -1312,
        480
      ],
      "parameters": {},
      "typeVersion": 1.3
    },
    {
      "id": "fa7b3918-2f19-4b32-896b-83fb8ea2b400",
      "name": "Home assistant Connector",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        512,
        272
      ],
      "parameters": {
        "include": "selected",
        "options": {},
        "endpointUrl": "http://0.0.0.0:8123/mcp_server/sse",
        "includeTools": [
          "GetLiveContext",
          "HassTurnOn",
          "HassTurnOff",
          "HassLightSet",
          "HassBroadcast"
        ],
        "authentication": "bearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "b7a623d6-f689-4687-bc66-275b1f73a63a",
      "name": "Home Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        304,
        32
      ],
      "parameters": {
        "text": "={{ $json.inputText }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2
    },
    {
      "id": "60021ab2-33cb-46e1-87e0-3d7f9d1e56fe",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        368,
        272
      ],
      "parameters": {},
      "typeVersion": 1.3
    },
    {
      "id": "c51dc09b-ad53-4a1d-8b38-59a950d9d31c",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        224,
        272
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8c61f905-4040-44ff-aed9-3b36ecbc6daf",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -1312,
        272
      ],
      "parameters": {
        "public": true,
        "options": {
          "loadPreviousSession": "memory"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "4117eb44-33aa-4d3c-b032-4de7a50f5b15",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1632,
        208
      ],
      "parameters": {
        "width": 256,
        "height": 224,
        "content": "## When chat message received:\n\nCaptures messages from n8n\u2019s built-in chat and feeds into normalization pipeline.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d1904d79-7004-445e-bc8e-ef056163a464",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1696,
        -208
      ],
      "parameters": {
        "content": "## Telegram Trigger:\nListens for incoming Telegram messages (text or voice).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fb31fb1c-c1ae-49fa-abb4-f239ed349706",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        -432
      ],
      "parameters": {
        "content": "## Bot Is typing:\nSends \u201ctyping\u2026\u201d action back to Telegram for better UX feedback."
      },
      "typeVersion": 1
    },
    {
      "id": "90ddab99-91db-419f-8190-7d5bfd74fdb9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        80
      ],
      "parameters": {
        "color": 4,
        "width": 400,
        "content": "## Voice or Text:\nChecks if the message is voice \u2192 routes to STT; otherwise uses text directly.\n## If Voice Node:\nBranch: if text missing, route through speech transcription."
      },
      "typeVersion": 1
    },
    {
      "id": "b5f91665-8eac-4ded-80cc-3bad4444d972",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -576,
        -448
      ],
      "parameters": {
        "color": 4,
        "width": 448,
        "height": 240,
        "content": "### Get Voice File:\nDownloads the voice message from Telegram for transcription.\n\n### Speech to Text:\nTranscribes voice input into text using OpenAI Whisper.\n\n### Transcription to ChatInput:\nMaps transcribed text into unified chatInput field."
      },
      "typeVersion": 1
    },
    {
      "id": "d93fb3d9-06d2-43eb-8c46-0c133ab636c3",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        -160
      ],
      "parameters": {
        "color": 4,
        "content": "### Process messages:\nNormalizes inputText, detects source (chat/telegram), and builds sessionId."
      },
      "typeVersion": 1
    },
    {
      "id": "d326f85d-61a1-4f29-8f52-207313b79a3a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1040,
        -208
      ],
      "parameters": {
        "content": "### Telegram Message Beautifier:\nFormats output: bold, bullets, inline code, links \u2013 splits into chunks."
      },
      "typeVersion": 1
    },
    {
      "id": "dfb1166c-9e3f-4b58-8cbf-021ab731c0c0",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -160
      ],
      "parameters": {
        "content": "## Home Agent:\nCore AI agent that orchestrates LLM and Home Assistant actions."
      },
      "typeVersion": 1
    },
    {
      "id": "c9f34a9e-b13b-43da-a45d-472b4ffb8a7a",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        416
      ],
      "parameters": {
        "width": 208,
        "height": 192,
        "content": "## Home Assistant Connector:\n\nExecutes smart home actions: turn lights on/off, set brightness, broadcast messages via MCP.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6f6e3028-9886-40dd-a17a-e82aa94f9747",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        -160
      ],
      "parameters": {
        "content": "## Reply Router:\nRoutes response back to Telegram or n8n chat UI depending on origin.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8e5c9b6c-8ad1-494e-a754-115f830d27bd",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1312,
        160
      ],
      "parameters": {
        "width": 272,
        "height": 240,
        "content": "### Telegram Send:\nSends formatted reply back to Telegram in HTML parse mode.\n\n### Respond to Webhook:\nStreams responses back to the n8n chat frontend webhook."
      },
      "typeVersion": 1
    },
    {
      "id": "5f8b5ae2-d736-40c0-9db6-daef3256f894",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1792,
        -752
      ],
      "parameters": {
        "color": 3,
        "width": 592,
        "height": 448,
        "content": "**Workflow Name:** Home Assistant Whisper\n\n**What it does:**\nThis workflow bridges natural conversation (via Telegram or n8n Chat) with Home Assistant. Users send commands\u2014text or voice\u2014and the system:\n* Transcribes voice using Whisper\n* Normalizes input, maintains session context\n* Uses Google Gemini + an AI agent to understand intent\n* Triggers smart home actions via MCP (turn lights on/off, adjust brightness, broadcast)\n* Formats and routes responses back to the correct channel\u2014Telegram or n8n Chat\u2014with polished markdown/HTML formatting.\n\n**Key highlights:**\n- Multi-channel (chat + voice)\n- Short-term memory for context\n- AI-powered intent understanding\n- Smart routing and beautified responses\n- Modular design\u2014easy to extend or tweak"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Get Voice File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Process messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Home Agent": {
      "main": [
        [
          {
            "node": "Reply Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reply Router": {
      "main": [
        [
          {
            "node": "Telegram Message Beautifier",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "Home Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Voice or Text": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Voice File": {
      "main": [
        [
          {
            "node": "Speech to Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory1": {
      "ai_memory": [
        [
          {
            "node": "When chat message received",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Speech to Text": {
      "main": [
        [
          {
            "node": "Transcription to ChatInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process messages": {
      "main": [
        [
          {
            "node": "Home Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Voice or Text",
            "type": "main",
            "index": 0
          },
          {
            "node": "Bot Is typing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Home Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Home assistant Connector": {
      "ai_tool": [
        [
          {
            "node": "Home Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Transcription to ChatInput": {
      "main": [
        [
          {
            "node": "Process messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Process messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Message Beautifier": {
      "main": [
        [
          {
            "node": "Telegram Send",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

This workflow creates a conversational bridge between Telegram / n8n Chat and Home Assistant. It allows users to control smart home devices or request information using natural language (text or voice).

Source: https://n8n.io/workflows/8411/ — 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

Transform your salon/service business with this streamlined Telegram automation system featuring Claude integration, zero-setup database management, and intelligent conversation handling. Claude MCP I

Redis, Agent Tool, Google Calendar +10
AI & RAG

This automation is designed to help you generate AI-powered music tracks, cover art, and fully rendered music videos — all triggered from a simple Telegram chat and managed via Google Sheets.

OpenAI Chat, Memory Buffer Window, Output Parser Structured +11
AI & RAG

Multi Agent System Benefits. Uses gmailTool, lmChatOpenAi, agent, googleCalendarTool. Event-driven trigger; 46 nodes.

Gmail Tool, OpenAI Chat, Agent +12
AI & RAG

AI marketing Team Agent. Uses toolWorkflow, telegram, memoryBufferWindow, openAi. Event-driven trigger; 46 nodes.

Tool Workflow, Telegram, Memory Buffer Window +10
AI & RAG

This n8n workflow is designed for WooCommerce store owners and e-commerce managers who want to automate their store operations through an intelligent AI assistant. The workflow creates a conversationa

Discord, Telegram, N8N Nodes Rapiwa +10