Skip to content

Telegram connection

Send messages to a Telegram chat or channel from a task over a managed Leoflow Connection. TelegramHook posts to the Bot API using a bot token.

URI shape

telegram://:<bot_token>@

There is no host โ€” the token (token-only shape, like Slack) lives in Password and is percent-escaped. The chat/channel id is supplied per message by the operator, or carried in Extra.

Fields the UI asks for

Field Required Notes
Conn Id yes e.g. telegram_default. Exported as AIRFLOW_CONN_TELEGRAM_DEFAULT.
Conn Type yes telegram.
Password yes The bot token from @BotFather, e.g. 1234567:AAH.... Encrypted at rest (ADR 0019).
Host no Leave blank.
Extra optional JSON: {"chat_id":"-1001234567890"} to pin a default chat.

Example DAG

from airflow.sdk import dag, task


@dag(schedule=None, catchup=False, tags=["telegram"])
def telegram_notify():
    @task
    def send():
        from airflow.providers.telegram.hooks.telegram import TelegramHook

        hook = TelegramHook(telegram_conn_id="telegram_default")
        hook.send_message({"chat_id": "-1001234567890", "text": "DAG finished"})

    send()


telegram_notify()
# leoflow.yaml
dag_id: telegram_notify
runtime: python3.12
requirements:
  - apache-airflow-providers-telegram
connections:
  - conn_id: telegram_default
    conn_type: telegram

Security notes

  • Treat the bot token like a password: anyone with it can post as the bot. Revoke and re-issue via @BotFather if leaked.
  • Restrict the bot: add it only to the chats it must post to; disable group privacy only if the bot must read messages.
  • Never log AIRFLOW_CONN_TELEGRAM_DEFAULT; it carries the token.
  • ADR 0019 โ€” secret encryption at rest.
  • ADR 0021 โ€” agent secret delivery (AIRFLOW_CONN_<CONN_ID>).
  • TestTelegramConnectionURIShapeIntegration โ€” chain-of-custody delivery test.
  • Slack connection โ€” the same token-in-password shape.