Skip to content

feat(gateway): dedicated alerts channel (#76780) - #76787

Open
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:feat/76780-alerts-channel
Open

feat(gateway): dedicated alerts channel (#76780)#76787
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:feat/76780-alerts-channel

Conversation

@webtecnica

Copy link
Copy Markdown
Contributor

Closes #76780

Summary

Adds a per-platform lifecycle_chat_id config key that redirects gateway lifecycle (up/down/restart) notifications to a dedicated alerts channel, separate from the conversational home channel.

Currently, "♻️ Gateway online", "♻ Gateway restarted" and the home-channel "Gateway shutting down / restarting" broadcasts are always sent to the platform's home channel, gated only by gateway_restart_notification. That forces an either/or: keep the pings in the operator's primary chat (clutter) or lose the up/down visibility entirely. This PR lets operators keep the lifecycle pings while moving them to a low-noise alerts channel — cron deliveries, reminders and normal chat stay on the home channel.

Behavior

  • When lifecycle_chat_id is set for a platform, the following go there instead of the home channel:
    • "♻️ Gateway online — Hermes is back and ready." (startup home-channel broadcast)
    • The home-channel "⚠️ Gateway shutting down / restarting" broadcast (active-session interrupt pings are unchanged — they still target the specific chat with the in-flight task)
    • "♻ Gateway restarted successfully. Your session continues." (the /restart confirmation; the reply anchor is dropped since the message moves to a different chat)
  • When unset (default), behavior is unchanged: pings go to the home channel, still toggled by gateway_restart_notification.
  • A platform with lifecycle_chat_id but no home channel still receives the lifecycle pings.
gateway:
  platforms:
    telegram:
      home_channel:
        chat_id: "123456789"               # conversational home (cron, reminders)
      lifecycle_chat_id: "-1003940233719"  # dedicated low-noise alerts channel
      gateway_restart_notification: true   # keep lifecycle pings on

No env var — pure config.yaml (repo convention). Both platforms.<name>.lifecycle_chat_id and top-level <name>.lifecycle_chat_id are supported (mirrors the gateway_restart_notification bridge routes).

Files changed

  • gateway/config.py — new PlatformConfig.lifecycle_chat_id field (+ to_dict/from_dict, incl. the extra bridge route) and shared-key bridging in load_gateway_config
  • gateway/run.py — redirect logic in _send_home_channel_startup_notifications, the shutdown home-channel broadcast, and _send_restart_notification
  • plugins/platforms/telegram/adapter.pylifecycle_chat_id added to _GENERIC_MERGE_KEYS so the plugin doesn't clobber the shared-key merge
  • tests/gateway/test_config.py — roundtrip / bridge / coercion tests
  • tests/gateway/test_restart_notification.py — redirect tests for startup, shutdown broadcast, and restart confirmation (home channel + lifecycle-only variants)
  • website/docs/user-guide/messaging/index.md + zh-Hans translation — "Dedicated alerts channel" section

Notes

  • Make sure the bot is a member of the alerts channel, or the redirected pings will fail to deliver (logged, best-effort like all lifecycle pings).
  • Active-session interrupt pings ("Your current task will be interrupted") are intentionally not redirected — they carry per-session resume hints and belong in the chat where the task runs.

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins platform/telegram Telegram bot adapter area/config Config system, migrations, profiles needs-decision Awaiting maintainer decision before any implementation sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 2, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #31046 and #76780. #76787 moves home-channel lifecycle broadcasts and restart confirmation to a dedicated target, while #31046 redirects every lifecycle notification, including active-session notices. A maintainer decision is needed on that delivery contract.

@teknium1

teknium1 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for the focused config-based approach; current main does route planned lifecycle broadcasts through the home channel (gateway/run.py:20305-20346), so the feature addresses a real gap.

Problems

  • The new bare lifecycle_chat_id cannot safely route through Relay. Current main deliberately adds persisted HomeChannel.user_id and scope_id for Relay startup delivery (gateway/run.py:20331-20336; introduced by 45a408f41a). Relay egress requires a resolvable scope or user discriminator and otherwise declines the send (gateway/relay/adapter.py:553-588). The PR drops that provenance for the dedicated target, and its new tests cover Telegram rather than Relay.
  • The member note correctly identifies an unresolved contract with feat(gateway): per-platform gateway_restart_notification_channel override #31046: this PR retains active-session interruption notices in the source chat, while feat(gateway): per-platform gateway_restart_notification_channel override #31046 redirects them. That needs a maintainer decision before settling the API.

Suggested changes

  • Model a lifecycle target with Relay routing provenance, then add Relay startup/shutdown/restart coverage for a target without inbound-cache state.
  • Add a load_gateway_config() test for both documented YAML shapes.

Automated hermes-sweeper review.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Six PRs address gateway lifecycle-notification control, but their diffs implement four distinct policies: a platform-wide toggle, suppression by channel type, a destination allowlist, and routing to a dedicated alerts target. #31046 and #76787 most directly address #76780, with different handling of active-session interruption notices.

Related pull requests

Duplicates

#20801 and #20892 are the same foundational toggle implementation, with #20892 being the merged salvage. #31046 and #76787 overlap on dedicated-target routing but are not strict duplicates: #31046 redirects active-session notices too, whereas #76787 preserves them; #52584 and #56015 are related filtering alternatives with different semantics.

Suggested consolidation

Keep #76787 open with a salvage path: preserve its focused separation of conversational home traffic from lifecycle broadcasts, then resolve the Relay provenance gap and add the requested config-loading and Relay tests before further disposition. Do not close #31046 as a duplicate while its visible keep_open review remains supported by a revised diff and the active-session routing contract is undecided; #20801 is already superseded by merged #20892, while closed #52584 and #56015 remain documented alternatives rather than candidates for reopening.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I76780(["issue #76780 (open)"])
    P76787["PR #76787 (open)"]
    P76787 -->|best fix| I76780
    class I76780 open
    class P76787 open
    class P76787 best
    class P76787 target
    click I76780 "https://github.com/NousResearch/hermes-agent/issues/76780"
    click P76787 "https://github.com/NousResearch/hermes-agent/pull/76787"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 6 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 111 kB of PR diffs, 23 kB of issue/PR text, 22 kB of discussion (7 comments), 6 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Dedicated alerts channel for gateway lifecycle (up/down) notifications, separate from home channel

4 participants