From efbe8d674a6d7814891eb027f38f24403c77b925 Mon Sep 17 00:00:00 2001 From: Teknium Date: Tue, 7 Apr 2026 17:38:07 -0700 Subject: [PATCH] docs: add Discord channel controls and Telegram reactions documentation - Discord: ignored_channels, no_thread_channels config reference + examples - Telegram: message reactions section with config, behavior notes - Environment variables reference updated for all new vars --- .../gateway/test_discord_channel_controls.py | 7 ++-- tests/gateway/test_telegram_reactions.py | 4 +- .../docs/reference/environment-variables.md | 4 ++ website/docs/user-guide/messaging/discord.md | 38 +++++++++++++++++++ website/docs/user-guide/messaging/telegram.md | 29 ++++++++++++++ 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/tests/gateway/test_discord_channel_controls.py b/tests/gateway/test_discord_channel_controls.py index 9b8e7cbb85..d71304d095 100644 --- a/tests/gateway/test_discord_channel_controls.py +++ b/tests/gateway/test_discord_channel_controls.py @@ -77,7 +77,6 @@ class FakeThread: def adapter(monkeypatch): monkeypatch.setattr(discord_platform.discord, "DMChannel", FakeDMChannel, raising=False) monkeypatch.setattr(discord_platform.discord, "Thread", FakeThread, raising=False) - monkeypatch.setattr(discord_platform.discord, "ForumChannel", type("ForumChannel", (), {}), raising=False) config = PlatformConfig(enabled=True, token="fake-token") adapter = DiscordAdapter(config) @@ -294,7 +293,9 @@ def test_config_bridges_ignored_channels(monkeypatch, tmp_path): }, })) monkeypatch.setenv("HERMES_HOME", str(tmp_path)) - monkeypatch.delenv("DISCORD_IGNORED_CHANNELS", raising=False) + # Use setenv (not delenv) so monkeypatch registers cleanup even when + # the var doesn't exist yet — load_gateway_config will overwrite it. + monkeypatch.setenv("DISCORD_IGNORED_CHANNELS", "") from gateway.config import load_gateway_config load_gateway_config() @@ -313,7 +314,7 @@ def test_config_bridges_no_thread_channels(monkeypatch, tmp_path): }, })) monkeypatch.setenv("HERMES_HOME", str(tmp_path)) - monkeypatch.delenv("DISCORD_NO_THREAD_CHANNELS", raising=False) + monkeypatch.setenv("DISCORD_NO_THREAD_CHANNELS", "") from gateway.config import load_gateway_config load_gateway_config() diff --git a/tests/gateway/test_telegram_reactions.py b/tests/gateway/test_telegram_reactions.py index c232a76011..5068adb9f8 100644 --- a/tests/gateway/test_telegram_reactions.py +++ b/tests/gateway/test_telegram_reactions.py @@ -230,7 +230,9 @@ def test_config_bridges_telegram_reactions(monkeypatch, tmp_path): }, })) monkeypatch.setenv("HERMES_HOME", str(tmp_path)) - monkeypatch.delenv("TELEGRAM_REACTIONS", raising=False) + # Use setenv (not delenv) so monkeypatch registers cleanup even when + # the var doesn't exist yet — load_gateway_config will overwrite it. + monkeypatch.setenv("TELEGRAM_REACTIONS", "") from gateway.config import load_gateway_config load_gateway_config() diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index 7d40546c39..beacb8c117 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -164,6 +164,7 @@ For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETI | `TELEGRAM_WEBHOOK_URL` | Public HTTPS URL for webhook mode (enables webhook instead of polling) | | `TELEGRAM_WEBHOOK_PORT` | Local listen port for webhook server (default: `8443`) | | `TELEGRAM_WEBHOOK_SECRET` | Secret token for verifying updates come from Telegram | +| `TELEGRAM_REACTIONS` | Enable emoji reactions on messages during processing (default: `false`) | | `DISCORD_BOT_TOKEN` | Discord bot token | | `DISCORD_ALLOWED_USERS` | Comma-separated Discord user IDs allowed to use the bot | | `DISCORD_HOME_CHANNEL` | Default Discord channel for cron delivery | @@ -171,6 +172,9 @@ For cloud sandbox backends, persistence is filesystem-oriented. `TERMINAL_LIFETI | `DISCORD_REQUIRE_MENTION` | Require an @mention before responding in server channels | | `DISCORD_FREE_RESPONSE_CHANNELS` | Comma-separated channel IDs where mention is not required | | `DISCORD_AUTO_THREAD` | Auto-thread long replies when supported | +| `DISCORD_REACTIONS` | Enable emoji reactions on messages during processing (default: `true`) | +| `DISCORD_IGNORED_CHANNELS` | Comma-separated channel IDs where the bot never responds | +| `DISCORD_NO_THREAD_CHANNELS` | Comma-separated channel IDs where bot responds without auto-threading | | `SLACK_BOT_TOKEN` | Slack bot token (`xoxb-...`) | | `SLACK_APP_TOKEN` | Slack app-level token (`xapp-...`, required for Socket Mode) | | `SLACK_ALLOWED_USERS` | Comma-separated Slack user IDs | diff --git a/website/docs/user-guide/messaging/discord.md b/website/docs/user-guide/messaging/discord.md index bad8d2e321..a015dbb9d6 100644 --- a/website/docs/user-guide/messaging/discord.md +++ b/website/docs/user-guide/messaging/discord.md @@ -280,6 +280,8 @@ Discord behavior is controlled through two files: **`~/.hermes/.env`** for crede | `DISCORD_AUTO_THREAD` | No | `true` | When `true`, automatically creates a new thread for every `@mention` in a text channel, so each conversation is isolated (similar to Slack behavior). Messages already inside threads or DMs are unaffected. | | `DISCORD_ALLOW_BOTS` | No | `"none"` | Controls how the bot handles messages from other Discord bots. `"none"` — ignore all other bots. `"mentions"` — only accept bot messages that `@mention` Hermes. `"all"` — accept all bot messages. | | `DISCORD_REACTIONS` | No | `true` | When `true`, the bot adds emoji reactions to messages during processing (👀 when starting, ✅ on success, ❌ on error). Set to `false` to disable reactions entirely. | +| `DISCORD_IGNORED_CHANNELS` | No | — | Comma-separated channel IDs where the bot **never** responds, even when `@mentioned`. Takes priority over all other channel settings. | +| `DISCORD_NO_THREAD_CHANNELS` | No | — | Comma-separated channel IDs where the bot responds directly in the channel instead of creating a thread. Only relevant when `DISCORD_AUTO_THREAD` is `true`. | ### Config File (`config.yaml`) @@ -292,6 +294,8 @@ discord: free_response_channels: "" # Comma-separated channel IDs (or YAML list) auto_thread: true # Auto-create threads on @mention reactions: true # Add emoji reactions during processing + ignored_channels: [] # Channel IDs where bot never responds + no_thread_channels: [] # Channel IDs where bot responds without threading # Session isolation (applies to all gateway platforms, not just Discord) group_sessions_per_user: true # Isolate sessions per user in shared channels @@ -342,6 +346,40 @@ Controls whether the bot adds emoji reactions to messages as visual feedback: Disable this if you find the reactions distracting or if the bot's role doesn't have the **Add Reactions** permission. +#### `discord.ignored_channels` + +**Type:** string or list — **Default:** `[]` + +Channel IDs where the bot **never** responds, even when directly `@mentioned`. This takes the highest priority — if a channel is in this list, the bot silently ignores all messages there, regardless of `require_mention`, `free_response_channels`, or any other setting. + +```yaml +# String format +discord: + ignored_channels: "1234567890,9876543210" + +# List format +discord: + ignored_channels: + - 1234567890 + - 9876543210 +``` + +If a thread's parent channel is in this list, messages in that thread are also ignored. + +#### `discord.no_thread_channels` + +**Type:** string or list — **Default:** `[]` + +Channel IDs where the bot responds directly in the channel instead of auto-creating a thread. This only has an effect when `auto_thread` is `true` (the default). In these channels, the bot responds inline like a normal message rather than spawning a new thread. + +```yaml +discord: + no_thread_channels: + - 1234567890 # Bot responds inline here +``` + +Useful for channels dedicated to bot interaction where threads would add unnecessary noise. + #### `group_sessions_per_user` **Type:** boolean — **Default:** `true` diff --git a/website/docs/user-guide/messaging/telegram.md b/website/docs/user-guide/messaging/telegram.md index a60697a064..a59b73ca5a 100644 --- a/website/docs/user-guide/messaging/telegram.md +++ b/website/docs/user-guide/messaging/telegram.md @@ -463,6 +463,35 @@ platforms: You usually don't need to configure this manually. The auto-discovery via DoH handles most restricted-network scenarios. The `TELEGRAM_FALLBACK_IPS` env var is only needed if DoH is also blocked on your network. ::: +## Message Reactions + +The bot can add emoji reactions to messages as visual processing feedback: + +- 👀 when the bot starts processing your message +- ✅ when the response is delivered successfully +- ❌ if an error occurs during processing + +Reactions are **disabled by default**. Enable them in `config.yaml`: + +```yaml +telegram: + reactions: true +``` + +Or via environment variable: + +```bash +TELEGRAM_REACTIONS=true +``` + +:::note +Unlike Discord (where reactions are additive), Telegram's Bot API replaces all bot reactions in a single call. The transition from 👀 to ✅/❌ happens atomically — you won't see both at once. +::: + +:::tip +If the bot doesn't have permission to add reactions in a group, the reaction calls fail silently and message processing continues normally. +::: + ## Troubleshooting | Problem | Solution |