diff --git a/charts/openab/templates/configmap.yaml b/charts/openab/templates/configmap.yaml index 4640dafb6..6a8e8b57e 100644 --- a/charts/openab/templates/configmap.yaml +++ b/charts/openab/templates/configmap.yaml @@ -61,7 +61,7 @@ data: {{- if not (has $cfg.discord.allowUserMessages (list "involved" "mentions" "multibot-mentions")) }} {{- fail (printf "agents.%s.discord.allowUserMessages must be one of: involved, mentions, multibot-mentions (use hyphen form, not underscore) — got: %s" $name $cfg.discord.allowUserMessages) }} {{- end }} - allow_user_messages = {{ $cfg.discord.allowUserMessages | toJson }} {{- /* involved (default): respond in bot's threads without @mention | mentions: always require @mention | multibot-mentions: require @mention only when another bot has posted in the thread */ -}} + allow_user_messages = {{ $cfg.discord.allowUserMessages | toJson }} {{- /* multibot-mentions (default): require @mention only when another bot has posted in the thread | involved: respond in bot's threads without @mention | mentions: always require @mention */ -}} {{- end }} {{- if hasKey $cfg.discord "allowDm" }} allow_dm = {{ $cfg.discord.allowDm }} @@ -116,7 +116,7 @@ data: {{- if not (has ($cfg.slack).allowUserMessages (list "involved" "mentions" "multibot-mentions")) }} {{- fail (printf "agents.%s.slack.allowUserMessages must be one of: involved, mentions, multibot-mentions (use hyphen form, not underscore) — got: %s" $name ($cfg.slack).allowUserMessages) }} {{- end }} - allow_user_messages = {{ ($cfg.slack).allowUserMessages | toJson }} {{- /* involved (default): respond in bot's threads without @mention | mentions: always require @mention | multibot-mentions: require @mention only when another bot has posted in the thread */ -}} + allow_user_messages = {{ ($cfg.slack).allowUserMessages | toJson }} {{- /* multibot-mentions (default): require @mention only when another bot has posted in the thread | involved: respond in bot's threads without @mention | mentions: always require @mention */ -}} {{- end }} {{- /* maxBotTurns: soft cap on consecutive bot turns per thread (human msg resets the counter) */ -}} {{- if hasKey ($cfg.slack | default dict) "maxBotTurns" }} diff --git a/charts/openab/values.yaml b/charts/openab/values.yaml index 778751168..27f5effe4 100644 --- a/charts/openab/values.yaml +++ b/charts/openab/values.yaml @@ -309,13 +309,13 @@ agents: allowBotMessages: "off" # trustedBotIds: Bot User IDs (U...) — find via Slack UI: click bot profile → Copy member ID trustedBotIds: [] - # allowUserMessages: "involved" (default) | "mentions" | "multibot-mentions" + # allowUserMessages: "multibot-mentions" (default) | "involved" | "mentions" # "involved" = respond to thread follow-ups without @mention if bot has participated # "mentions" = always require @mention # "multibot-mentions" = same as "involved" in single-bot threads; require @mention # only when another bot has also posted in the thread # (recommended for multi-bot deployments) - allowUserMessages: "involved" + allowUserMessages: "multibot-mentions" # maxBotTurns: soft cap on consecutive bot turns per thread before # the bot stops auto-replying. A human message resets the counter. # Default 100 (Rust-side `default_max_bot_turns()`). Raise for long diff --git a/config.toml.example b/config.toml.example index 200006e39..950d188e2 100644 --- a/config.toml.example +++ b/config.toml.example @@ -13,7 +13,7 @@ allowed_channels = ["1234567890"] # ↑ omitted + non-empty list → auto- # trusted_bot_ids = [] # empty = any bot (mode permitting); set to restrict # allowed_role_ids = [] # role IDs that trigger the bot (same as direct @mention) # note: if multiple bots share the same role, all will respond simultaneously -# allow_user_messages = "involved" # "involved" (default) | "mentions" +# allow_user_messages = "multibot-mentions" # "multibot-mentions" (default) | "involved" | "mentions" # "involved" = reply in threads bot owns or has participated in # "mentions" = always require @mention # allow_dm = false # true = respond to Discord DMs; false (default) = ignore DMs @@ -28,7 +28,7 @@ allowed_channels = ["1234567890"] # ↑ omitted + non-empty list → auto- # allowed_users = ["U0123456789"] # only checked when allow_all_users = false # allow_bot_messages = "off" # "off" (default) | "mentions" | "all" # trusted_bot_ids = [] # empty = any bot (mode permitting); set to restrict -# allow_user_messages = "involved" # "involved" (default) | "mentions" | "multibot-mentions" +# allow_user_messages = "multibot-mentions" # "multibot-mentions" (default) | "involved" | "mentions" # "involved" = reply in threads bot has participated in # "mentions" = always require @mention # "multibot-mentions" = like "involved", but require @mention diff --git a/docs/config-reference.md b/docs/config-reference.md index f40461071..4ca8e0e3a 100644 --- a/docs/config-reference.md +++ b/docs/config-reference.md @@ -38,7 +38,7 @@ Discord adapter. Requires a Discord bot token. | `allowed_users` | string[] | `[]` | User IDs to allow. Only checked when `allow_all_users` resolves to false. | | `allow_bot_messages` | string | `"off"` | `"off"` — ignore all bot messages. `"mentions"` — only process bot messages that @mention this bot. `"all"` — process all bot messages (capped by `max_bot_turns`). | | `trusted_bot_ids` | string[] | `[]` | When non-empty, only these bot IDs pass the bot gate. Empty = any bot (mode permitting). **Admission override:** a trusted bot that @mentions this bot bypasses `allow_bot_messages` mode entirely (treated as human @mention, can pull bot into threads). | -| `allow_user_messages` | string | `"involved"` | `"involved"` — reply in threads bot has participated in without @mention; channel messages require @mention; DMs always process. `"mentions"` — always require @mention. `"multibot-mentions"` — like `"involved"`, but require @mention once another bot has posted in the thread. | +| `allow_user_messages` | string | `"multibot-mentions"` | `"multibot-mentions"` — like `"involved"`, but require @mention once another bot has posted in the thread (recommended for multi-bot deployments). `"involved"` — reply in threads bot has participated in without @mention; channel messages require @mention; DMs always process. `"mentions"` — always require @mention. | | `allow_dm` | bool | `false` | `true` = respond to Discord DMs; `false` = ignore DMs. `allowed_users` still applies in DMs. Each DM user consumes one session slot. | | `max_bot_turns` | u32 | `100` | Max consecutive bot turns per thread before throttling (soft limit). Human message resets the counter. A compiled-in hard cap of 1000 consecutive bot messages is always enforced. | | `message_processing_mode` | string | `"per-message"` | Message dispatch mode: `"per-message"` (each message = own turn), `"per-thread"` (all messages in thread share one buffer), or `"per-lane"` (each sender gets own buffer). See [Message Dispatch Modes](message-dispatch-modes.md). | @@ -61,7 +61,7 @@ Slack adapter using Socket Mode. Requires both a Bot User OAuth Token and an App | `allowed_users` | string[] | `[]` | Slack user IDs (e.g. `U0123456789`). | | `allow_bot_messages` | string | `"off"` | Same as Discord. | | `trusted_bot_ids` | string[] | `[]` | Slack Bot User IDs (`U...`) or Bot IDs (`B...`). `U...` matching resolves event Bot IDs via Slack `bots.info`, so the bot token needs `users:read`. | -| `allow_user_messages` | string | `"involved"` | Same as Discord. | +| `allow_user_messages` | string | `"multibot-mentions"` | Same as Discord. | | `max_bot_turns` | u32 | `100` | Same as Discord. | | `message_processing_mode` | string | `"per-message"` | Same as Discord. See [Message Dispatch Modes](message-dispatch-modes.md). | | `max_buffered_messages` | u32 | `10` | Same as Discord. | diff --git a/docs/discord.md b/docs/discord.md index eacfcefd5..2267aac48 100644 --- a/docs/discord.md +++ b/docs/discord.md @@ -69,7 +69,7 @@ bot_token = "${DISCORD_BOT_TOKEN}" allowed_channels = ["123456789"] # channel ID allowlist (empty = all) allowed_users = ["987654321"] # user ID allowlist (empty = all) allow_bot_messages = "off" # off | mentions | all -allow_user_messages = "involved" # involved | mentions +allow_user_messages = "multibot-mentions" # multibot-mentions | involved | mentions trusted_bot_ids = [] # bot user IDs allowed through (empty = any) ``` @@ -103,9 +103,9 @@ Controls whether the bot requires @mention in threads. | Value | Behavior | |---|---| -| `"involved"` (default) | Respond in threads the bot owns or has participated in without @mention. Main channel always requires @mention. | +| `"involved"` | Respond in threads the bot owns or has participated in without @mention. Main channel always requires @mention. | | `"mentions"` | Always require @mention, even in the bot's own threads. | -| `"multibot-mentions"` | Same as `involved` in single-bot threads. In threads where other bots have also posted, requires @mention — prevents all bots from responding to every message. | +| `"multibot-mentions"` (default) | Same as `involved` in single-bot threads. In threads where other bots have also posted, requires @mention — prevents all bots from responding to every message. | #### Comparison @@ -201,7 +201,8 @@ To help the LLM know who each UID refers to, provide a UID→name mapping via sy When you @mention the bot in a channel, it creates a **thread** from your message and responds there. After that: -- **`involved` mode (default):** just type in the thread — no @mention needed +- **`multibot-mentions` mode (default):** just type in single-bot threads — no @mention needed; in multi-bot threads, @mention required +- **`involved` mode:** just type in the thread — no @mention needed - **`mentions` mode:** @mention required for every message, even in threads Each thread gets its own agent session. Sessions are cleaned up after `session_ttl_hours` (default: 24h). diff --git a/docs/feishu.md b/docs/feishu.md index 15e344f12..515123806 100644 --- a/docs/feishu.md +++ b/docs/feishu.md @@ -81,7 +81,7 @@ https://your-gateway-host/webhook/feishu | — | `FEISHU_TRUSTED_BOT_IDS` | — | Comma-separated open_id list of known bots | | — | `FEISHU_MAX_BOT_TURNS` | `20` | Max consecutive bot replies per channel before suppression | | — | `FEISHU_SESSION_TTL_HOURS` | `24` | How long the bot remembers thread participation (hours). After expiry, @mention is required again. | -| — | `FEISHU_ALLOW_USER_MESSAGES` | `involved` | Thread response mode: `involved` / `mentions` / `multibot-mentions`. See below. | +| — | `FEISHU_ALLOW_USER_MESSAGES` | `multibot-mentions` | Thread response mode: `multibot-mentions` / `involved` / `mentions`. See below. | | `gateway.botUsername` | — | — | Set to bot's `open_id` for @mention gating | | `gateway.streaming` | — | `false` | Enable streaming (typewriter) mode | @@ -111,8 +111,8 @@ When `FEISHU_ALLOW_USER_MESSAGES=multibot-mentions`, the bot detects when anothe | Mode | Behavior | |------|----------| -| `involved` (default) | Bot responds in participated threads without @mention. All participated bots respond. | -| `multibot-mentions` | Same as `involved`, but once another bot is @mentioned in the thread, require @mention for all bots. | +| `multibot-mentions` (default) | Like `involved`, but requires @mention once another bot has posted in the thread. | +| `involved` | Bot responds in participated threads without @mention. All participated bots respond. | | `mentions` | Always require @mention, even in participated threads. | **Multi-bot detection** (how the gateway identifies "another bot"): diff --git a/docs/messaging.md b/docs/messaging.md index d13a9e5a1..d604d8319 100644 --- a/docs/messaging.md +++ b/docs/messaging.md @@ -99,18 +99,18 @@ User in thread: can you also do Y? | Key | Type | Default | Description | |-----|------|---------|-------------| -| `allow_user_messages` | string | `"involved"` | Controls when bots respond without @mention. See Layer 3 for all modes. | +| `allow_user_messages` | string | `"multibot-mentions"` | Controls when bots respond without @mention. See Layer 3 for all modes. | -In this single-bot scenario, the default `"involved"` means the bot responds to all messages in threads it has participated in. +In this single-bot scenario, the default `"multibot-mentions"` behaves the same as `"involved"` — the bot responds to all messages in threads it has participated in. ### Example config.toml ```toml [discord] bot_token = "${DISCORD_BOT_TOKEN}" -# allow_user_messages defaults to "involved": -# bot responds to all messages in threads it has participated in, -# no @mention needed for follow-ups. +# allow_user_messages defaults to "multibot-mentions": +# bot responds to all messages in single-bot threads it has participated in; +# in multi-bot threads, @mention is required. ``` --- @@ -123,20 +123,20 @@ How involved bots behave on subsequent messages is controlled by `allow_user_mes | Mode | Behavior | |------|----------| -| `involved` (default) | All involved bots respond to every message — no @mention required. | +| `multibot-mentions` (default) | Like `involved`, but once a second bot has posted in the thread, you must @mention the bot(s) you want to respond. | +| `involved` | All involved bots respond to every message — no @mention required. | | `mentions` | Always require an explicit @mention, even in threads. | -| `multibot-mentions` | Like `involved`, but once a second bot has posted in the thread, you must @mention the bot(s) you want to respond. | ``` -# allow_user_messages = "involved" (default) +# allow_user_messages = "multibot-mentions" (default) User in thread: @BotB what do you think? → BotB replies, now "involved" User in thread: any other ideas? - → Both BotA and BotB reply + → No bot replies (need explicit @mention) -# allow_user_messages = "multibot-mentions" +# allow_user_messages = "involved" User in thread: any other ideas? - → No bot replies (need explicit @mention) + → Both BotA and BotB reply User in thread: @BotA any other ideas? → Only BotA replies ``` @@ -145,7 +145,7 @@ User in thread: @BotA any other ideas? | Key | Type | Default | Description | |-----|------|---------|-------------| -| `allow_user_messages` | string | `"involved"` | `"involved"` — reply without @mention in participated threads. `"mentions"` — always require @mention. `"multibot-mentions"` — require @mention once 2+ bots are in the thread. | +| `allow_user_messages` | string | `"multibot-mentions"` | `"multibot-mentions"` — require @mention once 2+ bots are in the thread. `"involved"` — reply without @mention in participated threads. `"mentions"` — always require @mention. | > **Note:** This is a **global setting** — it cannot be changed per thread. Configure it in `config.toml` or via `values.yaml` for Helm. @@ -154,8 +154,8 @@ User in thread: @BotA any other ideas? ```toml [discord] bot_token = "${DISCORD_BOT_TOKEN}" -# Default is "involved" — all involved bots respond without @mention. -# Use "multibot-mentions" for precise control in multi-bot threads. +# Default is "multibot-mentions" — require @mention in multi-bot threads. +# Use "involved" to let all bots respond without @mention. allow_user_messages = "multibot-mentions" ``` diff --git a/docs/multi-agent.md b/docs/multi-agent.md index 7a4b1a609..6fcb6d112 100644 --- a/docs/multi-agent.md +++ b/docs/multi-agent.md @@ -77,6 +77,8 @@ allow_bot_messages = "mentions" # recommended Use `"all"` only when bots need to react to each other's messages without explicit mentions (e.g. monitoring bots). A hard cap of 10 consecutive bot-to-bot turns prevents infinite loops. +> **💡 User messages in multi-bot threads:** The default `allow_user_messages = "multibot-mentions"` already handles the user→bot side — once multiple bots are in a thread, users must @mention the specific bot they want to respond. No extra config needed. + ### Example: Code Review → Deploy handoff ``` diff --git a/gateway/src/adapters/feishu.rs b/gateway/src/adapters/feishu.rs index 75cd45dd5..6f9728b24 100644 --- a/gateway/src/adapters/feishu.rs +++ b/gateway/src/adapters/feishu.rs @@ -73,12 +73,12 @@ pub enum AllowBots { #[derive(Debug, Clone, PartialEq, Default)] pub enum AllowUsers { /// Bot responds in threads it has participated in without @mention. - #[default] Involved, /// Always require @mention, even in participated threads. Mentions, /// Like Involved, but if another bot has also posted in the thread, /// require @mention to avoid all bots responding. + #[default] MultibotMentions, } @@ -150,14 +150,14 @@ impl FeishuConfig { }; let trusted_bot_ids = parse_csv("FEISHU_TRUSTED_BOT_IDS"); let allow_user_messages = match std::env::var("FEISHU_ALLOW_USER_MESSAGES") - .unwrap_or_else(|_| "involved".into()) + .unwrap_or_else(|_| "multibot_mentions".into()) .to_lowercase() .replace('-', "_") .as_str() { + "involved" => AllowUsers::Involved, "mentions" => AllowUsers::Mentions, - "multibot_mentions" => AllowUsers::MultibotMentions, - _ => AllowUsers::Involved, + _ => AllowUsers::MultibotMentions, }; let max_bot_turns = std::env::var("FEISHU_MAX_BOT_TURNS") .ok() @@ -2420,7 +2420,7 @@ mod tests { allowed_users: vec![], require_mention: true, allow_bots: AllowBots::Off, - allow_user_messages: AllowUsers::Involved, + allow_user_messages: AllowUsers::MultibotMentions, trusted_bot_ids: vec![], max_bot_turns: 20, dedupe_ttl_secs: 300, diff --git a/src/config.rs b/src/config.rs index 04d6d0c47..991071164 100644 --- a/src/config.rs +++ b/src/config.rs @@ -358,17 +358,17 @@ fn default_max_batch_tokens() -> usize { /// Controls whether the bot responds to user messages in threads without @mention. /// -/// - `Involved` (default): respond to thread messages only if the bot has participated +/// - `Involved`: respond to thread messages only if the bot has participated /// in the thread (posted at least one message, or the thread parent @mentions the bot). /// Channel/MPDM messages always require @mention. DMs always process (implicit mention). /// - `Mentions`: always require @mention, even in threads the bot is participating in. -/// - `MultibotMentions`: same as `Involved` in single-bot threads; falls back to `Mentions` -/// when other bots have also posted in the thread. +/// - `MultibotMentions` (default): same as `Involved` in single-bot threads; falls back to +/// `Mentions` when other bots have also posted in the thread. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub enum AllowUsers { - #[default] Involved, Mentions, + #[default] MultibotMentions, }