Skip to content

feat(plugins): let plugins register Telegram PTB handlers (ctx.register_telegram_handler) - #59159

Closed
teknium1 wants to merge 1 commit into
mainfrom
feat/telegram-plugin-handlers
Closed

feat(plugins): let plugins register Telegram PTB handlers (ctx.register_telegram_handler)#59159
teknium1 wants to merge 1 commit into
mainfrom
feat/telegram-plugin-handlers

Conversation

@teknium1

@teknium1 teknium1 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Plugins can now attach their own python-telegram-bot handlers to the running Telegram adapter via ctx.register_telegram_handler(factory) — the Telegram counterpart of the existing register_slack_action_handler surface.

This unblocks standalone plugins that need PTB update types the core adapter doesn't route (Telegram Business API secretary bots, custom inline-button callback prefixes, chat-member events) without touching core files. It is the enabling hook for shipping Telegram Business Mode (#30055 and its duplicate cluster #26654 / #35342 / #46728) as a standalone plugin instead of 2,000+ LOC in the core adapter.

How it works

  • Plugins queue a factory at register() time; the manager stores (factory, plugin_name).
  • At connect() time, right after the PTB Application is built and before the core handlers register, TelegramAdapter._wire_plugin_handlers() invokes each factory with (application, adapter).
  • PTB dispatches only the first matching handler per group, so a pattern-scoped plugin handler (e.g. CallbackQueryHandler(..., pattern=r"^bd:")) takes precedence for its own updates while everything else falls through to the core handlers unchanged.
  • Each factory is isolated: a raising plugin logs an error and Telegram still connects.
  • Factories may import telegram/telegram.ext lazily inside the factory body, so plugin register() works when PTB isn't installed.
  • discover_and_load(force=True) clears queued factories like every other plugin registration.

Changes

  • hermes_cli/plugins.py: PluginContext.register_telegram_handler(), manager-side queue + get_telegram_handler_factories() accessor, force-rediscovery clear.
  • plugins/platforms/telegram/adapter.py: _wire_plugin_handlers() invoked in connect() before core handler registration.
  • tests/gateway/test_telegram_plugin_handlers.py (new): 9 tests — validation, queuing, accessor copy semantics, multi-plugin ordering, force-clear, factory invocation args, fault isolation, manager-load failure.
  • website/docs/guides/build-a-hermes-plugin.md: "Register Telegram (PTB) handlers" section alongside the Slack one.

Validation

tests/gateway/test_telegram_plugin_handlers.py 9 / 9 passed
tests/hermes_cli/test_plugins.py + Slack action handlers + Telegram approval buttons + thread fallback 191 / 191 passed
ruff clean

Infographic

telegram-plugin-handlers

…ister_telegram_handler

Mirrors the Slack precedent (register_slack_action_handler): plugins queue
a factory at register() time; the Telegram adapter invokes each factory
with (application, adapter) at connect() time, before the core handlers
register, so pattern-scoped plugin handlers take precedence for their own
updates while everything else falls through unchanged. Factories are
isolated — a raising plugin cannot prevent Telegram from connecting.

Unblocks standalone plugins that need PTB update types the core adapter
doesn't route (Telegram Business API secretary bots, custom callback
prefixes, chat-member events) without touching core files.

@GottZ GottZ 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.

This was generated by AI during triage.

Summary

Two open PRs address the same missing Telegram plugin-extension surface by adding a lazy (application, adapter) handler-factory API and wiring factories before core PTB handlers. #59159 also adds public plugin-author documentation, while #61576 carries the consolidated API with broader registration-order, validation, and failure-isolation tests.

Related pull requests

  • #59159 related — (+326/-1) — duplicate with useful documentation: adds register_telegram_handler(factory), connect-time pre-core wiring, per-factory isolation, tests, and the plugin-guide section; its implementation now substantially matches #61576.
  • #61576 duplicate — (+341/-0) — preferred consolidation path: after the keep_open review on #61576 identified the incompatible PTB handle validation and competing API shape, the diff adopts #59159's lazy factory contract, eliminating that validator issue and adding broader ordering, copy-accessor, invalid-input, manager-failure, and per-factory-isolation coverage.

Duplicates

#59159 and #61576 now implement essentially the same ctx.register_telegram_handler(factory) API and connect-time Telegram adapter wiring; #59159 additionally contains the public plugin-guide documentation.

Suggested consolidation

Merge #61576 after carrying over #59159's plugin-guide documentation (with the corrected application.bot guidance), then close #59159 as superseded by #61576. This follows rather than overrides the keep_open review on #61576: its blocking PTB-contract concern is removed in the current diff by replacing handler duck-typing with the shared lazy factory API.

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
    subgraph Dup59159 ["PRs duplicating each other"]
        P59159["PR #59159 (open)"]
        P61576["PR #61576 (open)"]
    end
    class P59159 open
    class P61576 open
    class P59159 target
    click P59159 "https://github.com/NousResearch/hermes-agent/pull/59159"
    click P61576 "https://github.com/NousResearch/hermes-agent/pull/61576"
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 or no verify verdict yet (state tag in the node label).

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

paoloantinori added a commit to paoloantinori/hermes-agent that referenced this pull request Aug 16, 2026
… shape

Rebases the plugin API onto NousResearch#59159's factory shape per review feedback
("Consolidate with NousResearch#59159's chosen API shape"):

- register_telegram_handler(factory): the adapter invokes each factory with
  (application, adapter) at connect time, right after the PTB Application is
  built and BEFORE the core handlers are added — so pattern-scoped plugin
  handlers take precedence while everything else falls through to core.
  Plugins construct their own PTB handlers inside the factory, so the
  check_update/handle_update duck-type validation and the group param are
  gone; PTB's own contract applies at add_handler.
- PluginManager: _telegram_handler_factories / get_telegram_handler_factories
  (was the (handler, group, plugin_name) tuple queue).
- TelegramAdapter._wire_plugin_handlers: invokes factory(self._app, self);
  load-failure and per-factory exceptions isolated so one bad plugin can't
  break connect. NousResearch#59159 can now close as superseded.

Tests rewritten for the factory shape: queuing/validation, the connect-path
wiring (factories invoked with (app, adapter)), and isolation (load failure +
a raising factory don't block others).

Also fixes a doc bug carried over from NousResearch#59159: the Notes bullet advertised an
adapter.bot attribute that doesn't exist (only self._bot); corrected to point
plugin authors at application.bot (PTB).

Ran code-review (high) + simplify before pushing.
@teknium1

Copy link
Copy Markdown
Contributor Author

Subsumed by #59217 (merged, 34393c3) — its commit is included there; register_telegram_handler survives as a back-compat alias over the telegram bucket of ctx.register_platform_handler.

@teknium1 teknium1 closed this Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/telegram Telegram bot adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants