Agent MessengerAgent Messenger
TypeScript SDK

Telegram Bot

TypeScript SDK reference for Telegram Bot — client, real-time long-polling listener, credential management, and types.

Installation

npm install agent-messenger
import {
  TelegramBotClient,
  TelegramBotCredentialManager,
  TelegramBotError,
  TelegramBotListener,
} from 'agent-messenger/telegrambot'

TelegramBotClient

The main client wrapping Telegram's HTTP Bot API. Includes automatic 429 (rate-limit) handling using retry_after, network retries with exponential backoff, and structured errors via TelegramBotError.

const client = await new TelegramBotClient().login({ token: 'YOUR_BOT_TOKEN' })

Or use stored credentials — read from ~/.config/agent-messenger/telegrambot-credentials.json (managed by agent-telegrambot auth set):

const client = await new TelegramBotClient().login()

Authentication

const me = await client.getMe()
// → TelegramBotUser { id, is_bot, first_name, username?, ... }

Messages

// Send text message
const msg = await client.sendMessage(chatId, 'Hello', {
  parse_mode: 'HTML',
  reply_to_message_id: 42,
  disable_notification: true,
})

// Edit a chat message
await client.editMessageText({ chat_id: chatId, message_id: msg.message_id }, 'Edited text')

// Edit an inline-mode message (returned by inline query results)
await client.editMessageText({ inline_message_id: 'abc123' }, 'Edited text')

// Delete
await client.deleteMessage(chatId, msg.message_id)

// Forward
await client.forwardMessage(toChatId, fromChatId, messageId)

// Upload document (multipart)
await client.sendDocument(chatId, '/path/to/file.pdf', { caption: 'Report' })

Chats

// Full chat info (title, description, member count, etc.)
const chat = await client.getChat(chatId)

// Single member's status
const member = await client.getChatMember(chatId, userId)

// Member count for groups, supergroups, channels
const count = await client.getChatMemberCount(chatId)

Reactions

// Set a reaction (Telegram replaces previous bot reaction)
await client.setMessageReaction(chatId, messageId, [{ type: 'emoji', emoji: '👍' }])

// Clear all bot reactions
await client.setMessageReaction(chatId, messageId, [])

Updates (Manual Polling)

If you don't need the listener abstraction, you can call getUpdates directly:

const updates = await client.getUpdates({
  offset: 0,
  limit: 100,
  timeout: 30,
  allowed_updates: ['message', 'callback_query'],
})

TelegramBotListener

A long-polling listener for real-time updates. Telegram Bot API does not support WebSockets — long-polling is the canonical streaming mode used by frameworks like grammy and telegraf. No public HTTPS endpoint required.

import { TelegramBotClient, TelegramBotListener } from 'agent-messenger/telegrambot'

const client = await new TelegramBotClient().login({ token: 'YOUR_BOT_TOKEN' })
const listener = new TelegramBotListener(client, {
  timeoutSeconds: 30,
  limit: 100,
  allowedUpdates: ['message', 'callback_query'],
  dropPendingUpdates: false,
})

listener.on('connected', ({ user }) => {
  console.log(`Connected as @${user.username}`)
})

listener.on('message', (message) => {
  console.log(`${message.chat.id}: ${message.text}`)
})

listener.on('callback_query', (query) => {
  console.log(`Button clicked: ${query.data}`)
})

listener.on('disconnected', () => {
  console.log('Disconnected, will retry…')
})

listener.on('error', (error) => {
  console.error('Fatal error:', error)
})

await listener.start()

Lifecycle

  • start() — Removes any active webhook (mutex with polling), calls getMe to confirm auth, then enters the polling loop.
  • stop() — Aborts the in-flight getUpdates request and stops the loop. Safe to call multiple times.

Events

EventPayloadNotes
connected{ user: TelegramBotUser }Once after start() succeeds
disconnected[]After a recoverable error; listener will retry with exponential backoff
error[Error]Fatal error (Unauthorized 401, Conflict 409). Listener stops.
message[TelegramMessage]New text/media messages in private chats and groups
edited_message[TelegramMessage]Message edited
channel_post[TelegramMessage]New post in a channel where the bot is admin
edited_channel_post[TelegramMessage]Channel post edited
callback_query[TelegramCallbackQuery]Inline keyboard button pressed
inline_query[TelegramInlineQuery]Inline-mode query (@yourbot ...)
my_chat_member[TelegramChatMemberUpdated]Bot's own membership status changed
chat_member[TelegramChatMemberUpdated]Other member's status changed (requires opt-in)
telegram_update[TelegramUpdate]Catch-all — every raw update

Reconnection

On recoverable errors (network failure, 5xx, transient API errors), the listener emits disconnected and retries with exponential backoff capped at 30 seconds. On Unauthorized (401) or Conflict (409 — another polling instance is running), it emits error and stops; restart your process after fixing the cause.

TelegramBotCredentialManager

const manager = new TelegramBotCredentialManager()

// Store credentials
await manager.setCredentials({ token, bot_id, bot_name })

// Retrieve current
const creds = await manager.getCredentials()

// Multi-bot support
const all = await manager.listAll()
await manager.setCurrent('deploy')
await manager.removeBot('alert')
await manager.clearCredentials()

Credentials are stored under ~/.config/agent-messenger/telegrambot-credentials.json with 0600 file permissions. Override the directory with the AGENT_MESSENGER_CONFIG_DIR environment variable, or pass new TelegramBotCredentialManager(customDir).

Error Handling

All client methods throw TelegramBotError with a code property:

CodeMeaning
missing_tokenEmpty token passed to login
not_authenticatedUsed a method before .login()
no_credentialsNo stored credentials and none provided
unauthorized401 — invalid token
conflict409 — another polling instance running
forbidden403 — bot kicked or user hasn't started the bot
bad_request400 — usually invalid chat ID or message ID
not_found404
rate_limited429 (after retries exhausted)
network_errorFetch failed after retries
invalid_responseTelegram returned non-JSON
import { TelegramBotError } from 'agent-messenger/telegrambot'

try {
  await client.sendMessage(chatId, 'Hello')
} catch (error) {
  if (error instanceof TelegramBotError && error.code === 'forbidden') {
    console.log('User has not started the bot yet')
  }
}

On this page