Skip to content

feat(discord): fetch thread history when bot is first mentioned mid-thread - #6712

Closed
AgentWrapper wants to merge 1 commit into
NousResearch:mainfrom
AgentWrapper:feat/discord-thread-context
Closed

feat(discord): fetch thread history when bot is first mentioned mid-thread#6712
AgentWrapper wants to merge 1 commit into
NousResearch:mainfrom
AgentWrapper:feat/discord-thread-context

Conversation

@AgentWrapper

Copy link
Copy Markdown

Summary

When the Hermes bot is @mentioned in an existing Discord thread for the first time, it currently starts a blank session with no awareness of the thread's prior conversation. This PR ports the Slack adapter's _fetch_thread_context() pattern to Discord, so the agent receives the thread history as context on first mention.

Closes #6708

Changes

Three additions to gateway/platforms/discord.py:

  1. _has_active_session_for_thread() — checks the session store via build_session_key() to determine if a session already exists for this thread. Respects thread_sessions_per_user and group_sessions_per_user config settings. Mirrors the Slack adapter's implementation from feat(gateway): approval buttons for Slack & Telegram + Slack thread context #5890.

  2. _fetch_thread_context() — fetches up to 30 prior messages from the Discord thread via channel.history(oldest_first=True), formats them as:

    [Thread context — previous messages in this thread:]
    User1: message text
    User2: message text
    [End of thread context]
    

    Skips the bot's own messages and the current trigger message. Strips bot @mentions from context messages.

  3. Injection in _handle_message() — when the message is in an existing thread (not auto-created), and there's no prior session for it, calls _fetch_thread_context() and prepends the result to event_text. Follow-up messages use the normal session transcript.

Design decisions

  • Only fires for existing threads, not auto-created ones — when auto_thread creates a brand-new thread, there's no history to fetch, so we skip the API call.
  • Uses build_session_key() as single source of truth — avoids the manual key construction bug that was fixed in the Slack adapter (fix/slack-thread-session-key-mismatch  #5833), where thread_sessions_per_user was ignored.
  • Matches Slack formatting exactly — same [Thread context] ... [End of thread context] envelope so the agent prompt is consistent across platforms.
  • Limit of 30 messages — same as Slack, keeps the context injection bounded.

Testing

  • All 154 existing Discord tests pass
  • Syntax verification passes
  • No changes to existing lines (113 insertions, 0 modifications)

…hread

Ports the Slack adapter's _fetch_thread_context() pattern to Discord.
When the bot is @mentioned in an existing thread for the first time
(no prior session), fetches up to 30 prior messages via
channel.history() and injects them as context before the user's
message. Follow-up messages use the normal session transcript.

- Add _has_active_session_for_thread() using build_session_key()
- Add _fetch_thread_context() using discord.Thread.history()
- Inject context in _handle_message() only for existing threads
  with no prior session (skips auto-created threads)

Closes NousResearch#6708
@Tranquil-Flow

Copy link
Copy Markdown
Contributor

Heads up — I've opened #7466 which takes a similar approach but generalizes it into a base class hook (BasePlatformAdapter.fetch_thread_context()). The Discord override in that PR follows the same pattern as your implementation here (using channel.history(), skipping bot messages, stripping mentions, same 30-message limit).

The motivation was to avoid each platform adapter reimplementing the same session-check + context-fetch + prepend pattern independently. The base class also handles command safety (skipping /reset etc.) and session expiry checks.

Happy to coordinate if you'd prefer a different approach or want to merge aspects of both.

@alt-glitch alt-glitch added type/feature New feature or request P2 Medium — degraded but workaround exists platform/discord Discord bot adapter comp/gateway Gateway runner, session dispatch, delivery labels Apr 29, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #7466 (unified thread context hook in BasePlatformAdapter) which addresses the same issue #6708 with a more general approach.

Tranquil-Flow added a commit to Tranquil-Flow/hermes-agent that referenced this pull request May 25, 2026
Add fetch_thread_context() and has_active_session_for_event() to
BasePlatformAdapter, providing a single extension point for platform
adapters to fetch thread/conversation history when the bot first
enters an existing thread.

- Refactors Slack's existing thread context fetching into the new hook
- Adds Discord implementation using channel.history(), giving Discord
  feature parity with Slack for thread context
- Session liveness check evaluates reset policy (idle/daily expiry) so
  expired sessions still get context seeded and don't auto-trigger
  without @mention
- Commands (/reset, /status, etc.) are not prefixed with context
- Base default returns None so unimplemented platforms are unaffected

Fixes NousResearch#6708
Related to NousResearch#6712 (absorbs Discord thread context into unified pattern)
Related to NousResearch#1953, NousResearch#2950, NousResearch#5816 (Slack fixes refactored into base hook)
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused Discord implementation. This is an automated hermes-sweeper review; current main already provides the requested behavior.

  • e84fe483bc958ef2ce11463d10ee57bdc2ccc5fb added Discord channel-history backfill and is an ancestor of current main.
  • plugins/platforms/discord/adapter.py:6532 calls _fetch_channel_context() for existing threads and skips only newly auto-created threads.
  • plugins/platforms/discord/adapter.py:4995 fetches bounded pre-trigger history and formats it as agent context; tests/gateway/test_discord_free_response.py:1358 covers thread backfill dispatch.
  • The adapter has since moved from this PR's gateway/platforms/discord.py target to plugins/platforms/discord/adapter.py.

The related discussion of #7466 was considered; this close is based on the independently verified behavior already present on current main.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added sweeper:implemented-on-main Sweeper: behavior already present on current main sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state 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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
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 P2 Medium — degraded but workaround exists platform/discord Discord bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:implemented-on-main Sweeper: behavior already present on current main 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-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord: bot has no thread context when first mentioned in an existing thread

4 participants