Skip to content

feat(discord): opt-in toolsets + ID injection + split + feishu wiring (salvage #15457, #15458) - #15610

Merged
teknium1 merged 5 commits into
mainfrom
hermes/hermes-b2a07e89
Apr 25, 2026
Merged

feat(discord): opt-in toolsets + ID injection + split + feishu wiring (salvage #15457, #15458)#15610
teknium1 merged 5 commits into
mainfrom
hermes/hermes-b2a07e89

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Discord server tools are now user-toggleable (default OFF) and scoped to the Discord platform only. Salvage of #15457 + #15458 with a follow-up that stops the discord toolset from auto-bloating every Discord install with 19 tools.

Credits to @alt-glitch — commits preserved via rebase-merge.

Changes

From #15457 (@alt-glitch):

  • Recover non-configurable toolsets from composite resolution (fixes discord/feishu_doc/feishu_drive being silently dropped when user saves via hermes tools)
  • Split monolithic discord_server into discord (fetch_messages, search_members, create_thread) and discord_admin (list channels/roles, pin, assign roles)
  • Wire feishu_doc/feishu_drive into the hermes-feishu composite

From #15458 (@alt-glitch):

  • Add guild_id, parent_chat_id, message_id to SessionSource; populate from Discord adapter
  • Fix stale "no Discord APIs" disclaimer that was lying when tools were loaded
  • Inject a Discord IDs block in the session context when the discord tool is available

Follow-up (us):

  • discord added to CONFIGURABLE_TOOLSETS + _DEFAULT_OFF_TOOLSETS alongside discord_admin — both opt-in via hermes tools
  • New _TOOLSET_PLATFORM_RESTRICTIONS sidecar map: platform-scoped toolsets only appear in their platform's checklist and are stripped everywhere else
    • Applied at four gates: checklist render, _get_platform_tools resolution (both branches), _save_platform_tools, and tools_disable_enable_command
  • Session-prompt gate rewritten: IDs block requires BOTH discord/discord_admin enabled AND DISCORD_BOT_TOKEN set (toolset alone isn't enough — tool's check_fn gates on token at registry time)

Validation

Truth table (token × toolset-enabled, E2E against real imports with isolated HERMES_HOME):

toolset OFF toolset ON
no token disclaimer disclaimer
token set disclaimer IDs block

Platform scoping (E2E):

  • First-time Discord install: discord and discord_admin both OFF
  • First-time Telegram/CLI/Slack: neither appears in checklist or resolution
  • Hand-edited config putting discord on Telegram: stripped at save time
  • hermes tools enable discord -p telegram: rejected with clear error

Test suite: tests/hermes_cli/ tests/gateway/test_session.py tests/test_toolsets.py tests/tools/test_discord_tool.py — 2976 passed, 2 pre-existing failures on main unrelated to this PR (custom_provider_model_switch signature change, test_web_server single-field-category check).

Closes #15457
Closes #15458

@teknium1
teknium1 force-pushed the hermes/hermes-b2a07e89 branch from d80c5e6 to 7c776ab Compare April 25, 2026 11:50
alt-glitch and others added 5 commits April 25, 2026 04:50
Groundwork for injecting raw platform identifiers into the agent's
system prompt.  Currently only `thread_id` is exposed as a raw ID —
callers in a Discord thread had to guess `channel_id == thread_id`
(which happens to work because threads are channels in Discord's REST
API) and had no way to reference the parent channel, guild, or the
triggering message.

Adds three optional fields:

- `guild_id` — Discord guild / Slack workspace / Matrix server scope
- `parent_chat_id` — parent channel when chat_id refers to a thread
- `message_id` — ID of the triggering message (pin/reply/react)

Extends `BasePlatformAdapter.build_source()` to accept + forward them
and teaches `to_dict`/`from_dict` to serialize them.  Behaviourally a
no-op: nothing reads the fields yet and they default to None.
…onSource

Discord knows all four identifiers for every inbound message — guild,
channel (or thread), parent channel when in a thread, and the
triggering message.  Pass them into ``SessionSource`` via the new
``build_source()`` kwargs so downstream code (context-prompt builder,
delivery, logging) can use them without re-resolving from discord.py
objects.

For auto-threaded messages, remember the original channel as the
parent before swapping ``chat_id`` to the freshly created thread.

Behavioural: still a no-op — nothing consumes these fields yet.
The Discord platform note in the session context prompt claimed the
agent has no server-management APIs — pre-dating the discord tool.
With a bot token configured the agent actually has fetch_messages,
search_members, create_thread, and optionally the discord_admin tool;
telling the model otherwise causes it to refuse or apologise for
calls it is fully able to make.

Gate the disclaimer on DISCORD_BOT_TOKEN being unset, matching the
tool's own ``check_fn``.  Without a token the note still appears and
remains accurate; with a token the model is no longer gaslit into
refusing valid tool calls.
When DISCORD_BOT_TOKEN is set — meaning the discord tool actually
loads — emit a dedicated IDs block in the session context prompt so
the agent can call ``fetch_messages``, ``pin_message``, etc. with
real identifiers instead of probing.

Currently only ``thread_id`` was exposed as a raw ID (via the
``description`` string).  The agent in a Discord thread had to guess
that the thread ID doubles as a channel ID for the REST API (it
does), and it had no way to reference the parent channel, the guild,
or the triggering message at all.

The block adapts to context:

  - Thread:     guild / parent channel / thread / message
  - Channel:    guild / channel / message
  - (DM has no guild/channel IDs worth listing; only message)

Discord isn't in _PII_SAFE_PLATFORMS, so IDs ship unredacted.
Both discord (read/participate) and discord_admin (server admin) are now
configurable via `hermes tools` with default-OFF. Previously the core
discord tool (fetch_messages, search_members, create_thread) auto-loaded
on every Discord install with DISCORD_BOT_TOKEN set — 19 tools the user
never opted into.

Adds a platform-scoping mechanism (_TOOLSET_PLATFORM_RESTRICTIONS) so
the discord toolsets only show up in the Discord platform's checklist,
not on CLI/Telegram/Slack/etc. Applied at four gates:
  - _prompt_toolset_checklist: checklist filter
  - _get_platform_tools: resolution filter (both branches)
  - _save_platform_tools: save-time filter (covers 'Configure all
    platforms' and hand-edited config.yaml)
  - tools_disable_enable_command: rejects `hermes tools enable discord`
    on non-Discord platforms with a clear error

build_session_context_prompt now injects the Discord IDs block only
when both conditions hold: the discord/discord_admin toolset is
enabled AND DISCORD_BOT_TOKEN is set. Toolset alone isn't enough —
the tool's check_fn gates on the token at registry time, so opting
in without a token yields no tools and the IDs block would lie.
Otherwise keep the stale-API disclaimer.
@teknium1
teknium1 force-pushed the hermes/hermes-b2a07e89 branch from 7c776ab to fb7b2b5 Compare April 25, 2026 11:51
@teknium1
teknium1 merged commit 6ed37e0 into main Apr 25, 2026
7 checks passed
@teknium1
teknium1 deleted the hermes/hermes-b2a07e89 branch April 25, 2026 11:51
@alt-glitch alt-glitch added type/feature New feature or request P2 Medium — degraded but workaround exists comp/tools Tool registry, model_tools, toolsets platform/discord Discord bot adapter platform/feishu Feishu / Lark adapter labels Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tools Tool registry, model_tools, toolsets P2 Medium — degraded but workaround exists platform/discord Discord bot adapter platform/feishu Feishu / Lark adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants