Skip to content

feat(gateway): inbound message reactions from Telegram - #24149

Open
matrixclawx wants to merge 1 commit into
NousResearch:mainfrom
matrixclawx:feat/telegram-inbound-reactions
Open

feat(gateway): inbound message reactions from Telegram#24149
matrixclawx wants to merge 1 commit into
NousResearch:mainfrom
matrixclawx:feat/telegram-inbound-reactions

Conversation

@matrixclawx

Copy link
Copy Markdown

Summary

Adds inbound message-reaction handling to the Telegram gateway so agents can react to thumbs-up/down (or any emoji) on bot messages. Previously the adapter only sent outbound reactions; inbound MessageReactionUpdated events were being dropped because no MessageReactionHandler was registered, even though allowed_updates=Update.ALL_TYPES was already in place.

  • New ReactionEvent + ReactionHandler types in gateway/platforms/base.py.
  • MessageReactionHandler wired into the Telegram adapter — computes the add/remove diff between old and new reaction sets and emits one event per change. Channel posts (where mr.user is None) fall back to actor_chat per python-telegram-bot semantics. Handler exceptions are caught so a bad consumer can't poison the polling loop.
  • Default gateway consumer appends each reaction event to \$HERMES_HOME/reactions/inbound.jsonl so any agent toolset can tail the log and react out-of-band, without each sibling needing its own gateway patch.
  • 7 new tests in tests/gateway/ covering add/remove diff, channel actor_chat fallback, exception isolation, and JSONL serialization.
  • AGENTS.md note describing the new event flow and where consumers should hook in.

Test plan

  • python -m pytest tests/gateway/ -q passes locally
  • React with 👍 / 👎 on a bot message in a Telegram group where the bot is admin, confirm a line appears in \$HERMES_HOME/reactions/inbound.jsonl
  • React on a channel post, confirm the event carries actor_chat instead of user
  • Remove a reaction, confirm a corresponding removed event is emitted

🤖 Generated with Claude Code

Adds platform-level support for consuming user reactions on messages the
bot is in. Telegram is the only adapter wired today; Discord/Slack still
emit outbound lifecycle reactions only.

- New ReactionEvent dataclass + ReactionHandler type in gateway/platforms/base.py
- BasePlatformAdapter.set_reaction_handler() for consumers to opt in
- Telegram adapter registers MessageReactionHandler, diffs old vs new
  reaction lists, emits one ReactionEvent per added/removed emoji
- GatewayRunner default consumer appends a JSONL log at
  $HERMES_HOME/reactions/inbound.jsonl so agent tools can tail it
- Channel reactor fallback (actor_chat when mr.user is None)
- Tests cover dispatch, diff logic, no-handler drop, handler exceptions,
  and missing message_reaction shape
- AGENTS.md note documents the flow and Telegram admin requirement
@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter P3 Low — cosmetic, nice to have labels May 12, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related: #13992 (competing PR implementing the same feature behind env toggle) and #13942 (tracking issue).

This PR takes a different architectural approach — new ReactionEvent/ReactionHandler base types in base.py + JSONL file-based event log — vs #13992 which routes reactions as synthetic MessageEvents behind TELEGRAM_INBOUND_REACTIONS env var. Maintainers should decide which approach to pursue.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the inbound-reaction implementation. The current main branch needs a substantive rework before this can be salvaged.

Problems

  • The PR targets gateway/platforms/telegram.py, but that adapter was moved to plugins/platforms/telegram/adapter.py by 736ffb3bc15c56caeb27c554c7cc7f40a4232b45; the legacy path no longer exists on main.
  • gateway/platforms/telegram.py:4518 emits every Telegram reaction delta without proving the target was bot-authored or applying the normal inbound authorization/gating path. That can persist arbitrary group members' reaction activity for downstream consumers.
  • tests/gateway/test_telegram_inbound_reactions.py does not exercise the claimed actor_chat fallback or GatewayRunner JSONL serialization path.

Suggested changes

  • Rework against the bundled Telegram plugin and the current plugin handler seam (hermes_cli/plugins.py:991, added by 7c4cde9e8).
  • Correlate reactions to bot outputs and apply authorization before dispatch; add coverage for that boundary, channel actors, and the chosen consumer behavior.

Automated hermes-sweeper review.

@@ -4508,6 +4518,104 @@ def _build_message_event(
timestamp=message.date,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handler emits every reaction update but never verifies that mr.message_id is a bot-authored target or applies normal inbound authorization before the event reaches a durable consumer. Please establish both boundaries before dispatching reaction data.

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

Labels

comp/gateway Gateway runner, session dispatch, delivery 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 sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants