From 103fe14cb4ed72c89a00427d3a3506eb5a197f0e Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 10 Sep 2026 09:57:09 -0700 Subject: [PATCH] docs(gateway): document gateway.bot_loop_guard where ALLOW_BOTS is explained The Discord page said there was no circuit breaker for bot ack-loops; there is one now. Also strips two trailing blank lines left by the test trim. --- tests/agent/test_turn_author.py | 2 -- tests/cli/test_quiet_turn_author.py | 2 -- website/docs/user-guide/messaging/discord.md | 2 +- website/docs/user-guide/messaging/telegram.md | 13 +++++++++++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/agent/test_turn_author.py b/tests/agent/test_turn_author.py index a072f03ef3..5f69ee5a40 100644 --- a/tests/agent/test_turn_author.py +++ b/tests/agent/test_turn_author.py @@ -38,5 +38,3 @@ class TestEnvCarrier: assert take_turn_author_from_env(env) == author assert env == {"OTHER": "kept"} assert take_turn_author_from_env(env) is None - - diff --git a/tests/cli/test_quiet_turn_author.py b/tests/cli/test_quiet_turn_author.py index 4954571afb..6a13c781d3 100644 --- a/tests/cli/test_quiet_turn_author.py +++ b/tests/cli/test_quiet_turn_author.py @@ -60,5 +60,3 @@ def test_quiet_one_shot_consumes_the_variable_before_the_turn(monkeypatch): _run(monkeypatch, json.dumps(AUTHOR), run_conversation) assert seen["env"] is None assert TURN_AUTHOR_ENV not in os.environ - - diff --git a/website/docs/user-guide/messaging/discord.md b/website/docs/user-guide/messaging/discord.md index 609ab43918..dfad0cc25b 100644 --- a/website/docs/user-guide/messaging/discord.md +++ b/website/docs/user-guide/messaging/discord.md @@ -322,7 +322,7 @@ Discord behavior is controlled through two files: **`~/.hermes/.env`** for crede :::warning Bot-to-bot conversation is not supported `DISCORD_ALLOW_BOTS` exists to accept input from a specific trusted bot (e.g. a relay or webhook bot), not to let two Hermes profiles talk to each other. The default, `"none"`, ignores all other bots and is the safe setting. -Wiring multiple Hermes profiles to reply to one another in a shared channel — by setting `"mentions"` or `"all"` across several profiles — is an unsupported topology. Discord auto-`@mentions` the replied-to author on every reply, so under `"mentions"` two bots will satisfy each other's mention gate indefinitely and ack-loop. There is no circuit breaker for this because the supported configuration is simply to leave `DISCORD_ALLOW_BOTS` at `"none"`. If you must accept a particular bot, scope the acceptance narrowly and never to another auto-replying agent. +Wiring multiple Hermes profiles to reply to one another in a shared channel — by setting `"mentions"` or `"all"` across several profiles — is an unsupported topology. Discord auto-`@mentions` the replied-to author on every reply, so under `"mentions"` two bots will satisfy each other's mention gate and ack-loop. The gateway's bot loop guard bounds the damage rather than preventing it: after 20 bot-authored messages in one channel inside 5 minutes, further bot messages there are dropped for 10 minutes (tunable under `gateway.bot_loop_guard` in `config.yaml`; human messages are never counted). The supported configuration is still to leave `DISCORD_ALLOW_BOTS` at `"none"`. If you must accept a particular bot, scope the acceptance narrowly and never to another auto-replying agent. ::: ### Config File (`config.yaml`) diff --git a/website/docs/user-guide/messaging/telegram.md b/website/docs/user-guide/messaging/telegram.md index 9b04a06a80..d9d7b26bc1 100644 --- a/website/docs/user-guide/messaging/telegram.md +++ b/website/docs/user-guide/messaging/telegram.md @@ -584,6 +584,19 @@ With this setup, a group message like `@research_bot @ops_bot summarize this` is Two Hermes bots that answer each other's quote-replies can still loop forever with `TELEGRAM_ALLOW_BOTS=all`, because a reply to the bot always passes the `require_mention` gate. Setting `telegram.bots_require_mention: true` (env `TELEGRAM_BOTS_REQUIRE_MENTION`) closes that path: a message from another bot only triggers a response when it explicitly `@mentions` this bot, while human replies keep working unchanged. +A bot-to-bot loop guard also meters every chat where bot-authored messages are admitted (`TELEGRAM_ALLOW_BOTS` set to `mentions` or `all`). Once 20 bot messages land in one chat inside 5 minutes, further bot messages in that chat are dropped for 10 minutes and one warning is logged; human messages are never counted or dropped. Settings live in `config.yaml`: + +```yaml +gateway: + bot_loop_guard: + enabled: true # false turns the guard off + max_events: 20 # bot messages per chat per window + window_seconds: 300 + cooldown_seconds: 600 +``` + +A legitimate high-volume bot posting more than 20 messages into one chat in 5 minutes trips the guard too; raise `max_events` for that gateway. + Group conversation text and media captions keep every mention when the message names other participants too (`@research_bot , @ops_bot are you both listening?` reaches `research_bot` verbatim); when this bot is the only one addressed, its own handle is still stripped so short answers such as `@hermes_bot 2` keep working. Group turns also carry the bot's own Telegram username in the per-channel context so the model can tell which retained mentions are for it. Slash commands still use the normal command-trigger cleanup. Set `exclusive_bot_mentions: false` only for legacy groups where explicit mentions should not override reply and wake-word triggers.