Messaging Gateway — Telegram Bot
Talk to your data from Telegram. The same QRY brain — workspaces, datasources, RBAC, scheduled tasks, alerts — accessible from your phone via a chat with the bot.
Production Ready — Telegram is live. WhatsApp is on the roadmap and reuses the same backend.
Overview
The Messaging Gateway exposes QRY to chat platforms without duplicating any of the platform's logic. The Telegram bot speaks to the gateway, the gateway runs the request through the same worker pipeline that powers the web UI, and the response comes back in a phone-friendly format.
Three things you can do with it:
- Notifications: in-app notifications fan out to your Telegram chat automatically (bell-toggleable per token).
- Scheduled deliveries: ask the bot to schedule a query and have the result delivered to this chat at a specific time, daily, weekly…
- Conditional alerts: tell the bot to watch a condition and only ping you when something requires attention, with a cooldown to avoid spam.
Quick start
1. Get a token
In the web UI, open Settings → Messaging Tokens and click Create token. The plaintext token (qry_msg_…) is shown once — copy it. Toggle the 🔔 bell on the token to receive notifications via Telegram.
2. Connect to the bot
Open Telegram and find your tenant's bot (your admin can share its handle, e.g. @qryai_bot). Then:
/start
/login qry_msg_xxxxxxxxxxxx
You're authenticated. The bot remembers your session and, if you have multiple chats with it, your tokens for fan-out delivery.
3. Pick a workspace and ask
/ws Sales
What were our top 10 customers last month?
The bot replies with the answer in plain text or a small chart. Done.
Personal commands
The bot is stateful per chat: workspace, datasource, model, and the active conversation are remembered between messages.
| Command | Purpose |
|---|---|
/login <token> | Authenticate with a qry_msg_* token |
/logout | Forget the session in this chat |
/whoami | Show who you are and which workspace / datasource / model are active |
/ws [name] | Pick a workspace by name (fuzzy match) or open the picker |
/ds [name] | Pick a datasource (fuzzy match) — overrides the workspace default |
/model [name] | Override the LLM model for this chat |
/new | Start a fresh conversation thread |
Workspace defaults (catalog, schema, datasource) are auto-applied when you switch with /ws — same behaviour as the web UI when you open a workspace.
Conversation commands
| Command | Purpose |
|---|---|
/share | Make the current conversation public and return a link |
/last | Send back the most recent assistant reply (handy after losing the chat scroll) |
/recent | Show the last 5 conversations as buttons; tap to resume |
/cancel | Interrupt the in-flight request (also responds to ESC if your client supports it) |
/share returns a URL pointing at your tenant's public host — the same link works in any browser.
Notifications
When the platform writes an in-app notification (job done, scheduled task completed, alert fired, etc.) the gateway can fan it out to your Telegram chats automatically.
To enable: go to Settings → Messaging Tokens and toggle the 🔔 on the tokens that should receive notifications. Multiple chats are supported — every chat that did /login with one of those tokens receives the message.
To mute: toggle the bell off on the token. Scheduled deliveries (see below) are NOT affected — those bypass the opt-in because you explicitly scheduled them.
Scheduled deliveries
Schedule a task and have its result delivered straight to the Telegram chat that asked for it.
You: Every Monday at 9am, count last week's signups
and send the result here.
The bot creates a scheduled task with output_type='telegram' and the platform routes the result to this chat. No separate setup needed — the bot already knows your chat from the active session.
One-off deliveries work the same way: "schedule a one-time task in 30 minutes…" — the platform fires it, runs the prompt, and pushes the answer to Telegram once.
If the bot fails to deliver three times in a row (revoked token, bot blocked, network outage), the task is auto-disabled. Re-enable from Scheduled Tasks in the web UI.
Conditional alerts
Conditional alerts are scheduled tasks that only deliver when a condition is met, with a cooldown to prevent spam during noisy events.
You: Watch our daily error rate and alert me here if it
goes above 1%. Cooldown 30 minutes.
How it works:
- The bot creates a recurring task tagged
is_alert=truewith the cooldown you specified. - On each tick the LLM evaluates the condition and ends its reply with
[ALERT_FIRE]or[ALERT_OK]. - The platform delivers only on
[ALERT_FIRE]AND elapsed cooldown. Quiet evaluations and cooldown-suppressed fires are silent. - The marker is stripped from the message you actually receive.
This makes it safe to run alerts every minute on noisy data — you'll only hear from the bot when something actually warrants your attention.
Tuning the cooldown: the default is 60 minutes. Set it to 0 to fire on every breach (spammy on noisy conditions); set it longer for slow-moving signals.
Workspaces and access control
Telegram requests go through the same workspace membership and RBAC checks as the web UI:
- The bot's
/wslisting only includes workspaces you're a member of. /dsonly shows datasources you have RBAC permission on.- ABAC tag-based row filtering applies to every query the bot runs on your behalf.
- A
qry_msg_*token is scoped to one user — there's no token sharing across users.
Configuration (admins)
The Telegram integration is configured entirely from the admin UI — no env vars, no Kubernetes Secrets to rotate.
System Settings → Messaging:
- Telegram enabled — master toggle. The bot supervisor reconciles every 30s, so flipping the toggle takes effect within the minute.
- Telegram bot token — from BotFather. Stored encrypted; rotating it triggers a reconnect.
- API base URL — defaults to
https://api.telegram.org; only override for self-hosted Telegram Bot API. - Default LLM model — the model used when a request doesn't specify one (typical for messaging adapters).
- Per-token rate limit — defaults to 30 messages/minute per token.
Telegram bot deployment: a single Kubernetes Deployment (replicas: 1 hardcoded — Telegram only allows one long-poller per token; strategy: Recreate avoids 409 conflicts on rollout). The pod stays up whether or not Telegram is enabled, reconciles config every 30s, and reconnects automatically on token rotation.
Limitations
- One Telegram chat is one QRY user. To switch users,
/logoutthen/loginwith a different token. - Telegram's per-message limit is 4096 chars. The bot paginates longer answers across messages, breaking on paragraph / sentence / word boundaries.
- The bot uses Markdown for emphasis (single
*bold*,_italic_,`code`). Tables, headers, and fenced code blocks are intentionally avoided — they don't render well on phones. - Charts are sent as inline images (matplotlib/seaborn). Plotly's interactive HTML doesn't display inline; if the LLM produces one anyway, you'll get a still preview only.
- File downloads work for Excel, PDF, and similar non-trivial outputs (the executor captures them when the code imports
openpyxl,reportlab, etc.). Plainpd.to_csvis silently dropped — if you need a CSV, ask for it via Excel format or withimport openpyxlfirst. /cancelinterrupts the in-flight LLM call but cannot rewind already-sent messages.
Troubleshooting
The bot doesn't reply to /login
Check that the Telegram integration is enabled in System Settings → Messaging and that the bot token is correct. The supervisor reconciles every 30s, so wait up to a minute after toggling.
"Need /login" loop after a known-good token
Token may have been revoked from the web UI. Issue a fresh one in Settings → Messaging Tokens.
Schedule says "send to Telegram" but result doesn't arrive
Verify the scheduled task in the web UI under Scheduled Tasks:
output_typeshould betelegram- the chat_id should match yours
consecutive_failuresshould be 0; if 3+ the task auto-disabled (revoked token / bot blocked)
Alert fires too often / not often enough
Adjust cooldown_minutes in the task. Set to 0 for instant repeats, or longer (60+) for slow-moving signals. The cooldown is measured from the last actual delivery, so cooldown-suppressed evaluations don't reset the clock.
/share returns a localhost URL
The tenant's public URL isn't configured. Set application.public_url in System Settings. The bot reads it directly from the system configuration table, so changes take effect immediately.
See also
- Workspaces — how membership and defaults are inherited by the bot
- Scheduled Tasks — full reference for the task model the bot drives
- RBAC and ABAC — the access controls enforced on every Telegram query
- Conversation Sharing — what
/shareproduces
WhatsApp support is on the roadmap. The same gateway and bot supervisor pattern apply, so when it ships your scheduled tasks and notification preferences carry over. Stay tuned to the release notes.