feat(telegram): support multiple bot accounts per gateway - #2203
Conversation
25a7235 to
4abb0e5
Compare
GPT 5.6 Review — ✅ human override acceptedHuman judgment by @chenmingwei23 overrides the GPT 5.6 finding for This comment is updated in place on each push. The model was not re-run because an authorized human decision supersedes it. False positive or not applicable? A repository writer can comment: |
Design Review (Fable 5) — 🟡 CONCERNSAdvisory design-level review of Design-Verdict: CONCERNS Named accounts ship half-integrated: an unregistered persisted session-key shape, silent per-account failures, and feature gaps all keyed on a magic Watch
Suggestions
[DESIGN-REVIEWED] 381d53b |
4abb0e5 to
773a614
Compare
|
/ai-review override gpt 773a614: accounts.bot_token has identical security posture as the existing telegram.bot_token field (also in config.json with the same sensitive=True metadata). The field exists for convenience alongside the recommended .env path, matching the established pattern. |
773a614 to
7aa8c03
Compare
|
AI-review override not recorded: |
Add telegram.accounts config map enabling a single gateway process to
serve multiple Telegram bots simultaneously. Each named account has its
own bot_token, allowed_user_ids, and forum settings. Messages on each
account are routed to a bound agent (via the new telegram_account field
on KiroCrewAgentConfig), with session keys naturally isolated by
incorporating the account ID into the channel namespace.
Backward compatible: when telegram.accounts is absent, the existing
single-token config is auto-wrapped as a 'default' account with no
behavioral change. The accounts config pattern is channel-agnostic by
design and can be extended to Discord, Slack, and other channels in
future PRs.
Config schema:
telegram.accounts.{name}.bot_token
telegram.accounts.{name}.allowed_user_ids
telegram.accounts.{name}.allow_forum
telegram.accounts.{name}.allowed_forum_chat_ids
agents.{name}.telegram_account (binds agent to account)
7aa8c03 to
381d53b
Compare
|
/ai-review override gpt 381d53b: The field carries sensitive=True metadata (line 3840), which is the same mechanism the existing telegram.bot_token uses for masking in the /api/config response. Dynamic-path masking for nested fields is a config-API concern orthogonal to this PR. |
Human judgment recorded@chenmingwei23 marked the gpt AI finding as false positive, not applicable, or explicitly accepted for
This decision applies only to this commit. A new push requires a new judgment. |
Opus 5 Review — ✅ no blocking findingsReviewed Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
iamwhatever
left a comment
There was a problem hiding this comment.
This one definitely require additional control configured, specifically governance management. Please check the way to turn this one off with simple config as the enterprise may not want this thing for security reason.
) The 0.2.0 section was written in #2305, the commit that became v0.2.0-rc.4. Seventy-one commits have landed on main since, nineteen of them feat:, and the section was never revisited. It therefore both omitted shipped features and described one that no longer exists as written. The wrong entry mattered most: the Webhooks bullet told the reader to manage inbound automation "from Settings", but #2343 moved that page behind a per-device Preview pages toggle under Developer and hides it by default. A 0.2.0 user following the release notes would have gone looking for a page that is not there. Added, all from the rc.6 range: opt-in Slack setup and the multi-channel repositioning (#2340), Telegram multi-account (#2203) and inbound attachments (#2201), sub-agent completions reaching non-Slack parents (#2352), Discord reply continuation (#2326), Slack OPTIONS as a control (#1467), the Agent Templates two-pane inspector, project-local agent discovery (#2167), send-a-copy-to-another-instance, Jira and setting link chips (#2019, #1907), CJK emphasis rendering, the MCP Apps switch (#2293, #2337), the Connections provider registry (#2285), GitHub Enterprise Server support in Code Review Sage (#2154), operator notes on user deny patterns (#2341), the locked git-publish floor rules (#2369), the persist-or-refuse boot guard (#2279), and the turn-ceiling bounds on the approval and stall windows (#2372, #2373). Scope is exactly 5fe4bd5..ab20b4e, the range v0.2.0-rc.6 ships. The three commits main carries beyond rc.6, including meeting deletion (#2268), belong to the next release and are deliberately not described here.
…#2203) Add telegram.accounts config map enabling a single gateway process to serve multiple Telegram bots simultaneously. Each named account has its own bot_token, allowed_user_ids, and forum settings. Messages on each account are routed to a bound agent (via the new telegram_account field on KiroCrewAgentConfig), with session keys naturally isolated by incorporating the account ID into the channel namespace. Backward compatible: when telegram.accounts is absent, the existing single-token config is auto-wrapped as a 'default' account with no behavioral change. The accounts config pattern is channel-agnostic by design and can be extended to Discord, Slack, and other channels in future PRs. Config schema: telegram.accounts.{name}.bot_token telegram.accounts.{name}.allowed_user_ids telegram.accounts.{name}.allow_forum telegram.accounts.{name}.allowed_forum_chat_ids agents.{name}.telegram_account (binds agent to account)
…rodotdev#2412) The 0.2.0 section was written in kirodotdev#2305, the commit that became v0.2.0-rc.4. Seventy-one commits have landed on main since, nineteen of them feat:, and the section was never revisited. It therefore both omitted shipped features and described one that no longer exists as written. The wrong entry mattered most: the Webhooks bullet told the reader to manage inbound automation "from Settings", but kirodotdev#2343 moved that page behind a per-device Preview pages toggle under Developer and hides it by default. A 0.2.0 user following the release notes would have gone looking for a page that is not there. Added, all from the rc.6 range: opt-in Slack setup and the multi-channel repositioning (kirodotdev#2340), Telegram multi-account (kirodotdev#2203) and inbound attachments (kirodotdev#2201), sub-agent completions reaching non-Slack parents (kirodotdev#2352), Discord reply continuation (kirodotdev#2326), Slack OPTIONS as a control (kirodotdev#1467), the Agent Templates two-pane inspector, project-local agent discovery (kirodotdev#2167), send-a-copy-to-another-instance, Jira and setting link chips (kirodotdev#2019, kirodotdev#1907), CJK emphasis rendering, the MCP Apps switch (kirodotdev#2293, kirodotdev#2337), the Connections provider registry (kirodotdev#2285), GitHub Enterprise Server support in Code Review Sage (kirodotdev#2154), operator notes on user deny patterns (kirodotdev#2341), the locked git-publish floor rules (kirodotdev#2369), the persist-or-refuse boot guard (kirodotdev#2279), and the turn-ceiling bounds on the approval and stall windows (kirodotdev#2372, kirodotdev#2373). Scope is exactly 5fe4bd5..ab20b4e, the range v0.2.0-rc.6 ships. The three commits main carries beyond rc.6, including meeting deletion (kirodotdev#2268), belong to the next release and are deliberately not described here.
What is the problem?
Users who want to run specialized bots (e.g. different personas, topic-focused assistants, or access-scoped bots) currently need separate gateway processes per bot. Each process has its own memory footprint (~200MB), its own config directory, and its own lifecycle management. This is operationally heavy for what is conceptually a single agent platform serving multiple front-ends.
Why this issue matters
A single gateway process already multiplexes Slack, Discord, Webex, and other channels. Telegram is the only channel locked to a 1:1 token:gateway ratio. Power users who want to expose different capabilities via different bot handles (e.g. a general assistant, a finance bot, and a domain-specific bot) are forced into N independent processes with duplicated config, duplicated memory, and no shared session management.
How the fix solves it
Adds
telegram.accounts— a named map of bot accounts, each with its ownbot_token,allowed_user_ids, and forum settings. One gateway starts one polling loop per account. Sessions are naturally isolated: named accounts usetelegram:{account_id}as the channel namespace in the session key, while thedefaultaccount keeps the baretelegramprefix for backward compatibility.Agent routing: a new
telegram_accountfield on the agent config binds an agent to a specific account. Messages on that bot route to the bound agent (workspace, memory store, model). Unbound accounts route to the default agent.Backward compatible: when
telegram.accountsis absent, the existing single-token config (telegram.bot_token) is auto-wrapped as a"default"account with zero behavioral change. Existing configs work unchanged.The
accountsconfig pattern is channel-agnostic by design and can be extended to Discord, Slack, and other channels in future PRs.Config example
{ "telegram": { "enabled": true, "accounts": { "main": { "bot_token": "...", "allowed_user_ids": [123] }, "finance": { "bot_token": "...", "allowed_user_ids": [123, 456] } } }, "agents": { "default": { "kiro_agent": "kirocrew", "workspace": "default", "telegram_account": "main" }, "finance": { "kiro_agent": "kirocrew", "workspace": "finance", "telegram_account": "finance" } } }What tests we did
resolved_accounts()correctly synthesizes the legacy pathOther suggestions
accountspattern to Discord (discord.accounts) and other channels with minimal effort — the session key builder already accepts arbitrary channel names.