opensre (no subcommand). Slash commands below are run from that REPL.
Prerequisites
- A Telegram account.
- The Telegram mobile or desktop app, signed in.
- The chat (group, channel, or direct message) where you want to receive findings.
Step 1: Create a bot with BotFather
BotFather is Telegram’s official bot for creating other bots.- Open Telegram and search for
@BotFather. Open the chat and tap Start. - Send
/newbot. - When prompted, send a display name for your bot (e.g.
OpenSRE Alerts). - Send a username that ends in
bot(e.g.opensre_alerts_bot). It must be globally unique. - BotFather replies with an HTTP API token of the form
<numeric-id>:<token-secret>. Copy it — it is your bot token. Treat it like a password. Anyone holding it can send messages as your bot.
Step 2: Add the bot to a chat
The bot can deliver to three kinds of destinations. Pick the one that fits your team:- Group chat
- Channel
- Direct message
- Open the group where you want findings to land.
- Tap the group name → Add members → search for your bot username → Add.
- By default, bots in groups only see messages addressed to them, which is fine for delivery-only.
Step 3: Find your chat_id
The chat ID identifies where the bot should post.
-
Send any message in the destination chat — for a channel, post anything; for a DM, send
/startto your bot. -
In a browser, open:
(replace
<YOUR_BOT_TOKEN>with the token from Step 1) -
In the JSON response, look for a
chat.idfield. The value depends on the chat type:Copy the entire value, including the leading minus sign for groups and channels.Chat type Format Example Direct message with a user Positive integer 123456789Group Negative integer -987654321Large group or channel Negative integer starting with -100-1001234567890
If
getUpdates returns an empty array, post a fresh message in the chat and reload — Telegram only buffers recent updates.Step 4: Configure the integration
Option A: Onboarding wizard (recommended)
Interactive shell:- Bot token — stored in the system keyring (not plain
.env) - Default chat ID — written to
.envasTELEGRAM_DEFAULT_CHAT_ID
~/.opensre/integrations.json via upsert_integration("telegram", ...).
Non-interactive setup:
Interactive shell:
Option B: Environment variables
Set in.env (bot token can also live in the keyring after wizard setup):
| Variable | Description |
|---|---|
TELEGRAM_BOT_TOKEN | Bot HTTP API token from BotFather. Required. |
TELEGRAM_DEFAULT_CHAT_ID | Default delivery destination. Required for delivery to work. |
Credential resolution. Every Telegram delivery surface — investigations, the
scheduler,
/watchdog, /hermes watch, and /watch — resolves the bot token
in the same order: integration store → TELEGRAM_BOT_TOKEN env → system keyring;
and the chat id as --chat-id → store default_chat_id →
TELEGRAM_DEFAULT_CHAT_ID env. Either setup option above works for all of them.Step 5: Verify
Interactive shell:getMe endpoint. On success it reports the bot @username. On failure it reports the Telegram API error message verbatim.
You can also trigger a real investigation against a bundled fixture:
Interactive shell:
Programmatic messaging: telegram_send_message tool
When the Telegram integration is configured, OpenSRE exposes a
telegram_send_message tool. The tool can send user-requested action messages,
incident notifications, or follow-up updates to the configured default chat, or
to an explicit chat_id when one is supplied. Ask in plain language from the
interactive shell (for example: “send a Telegram message to the team that DB CPU
is back below 70%”).
TELEGRAM_BOT_TOKEN, then the system keyring.
If chat_id is omitted, it sends through the configured default_chat_id, so a
user can ask OpenSRE to send a message through the configured Telegram bot
without knowing or exposing the bot token.
Delivery is an external side effect. Its result includes a stable status,
sent, error_type, chat_id, reply_to_message_id, and message_length
shape so follow-up tool calls can tell configuration failures from Telegram
delivery failures.
Two-way chat gateway (DM text)
OpenSRE can also run a Telegram messaging gateway so you can chat with the agent from your phone in a private DM. v1 supports text-only direct messages (no groups, voice, or attachments).Allow your Telegram user
Find your numeric user id with @userinfobot, then: Interactive shell:TELEGRAM_ALLOWED_USERS=123456789 in .env.
DM pairing (optional)
Same policy as other messaging platforms. Generate a code: Interactive shell:Long polling (local and production)
No public HTTPS URL required. The gateway is OpenSRE’s background agent daemon — one process that runs the Telegram chat worker, the web health app, and the cron task scheduler. It runs in the background by default:| Command | What it does |
|---|---|
opensre gateway start | Start the daemon (web, Telegram chat, task scheduler) |
opensre gateway start -f | Run attached to the terminal instead |
opensre gateway status | Show the daemon and each component’s state |
opensre gateway logs [-n N] [-f] | Print (or follow) the daemon logs |
opensre gateway stop | Stop the daemon |
~/.opensre/gateway/gateway.log.
If Telegram is not configured the daemon still runs the other components and
opensre gateway status shows telegram: not configured.
The same controls are available inside the interactive shell via /gateway:
/new to start a fresh session; /help for built-in commands.
The gateway uses the same headless agent harness as the interactive shell, with Telegram-specific wiring:
- Prompt grounding — CLI reference, AGENTS.md, integration list, and investigation flow context
- Read-only evidence tools — live integration queries (GitHub, logs, metrics, etc.) via the gather pass when integrations are configured
- Action tools —
shell_runandinvestigation_start
Deploying the gateway to a remote host
Running the gateway on a server withmake deploy (EC2) is different from local
use in one important way: the remote host cannot read your local machine’s
keychain. Guided setup stores the bot token (and your LLM API key) in the system
keyring, which is perfect locally but does not travel to the deployed instance.
So make deploy validates that the required secrets are present as plaintext
env vars in .env, and aborts if they are only in the keychain:
make deploy reports MISSING: TELEGRAM_BOT_TOKEN — API key not set or
MISSING: OPENAI_API_KEY — API key not set (or your provider’s key env) even
though local setup succeeded, this is
why — copy the values into .env (or .env.deploy.example) for the deploy. A
“missing” here means “not in the deploy env”, not “not configured”.
Scheduled and watchdog delivery
Cron (recurring reports)
Interactive shell:Watchdog (process threshold alarms)
Configure Telegram first (Steps 4–5), then: Interactive shell:Hermes incident escalation
Interactive shell:Troubleshooting
/integrations verify telegram, /verify telegram, and opensre integrations verify telegram only call Telegram’s getMe endpoint, so they surface token-validity errors but cannot detect chat-routing problems. Delivery-time errors only show up when an investigation actually posts.
Errors from verify
Missing bot_token
TELEGRAM_BOT_TOKEN is empty. Re-check .env and restart any long-running OpenSRE process so it re-reads the file.
Telegram API check failed: 401 Client Error: Unauthorized for url: …
The bot token is invalid or has been revoked. Generate a new one in BotFather (/mybots → your bot → API Token → Revoke current token) and update .env.
Errors that only surface during delivery
These are Telegram API responses that come back when OpenSRE actually tries to post a finding.verify only calls getMe, so it cannot catch them. They appear in OpenSRE logs as [telegram] post message failed: <description> with the Telegram description copied verbatim.
description: chat not found
The bot is not in the chat, or TELEGRAM_DEFAULT_CHAT_ID is wrong. Re-add the bot and re-fetch chat_id from getUpdates.
description: bot was kicked from the large group … (or similar)
Re-add the bot. For channels, the bot must be an administrator with Post Messages permission.
Findings never arrive, but verify passes
getMe only confirms the token is valid; it does not test delivery. Send a fresh message in the destination chat and re-fetch chat_id from getUpdates — your chat_id may have changed (for example, if a group was upgraded and now uses a -100 prefix).
Gateway: User <id> is not in the allowed users list
Run /messaging status -p telegram and confirm the sender’s numeric user id is listed. Re-add with /messaging allow -p telegram -u <user_id> or complete /messaging pair -p telegram pairing.
Tracer