AutomationFlowsAI & RAG › Moss - Telegram Assistant

Moss - Telegram Assistant

Moss - Telegram Assistant. Uses telegramTrigger, agent, telegram, lmChatDeepSeek. Event-driven trigger; 11 nodes.

Event trigger★★★★☆ complexityAI-powered11 nodesTelegram TriggerAgentTelegramLm Chat Deep SeekMemory Buffer WindowTool CodeTool Workflow
AI & RAG Trigger: Event Nodes: 11 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Lmchatdeepseek 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": "Moss - Telegram Assistant",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "id": "a276483d-6e0a-440e-aab3-dd16dc3d6315",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "agent": "conversationalAgent",
        "promptType": "define",
        "text": "=={{ $json.text }}",
        "options": {
          "systemMessage": "==you are moss, a personal AI assistant, female\n\ncurrent date: {{ $now.format('yyyy-MM-dd') }}\n\n## tools\n\n### todoist\nuse todoist when the user mentions tasks, todos, or anything to track. pass a JSON string:\n- action: get_tasks | create_task | close_task | delete_task\n- filter: today | overdue (for get_tasks)\n- content: task name (for create_task)\n- due_string: e.g. \"tomorrow\" (for create_task)\n- task_id: required for close_task / delete_task\n\n### google_calendar\nuse google_calendar when the user asks about schedule, meetings, or events, or wants to add/delete them.\n- get_events: filter (today / tomorrow / this_week)\n- create_event: summary, start (ISO +08:00), end (optional), description, location\n- delete_event: event_id \u2014 ALWAYS call get_events first to find the id\n\n### google_drive\nuse google_drive when the user mentions files, documents, spreadsheets, or anything stored in Drive.\n- search_files: query (file name or keyword), max_results\n- read_file: file_id (get it from search_files first)\nOnly Google Docs/Sheets/Slides can be read as text. PDFs cannot.\n\n### gmail\nuse gmail when the user wants to read, send, search, or reply to emails.\n- send_email: to, subject, body, cc (optional)\n- search_emails: query (Gmail syntax), max_results\n- read_email: email_id \u2192 returns content + thread_id for replying\n- reply_email: thread_id, to, subject, body\nNEVER make up email content \u2014 always call the tool.\n\n## what you know about this user\n{{ $('load profile').item.json.profile || 'no profile yet' }}\n\n## behavior\n- direct and efficient. no filler phrases\n- have opinions, push back when it makes sense\n- reply in the language the user writes in\n- use structured output for complex answers\n- chain tool calls when needed (e.g. search then read, get events then delete)"
        }
      },
      "id": "d8170eb9-b39e-417b-8deb-8491f875a0e5",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        480,
        0
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "text": "={{ $json.output }}",
        "additionalFields": {
          "appendAttribution": false,
          "parse_mode": "Markdown"
        }
      },
      "id": "d5ca14c4-f805-4928-bf95-2bcb4621da84",
      "name": "Send Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        944,
        0
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatDeepSeek",
      "typeVersion": 1,
      "position": [
        144,
        208
      ],
      "id": "0419cd3e-f7c8-4785-9633-15e61570f059",
      "name": "DeepSeek Chat Model",
      "credentials": {
        "deepSeekApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const fs = require('fs');\n  const chatId = $('Telegram Trigger').item.json.message.chat.id.toString();\n  const text = $('Telegram Trigger').item.json.message.text || '';\n\n  const profilePath = '/home/node/.n8n/moss_profiles.json';\n  let profiles = {};\n  try {\n    profiles = JSON.parse(fs.readFileSync(profilePath, 'utf8'));\n  } catch(e) {\n    profiles = {};\n  }\n\n  const profile = profiles[chatId] || null;\n\n  return [{\n    json: {\n      chatId,\n      text,\n      profile: profile || '',\n      isNewUser: !profile\n    }\n  }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        0
      ],
      "id": "bf085567-0765-4132-909c-d35f9fbc1c76",
      "name": "load profile"
    },
    {
      "parameters": {
        "jsCode": "const fs = require('fs');\n  const chatId = $('load profile').item.json.chatId;\n  const userMessage = $('load profile').item.json.text;\n  const agentReply = $input.item.json.output || '';\n  const existingProfile = $('load profile').item.json.profile || '';\n\n  const profilePath = '/home/node/.n8n/moss_profiles.json';\n  let profiles = {};\n  try {\n    profiles = JSON.parse(fs.readFileSync(profilePath, 'utf8'));\n  } catch(e) {\n    profiles = {};\n  }\n\n  const currentProfile = profiles[chatId] || existingProfile;\n  const conversation = `user: ${userMessage}\\nmoss: ${agentReply}`;\n\n  profiles[chatId] = currentProfile\n    ? `${currentProfile}\\n\\n[recent] ${conversation}`.slice(-2000)\n    : `[first conversation]\\n${conversation}`;\n\n  fs.writeFileSync(profilePath, JSON.stringify(profiles, null, 2));\n\n  return [{ json: { output: agentReply, chatId } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        832,
        0
      ],
      "id": "07427a40-4bd9-4a03-a602-1c1e330626c5",
      "name": "update profile"
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Telegram Trigger').item.json.message.chat.id }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        496,
        208
      ],
      "id": "d7a3d206-e730-4f34-bbe1-866c46d1c8ae",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "description": "Manage the user's Todoist tasks. Actions: get_tasks (filter: today/overdue), create_task (content, due_string), close_task (task_id). Always get tasks first before closing.",
        "jsCode": "const https = require('https');\n  const TOKEN = 'YOUR_TODOIST_API_TOKEN';\n  const BASE = 'api.todoist.com';\n\n  function request(method, path, body) {\n    return new Promise((resolve, reject) => {\n      const data = body ? JSON.stringify(body) : null;\n      const opts = {\n        hostname: BASE,\n        path: `/api/v1${path}`,\n        method,\n        headers: {\n          'Authorization': `Bearer ${TOKEN}`,\n          'Content-Type': 'application/json',\n          ...(data ? { 'Content-Length': Buffer.byteLength(data) } : {})\n        }\n      };\n      const req = https.request(opts, res => {\n        let raw = '';\n        res.on('data', c => raw += c);\n        res.on('end', () => {\n          try { resolve({ status: res.statusCode, body: raw ? JSON.parse(raw) : {} }); }\n          catch(e) { resolve({ status: res.statusCode, body: raw }); }\n        });\n      });\n      req.on('error', reject);\n      if (data) req.write(data);\n      req.end();\n    });\n  }\n\n  let params = {};\n  try { params = JSON.parse(query); } catch(e) {\n    params = { action: 'get_tasks', filter: 'today' };\n  }\n\n  const { action = 'get_tasks', filter, content, due_string, priority, task_id } = params;\n\n  let result;\n  if (action === 'get_tasks') {\n    const res = await request('GET', `/tasks?filter=${encodeURIComponent(filter || 'today')}`);\n    const tasks = (res.body.results || []).map(t => ({ id: t.id, content: t.content, due: t.due?.string || null, priority: t.priority }));\n    result = tasks.length ? tasks : 'no tasks found';\n\n  } else if (action === 'create_task') {\n    const body = { content };\n    if (due_string) body.due_string = due_string;\n    if (priority) body.priority = priority;\n    const res = await request('POST', '/tasks', body);\n    result = res.body.id ? { created: res.body.content, id: res.body.id, due: res.body.due?.string || null } : { error: 'create failed', detail: res.body };\n\n  } else if (action === 'close_task') {\n    const res = await request('POST', `/tasks/${task_id}/close`);\n    result = res.status === 204 ? 'task marked complete' : { error: 'close failed', status: res.status };\n\n  } else if (action === 'delete_task') {\n    const res = await request('DELETE', `/tasks/${task_id}`);\n    result = res.status === 204 ? 'task deleted' : { error: 'delete failed', status: res.status };\n\n  } else {\n    result = 'unknown action. use: get_tasks, create_task, close_task, delete_task';\n  }\n\n  return JSON.stringify(result);"
      },
      "type": "@n8n/n8n-nodes-langchain.toolCode",
      "typeVersion": 1.3,
      "position": [
        896,
        208
      ],
      "id": "c2aa916a-b65b-4124-a7c0-4e74041e2feb",
      "name": "todoist"
    },
    {
      "parameters": {
        "name": "google_calendar",
        "description": "Manage the user's Google Calendar. Actions:\n- get_events: get events. filter: today | tomorrow | this_week\n- create_event: create an event. fields: summary, start (ISO datetime +08:00), end (optional), description, location\n- delete_event: delete an event. field: event_id (ALWAYS call get_events first to get the ID)\n\nALWAYS call this tool when asked about schedule or events \u2014 never make up data.\nFor delete: first get_events to find the right event and its id, then delete_event with that id.",
        "workflowId": {
          "__rl": true,
          "value": "moss-cal-tool-001",
          "mode": "id"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2,
      "position": [
        1104,
        208
      ],
      "id": "node-cal-tool",
      "name": "google calendar"
    },
    {
      "parameters": {
        "name": "google_drive",
        "description": "Access the user's Google Drive. Actions:\n- search_files: find files by name. fields: query (search term), max_results (optional, default 10)\n- read_file: read text content of a Google Doc, Sheet, or Slides file. field: file_id (from search_files)\n\nUse search_files first to find the file ID, then read_file to get content.\nNote: only Google Workspace files (Docs/Sheets/Slides) support read_file \u2014 PDFs/images cannot be read as text.",
        "workflowId": {
          "__rl": true,
          "value": "moss-drive-001",
          "mode": "id"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.1,
      "position": [
        800,
        300
      ],
      "id": "node-drive-tool",
      "name": "google_drive"
    },
    {
      "parameters": {
        "name": "gmail",
        "description": "Access the user's Gmail. Actions:\n- send_email: send an email. fields: to, subject, body, cc (optional), bcc (optional)\n- search_emails: search inbox. fields: query (Gmail search syntax, e.g. 'from:boss@company.com is:unread'), max_results (optional)\n- read_email: read full content of an email. field: email_id (from search_emails). Also returns thread_id for replies.\n- reply_email: reply to a thread. fields: thread_id (from read_email), to, subject, body\n\nFor reading emails: search_emails first to get IDs, then read_email for content.\nALWAYS use this tool when the user asks about email \u2014 never make up email content.",
        "workflowId": {
          "__rl": true,
          "value": "moss-gmail-001",
          "mode": "id"
        },
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {},
          "matchingColumns": [],
          "schema": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2.1,
      "position": [
        1000,
        300
      ],
      "id": "node-gmail-tool",
      "name": "gmail"
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "load profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "update profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeepSeek Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "load profile": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "update profile": {
      "main": [
        [
          {
            "node": "Send Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "todoist": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "google calendar": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "google_drive": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "gmail": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  }
}

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

Moss - Telegram Assistant. Uses telegramTrigger, agent, telegram, lmChatDeepSeek. Event-driven trigger; 11 nodes.

Source: https://github.com/sethlsx/moss/blob/bd15b4f7f5068f0e2c54318448815e98681cfc28/workflows/moss_simple.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

Agent Access Control Template. Uses memoryBufferWindow, lmChatOpenAi, telegramTrigger, airtable. Event-driven trigger; 36 nodes.

Memory Buffer Window, OpenAI Chat, Telegram Trigger +9
AI & RAG

This workflow allows granular control over the access to tools connected to AI Agents (including Multi-Agent setups) using Role Based Access Control.

Memory Buffer Window, OpenAI Chat, Telegram Trigger +9
AI & RAG

BoomerBobBot.TP. Uses agent, telegramTrigger, telegram, memoryBufferWindow. Event-driven trigger; 95 nodes.

Agent, Telegram Trigger, Telegram +10
AI & RAG

A comprehensive n8n workflow demonstrating advanced AI agent orchestration, stateful conversation management, and multi-modal input processing for nutrition tracking applications.

Telegram, Memory Buffer Window, Google Gemini Chat +6
AI & RAG

&gt; AI-powered nutrition assistant for Telegram — log meals, set goals, and get personalized daily reports with Google Sheets integration.

Telegram, Google Gemini, Google Gemini Chat +7