Discord Thread Dashboard — Implementation Plan#
Status: Planned (not implemented)
Last updated: 2026-05-22
Audience: Funday devs and agents maintaining Hermes on Discord
Hermes tree:~/.hermes/hermes-agent/(upstream: NousResearch/hermes-agent)
This document captures the design for a hook-driven embed dashboard in Discord: when Hermes auto-creates a thread and adds 👀 on the user’s message, a separate embed message in the thread acts as a live status panel (edited on each agent step, finalized on completion).
Related context: slash-command visibility fix (allowed_contexts / allowed_installs on discord.py 2.7+) is documented here for Funday’s install only — see § Background.
Table of Contents#
- 1. Goals
- 2. Background
- 3. Current behavior
- 4. Proposed UX
- 5. Architecture
- 6. Hook contract
- 7. Core changes (hermes-agent)
- 8. Funday hook (
~/.hermes/hooks/) - 9. Configuration
- 10.
hermes updateand persistence - 11. Implementation phases
- 12. Testing
- 13. Open decisions
1. Goals#
| Goal | Detail |
|---|---|
| Visibility | One embed in the thread shows the user’s request and live agent status (tools, step count). |
| Non-noisy | Avoid spamming the thread with many tool-progress text bubbles when the embed is enough. |
| Extensible | Layout and copy live in ~/.hermes/hooks/, not hard-coded in Funday-only patches. |
| Aligned with today | Keep 👀 on the parent-channel trigger message; dashboard lives in the thread where replies go. |
Non-goals (v1): Buttons on the dashboard, cross-platform parity (Telegram/Matrix), replacing the final agent reply.
2. Background#
2.1 Slash commands and discord.py 2.7+#
Hermes pins discord.py[voice]==2.7.1. In 2.7+, allowed_contexts and allowed_installs default to None. When synced to Discord API v10, null values make slash commands invisible in the / picker.
Mitigation (local patch today): After registering all slash commands, set on every command without explicit values:
allowed_contexts: guild + DM + private channelallowed_installs: guild + user
Location: gateway/platforms/discord.py → _register_slash_commands() (end of registration, before optional DISCORD_HIDE_SLASH_COMMANDS).
Other installs may not have noticed this if they were on older discord.py, had fewer global commands, or never relied on the slash picker.
2.2 Auto-thread + reactions (already shipped)#
| Setting | Funday default | Effect |
|---|---|---|
DISCORD_AUTO_THREAD | true | New thread per @mention in channels |
DISCORD_REACTIONS | true | 👀 on processing start, ✅/❌ on complete |
3. Current behavior#
User @mentions Hermes in #channel
│
▼
DISCORD_AUTO_THREAD → create thread; session routes to thread id
│
▼
MessageEvent:
source.chat_id = thread id
raw_message = original message in #channel
│
▼
on_processing_start → 👀 on raw_message (parent channel)
Agent reply → sent to thread
Tool progress → optional editable TEXT bubble in thread
(display.platforms.discord.tool_progress)Implication: The dashboard embed should be posted in the thread (source.chat_id), while 👀 stays on the user’s message in the parent channel.
4. Proposed UX#
- User mentions bot in a text channel.
- Hermes creates a thread (existing behavior).
- 👀 appears on the user’s original message (existing behavior).
- New: Bot posts a single embed in the thread:
- Title: e.g.
Hermesor session label - Description: excerpt of the user’s message (from trigger text)
- Fields: Status (
Processing…), step, last tools
- Title: e.g.
- On each tool-calling iteration, the embed is edited in place.
- On success/failure, embed color/footer updates (e.g. green / red); optional cleanup of tool-progress text messages.
5. Architecture#
5.1 Recommended approach: core plumbing + hook layouts#
| Layer | Responsibility |
|---|---|
| hermes-agent | Detect auto-thread; send/edit/finish embed via DiscordAdapter; emit hook events; apply hook-returned embed dicts |
~/.hermes/hooks/ | Return embed structure (title, description, color, fields) per event — survives hermes update |
┌─────────────────────┐ emit_collect ┌──────────────────────────┐
│ Gateway / run.py │ ────────────────────► │ ~/.hermes/hooks/ │
│ agent:step, etc. │ │ discord-thread-dashboard │
└─────────┬───────────┘ └────────────┬─────────────┘
│ │
│ apply embed dict │ return layout
▼ │
┌─────────────────────┐◄─────────────────────────────────────┘
│ DiscordAdapter │
│ send / edit embed │
└─────────────────────┘5.2 Alternatives considered#
| Option | Pros | Cons |
|---|---|---|
| A. Hook-only (REST) | No upstream diff | No chat_id/thread_id in hook context today; fragile state |
| B. Core + hooks ✅ | Correct routing; Funday customizes layout in HERMES_HOME | Small patch in hermes-agent |
| C. Built-in only | Fastest | Hard to customize |
6. Hook contract#
New gateway events (exact names TBD; prefer discord:dashboard:* prefix):
| Event | When | Context keys (minimum) |
|---|---|---|
discord:dashboard:create | Auto-thread + processing start | session_id, session_key, chat_id, thread_id, message_id, user_id, user_name, user_message, discord_auto_thread |
discord:dashboard:update | Each agent:step while dashboard active | Above + iteration, tool_names, tools |
discord:dashboard:finish | Processing complete | Above + outcome (success / failure / cancelled), response_preview |
Handler return shape (first non-None result wins via emit_collect):
{
"title": "Hermes",
"description": "…", # optional; max ~4096 for Discord
"color": 0x5865F2, # int, Discord embed color
"fields": [
{"name": "Status", "value": "👀 Processing…", "inline": False},
{"name": "Tools", "value": "read_file, …", "inline": False},
],
"footer": {"text": "Step 3"}, # optional
}Errors in hooks are logged; they never block the agent pipeline (same as existing Event Hooks).
6.1 Enrich existing agent:* hooks (optional)#
Extend agent:start / agent:step / agent:end context with chat_id, thread_id, message_id for hooks that do not need Discord-specific events. Dashboard plumbing should still use discord:dashboard:* so layouts stay platform-scoped.
7. Core changes (hermes-agent)#
Planned touch points (upstream PR or Funday fork branch):
| File | Change |
|---|---|
gateway/platforms/base.py | Optional discord_auto_thread: bool on MessageEvent (or tag in source) |
gateway/platforms/discord.py | Set flag when _auto_create_thread succeeds; _thread_dashboards map session_key → message_id; send/edit embed helpers; call hooks via gateway_runner.hooks |
gateway/run.py | On agent:step for Discord, call adapter dashboard update; enrich agent:start hook context |
gateway/hooks.py | Document new events in module docstring |
website/docs/.../hooks.md | Document discord:dashboard:* and return shape |
Adapter methods (sketch):
async def _start_thread_dashboard(self, event: MessageEvent) -> None: ...
async def _update_thread_dashboard(self, session_key: str, step_ctx: dict) -> None: ...
async def _finish_thread_dashboard(self, event: MessageEvent, outcome: ProcessingOutcome) -> None: ...Integration point: on_processing_start → create; bridge from existing agent:step emission in _run_agent; on_processing_complete → finish.
8. Funday hook (~/.hermes/hooks/)#
Planned layout (not created until core emits events):
~/.hermes/hooks/discord-thread-dashboard/
├── HOOK.yaml
└── handler.pyHOOK.yaml (draft):
name: discord-thread-dashboard
description: Embed layout for auto-thread processing dashboard on Discord
events:
- discord:dashboard:create
- discord:dashboard:update
- discord:dashboard:finishhandler.py (draft): Return embed dicts; quote user message on create; show tool list on update; set green/red on finish.
This directory is not overwritten by hermes update (lives under HERMES_HOME, not the git repo).
9. Configuration#
| Variable / config | Default | Purpose |
|---|---|---|
DISCORD_THREAD_DASHBOARD | false | Enable embed dashboard for auto-thread sessions |
discord.thread_dashboard in config.yaml | — | YAML equivalent (if wired in gateway/config.py) |
display.platforms.discord.tool_progress | all | Set to off in threads if embed replaces text progress |
Funday rollout suggestion: enable dashboard in ~/.hermes/.env after core lands; tune tool progress per channel noise preference.
10. hermes update and persistence#
| Artifact | After hermes update |
|---|---|
~/.hermes/hooks/discord-thread-dashboard/ | Kept |
~/.hermes/.env, config.yaml, SOUL.md | Kept |
gateway/platforms/discord.py in repo | Replaced by git pull unless changes are committed upstream or stashed locally |
Local-only patches (e.g. allowed_contexts block) | Lost if uncommitted when pull/reset runs |
Practice: Put agent changes in upstream Hermes or a tracked fork branch; keep Funday-specific behavior in ~/.hermes/hooks/ and config.
11. Implementation phases#
| Phase | Scope | Owner |
|---|---|---|
| P0 | Document plan (this page) | Funday docs ✅ |
| P1 | allowed_contexts fix upstream or committed on deploy branch | Hermes |
| P2 | MessageEvent auto-thread flag + adapter embed send/edit | Hermes |
| P3 | discord:dashboard:* events + emit_collect wiring | Hermes |
| P4 | Funday hook under ~/.hermes/hooks/ + DISCORD_THREAD_DASHBOARD=true | Funday |
| P5 | Docs in upstream Hermes hooks guide; runbook entry in Funday runbooks | Both |
12. Testing#
Manual checklist (Discord test server):
- @mention bot in a channel with
DISCORD_AUTO_THREAD=trueand dashboard enabled. - Confirm thread created, 👀 on parent message, embed appears in thread with user text.
- Trigger a multi-tool turn; confirm embed fields update without new spam messages.
- Confirm ✅ on parent message and embed shows success state on completion.
- Failure path: tool error → embed shows failure color; ❌ on parent message.
hermes update→ hook still loaded; dashboard still works if core events present.
13. Open decisions#
| # | Question | Recommendation |
|---|---|---|
| 1 | Dashboard alongside or instead of tool-progress text? | Alongside initially; Funday can set tool_progress: off for Discord if noisy |
| 2 | Delete dashboard embed after final reply? | No (v1) — leave as breadcrumb; optional cleanup_progress-style flag later |
| 3 | Only auto-thread, or all thread sessions? | Auto-thread only (v1) — avoids duplicate dashboards in long-lived threads |
| 4 | Slash-command threads (/thread)? | Out of scope (v1) — mention/auto-thread path only |
References#
- Hermes Discord messaging:
hermes-agent/website/docs/user-guide/messaging/discord.md - Gateway event hooks:
hermes-agent/website/docs/user-guide/features/hooks.md - Funday Hermes setup: Hermes Setup
- Code:
gateway/platforms/discord.py(_auto_create_thread,on_processing_start,_register_slash_commands)