mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 15:14:45 +00:00
docs: add ambient room events guide
This commit is contained in:
214
docs/channels/ambient-room-events.md
Normal file
214
docs/channels/ambient-room-events.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
summary: "Let supported group rooms provide quiet context unless the agent sends with the message tool"
|
||||
read_when:
|
||||
- Configuring always-on group or channel rooms
|
||||
- You want the agent to watch room chatter without posting final text automatically
|
||||
- Debugging typing and token usage with no visible room message
|
||||
title: "Ambient room events"
|
||||
sidebarTitle: "Ambient room events"
|
||||
---
|
||||
|
||||
Ambient room events let OpenClaw process unmentioned group or channel chatter as quiet context. The agent can update memory and session state, but the room stays silent unless the agent explicitly calls the `message` tool.
|
||||
|
||||
Use this for always-on rooms where the agent should listen, decide when a reply is useful, and avoid the old prompt pattern of answering `NO_REPLY`.
|
||||
|
||||
Supported today: Discord guild channels, Slack channels and private channels, Slack multi-person DMs, and Telegram groups or supergroups. Other group channels keep their existing group behavior unless their channel page says they support ambient room events.
|
||||
|
||||
## Quick setup
|
||||
|
||||
Set the global group-chat behavior:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
groupChat: {
|
||||
unmentionedInbound: "room_event",
|
||||
visibleReplies: "message_tool",
|
||||
historyLimit: 50,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Then configure the room itself as always-on by disabling mention gating for that room. The channel must still be allowed by its normal `groupPolicy`, room allowlist, and sender allowlist.
|
||||
|
||||
After saving the config, the Gateway hot-reloads `messages` settings. Restart only when file watching or config reload is disabled.
|
||||
|
||||
## What changes
|
||||
|
||||
With `messages.groupChat.unmentionedInbound: "room_event"`:
|
||||
|
||||
- unmentioned allowed group or channel messages become quiet room events
|
||||
- mentioned messages stay user requests
|
||||
- text commands and native commands stay user requests
|
||||
- abort or stop requests stay user requests
|
||||
- direct messages stay user requests
|
||||
|
||||
Room events use strict visible delivery. Final assistant text is private. The agent must call `message(action=send)` to post in the room.
|
||||
|
||||
## Discord example
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
groupChat: {
|
||||
unmentionedInbound: "room_event",
|
||||
visibleReplies: "message_tool",
|
||||
historyLimit: 50,
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
discord: {
|
||||
groupPolicy: "allowlist",
|
||||
guilds: {
|
||||
"<DISCORD_SERVER_ID>": {
|
||||
requireMention: false,
|
||||
users: ["<YOUR_DISCORD_USER_ID>"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Use per-channel Discord config when only one channel should be ambient:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
discord: {
|
||||
guilds: {
|
||||
"<DISCORD_SERVER_ID>": {
|
||||
channels: {
|
||||
"<DISCORD_CHANNEL_ID_OR_NAME>": {
|
||||
allow: true,
|
||||
requireMention: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Slack example
|
||||
|
||||
Slack channel allowlists are ID-first. Use channel IDs such as `C12345678`, not `#channel-name`.
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
groupChat: {
|
||||
unmentionedInbound: "room_event",
|
||||
visibleReplies: "message_tool",
|
||||
historyLimit: 50,
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
slack: {
|
||||
groupPolicy: "allowlist",
|
||||
channels: {
|
||||
"<SLACK_CHANNEL_ID>": {
|
||||
allow: true,
|
||||
requireMention: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Telegram example
|
||||
|
||||
For Telegram groups, the bot must be able to see normal group messages. If `requireMention: false`, disable BotFather privacy mode or use another Telegram setup that delivers full group traffic to the bot.
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
groupChat: {
|
||||
unmentionedInbound: "room_event",
|
||||
visibleReplies: "message_tool",
|
||||
historyLimit: 50,
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
telegram: {
|
||||
groups: {
|
||||
"<TELEGRAM_GROUP_CHAT_ID>": {
|
||||
groupPolicy: "open",
|
||||
requireMention: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Telegram group IDs are usually negative numbers such as `-1001234567890`. Read `chat.id` from `openclaw logs --follow`, forward a group message to an ID helper bot, or inspect Bot API `getUpdates`.
|
||||
|
||||
## Agent specific policy
|
||||
|
||||
Use an agent override when several agents share the same room but only one should treat unmentioned chatter as ambient context:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
groupChat: {
|
||||
visibleReplies: "message_tool",
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
groupChat: {
|
||||
unmentionedInbound: "room_event",
|
||||
mentionPatterns: ["@openclaw", "openclaw"],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The agent-specific `agents.list[].groupChat.unmentionedInbound` value overrides `messages.groupChat.unmentionedInbound` for that agent.
|
||||
|
||||
## Visible reply modes
|
||||
|
||||
`messages.groupChat.visibleReplies: "message_tool"` is the recommended group and channel default. It lets the agent decide when to speak by calling the message tool. If the model returns final text without calling the tool, OpenClaw keeps that final text private and logs suppressed delivery metadata.
|
||||
|
||||
Use `messages.groupChat.visibleReplies: "automatic"` only when you want legacy behavior where normal group requests post final assistant text automatically.
|
||||
|
||||
Room events stay strict even when other group requests use automatic replies. Unmentioned ambient room events still require `message(action=send)` for visible output.
|
||||
|
||||
## History
|
||||
|
||||
`messages.groupChat.historyLimit` controls the global group history default. Channels can override it with `channels.<channel>.historyLimit`, and some channels also support per-account history limits.
|
||||
|
||||
Set `historyLimit: 0` to disable group history context.
|
||||
|
||||
Supported room-event channels keep recent ambient room messages as context. Discord keeps room-event history until a visible Discord send succeeds, so quiet context is not lost before message-tool delivery.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the room shows typing or token usage but no visible message:
|
||||
|
||||
1. Confirm the room is allowed by the channel allowlist and sender allowlist.
|
||||
2. Confirm `requireMention: false` is set at the room level you expect.
|
||||
3. Check whether `messages.groupChat.unmentionedInbound` or the agent override is `"room_event"`.
|
||||
4. Inspect logs for suppressed final payload metadata or `didSendViaMessagingTool: false`.
|
||||
5. Use a model/runtime that reliably calls tools, or set `messages.groupChat.visibleReplies: "automatic"` for legacy final replies on normal group requests.
|
||||
|
||||
If Telegram ambient rooms do not trigger at all, check BotFather privacy mode and verify the Gateway is receiving normal group messages.
|
||||
|
||||
If Slack ambient rooms do not trigger, verify the channel key is the Slack channel ID and the app has the required `channels:history` or `groups:history` scope for that room type.
|
||||
|
||||
## Related
|
||||
|
||||
- [Groups](/channels/groups)
|
||||
- [Discord](/channels/discord)
|
||||
- [Slack](/channels/slack)
|
||||
- [Telegram](/channels/telegram)
|
||||
- [Channel troubleshooting](/channels/troubleshooting)
|
||||
- [Channel configuration reference](/gateway/config-channels)
|
||||
@@ -250,9 +250,9 @@ Once DMs are working, you can set up your Discord server as a full workspace whe
|
||||
<Step title="Allow responses without @mention">
|
||||
By default, your agent only responds in guild channels when @mentioned. For a private server, you probably want it to respond to every message.
|
||||
|
||||
In guild channels, visible Discord output should use the `message` tool by default, so the agent can lurk and only post when it decides a channel reply is useful. For normal requests, OpenClaw falls back to the assistant's final text when the model misses the tool; ambient room events stay quiet unless the tool sends.
|
||||
In guild channels, visible Discord output should use the `message` tool by default, so the agent can lurk and only post when it decides a channel reply is useful. Ambient room events stay quiet unless the tool sends. See [Ambient room events](/channels/ambient-room-events) for the full lurk-mode config.
|
||||
|
||||
This means the selected model should reliably call tools. If Discord shows typing and the logs show token usage but no posted message, check whether the turn was configured as an ambient room event or use the config below to restore legacy automatic final replies.
|
||||
This means the selected model should reliably call tools. If Discord shows typing and the logs show token usage but no posted message, check whether the turn was configured as an ambient room event or use the config below to restore legacy automatic final replies for normal group requests.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Ask your agent">
|
||||
|
||||
@@ -8,6 +8,8 @@ sidebarTitle: "Groups"
|
||||
|
||||
OpenClaw treats group chats consistently across surfaces: Discord, iMessage, Matrix, Microsoft Teams, Signal, Slack, Telegram, WhatsApp, Zalo.
|
||||
|
||||
For always-on rooms that should provide quiet context unless the agent explicitly sends a visible message, see [Ambient room events](/channels/ambient-room-events).
|
||||
|
||||
## Beginner intro (2 minutes)
|
||||
|
||||
OpenClaw "lives" on your own messaging accounts. There is no separate WhatsApp bot user. If **you** are in a group, OpenClaw can see that group and respond there.
|
||||
@@ -64,7 +66,7 @@ This replaces the old pattern of forcing the model to answer `NO_REPLY` for most
|
||||
|
||||
Typing indicators are still sent for direct group requests. Ambient always-on room events, when enabled, stay strict and quiet unless the agent calls the message tool.
|
||||
|
||||
To submit unmentioned always-on group chatter as quiet room context instead of user requests:
|
||||
To submit unmentioned always-on group chatter as quiet room context instead of user requests, use [Ambient room events](/channels/ambient-room-events):
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -78,6 +80,8 @@ To submit unmentioned always-on group chatter as quiet room context instead of u
|
||||
|
||||
The default is `unmentionedInbound: "user_request"`.
|
||||
|
||||
Mentioned messages, commands, abort requests, and DMs stay user requests.
|
||||
|
||||
To restore legacy automatic final replies for group/channel requests:
|
||||
|
||||
```json5
|
||||
@@ -367,7 +371,7 @@ Replying to a bot message counts as an implicit mention when the channel support
|
||||
- Allowlisting a group or sender does not disable mention gating; set that group's `requireMention` to `false` when all messages should trigger.
|
||||
- Automatic group chat prompt context carries the resolved silent-reply instruction every turn; workspace files should not duplicate `NO_REPLY` mechanics.
|
||||
- Groups where automatic silent replies are allowed treat clean empty or reasoning-only model turns as silent, equivalent to `NO_REPLY`. Direct chats never receive `NO_REPLY` guidance, and message-tool-only group replies stay quiet by not calling `message(action=send)`.
|
||||
- Ambient always-on group chatter uses user-request semantics by default. Set `messages.groupChat.unmentionedInbound: "room_event"` to submit it as quiet context instead.
|
||||
- Ambient always-on group chatter uses user-request semantics by default. Set `messages.groupChat.unmentionedInbound: "room_event"` to submit it as quiet context instead. See [Ambient room events](/channels/ambient-room-events) for setup examples.
|
||||
- Room events are not stored as fake user requests, and private assistant text from no-message-tool room events is not replayed as chat history.
|
||||
- Discord defaults live in `channels.discord.guilds."*"` (overridable per guild/channel).
|
||||
- Group history context is wrapped uniformly across channels. Mention-gated groups keep pending skipped messages; always-on groups may also retain recent processed room messages when the channel supports it. Use `messages.groupChat.historyLimit` for the global default and `channels.<channel>.historyLimit` (or `channels.<channel>.accounts.*.historyLimit`) for overrides. Set `0` to disable.
|
||||
|
||||
@@ -21,6 +21,9 @@ Text is supported everywhere; media and reactions vary by channel.
|
||||
- Channels that accept bot-authored inbound messages can use shared
|
||||
[bot loop protection](/channels/bot-loop-protection) to prevent bot pairs from
|
||||
replying to each other indefinitely.
|
||||
- Supported always-on rooms can use [ambient room events](/channels/ambient-room-events)
|
||||
so unmentioned room chatter becomes quiet context unless the agent sends with
|
||||
the `message` tool.
|
||||
|
||||
## Supported channels
|
||||
|
||||
|
||||
@@ -1365,6 +1365,7 @@ Primary reference: [Configuration reference - Slack](/gateway/config-channels#sl
|
||||
- `requireMention`
|
||||
- per-channel `users` allowlist
|
||||
- `messages.groupChat.visibleReplies`: if it is `"message_tool"` and logs show assistant text with no `message(action=send)` call, the model missed the visible message-tool path. Final text stays private in this mode; inspect the gateway verbose log for suppressed payload metadata, or set it to `"automatic"` if you want every normal assistant final reply posted through the legacy path.
|
||||
- `messages.groupChat.unmentionedInbound`: if it is `"room_event"`, unmentioned allowed channel chatter is ambient context and stays silent unless the agent calls the `message` tool. See [Ambient room events](/channels/ambient-room-events).
|
||||
|
||||
```json5
|
||||
{
|
||||
|
||||
@@ -80,12 +80,12 @@ Full troubleshooting: [Telegram troubleshooting](/channels/telegram#troubleshoot
|
||||
|
||||
### Discord failure signatures
|
||||
|
||||
| Symptom | Fastest check | Fix |
|
||||
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Bot online but no guild replies | `openclaw channels status --probe` | Allow guild/channel and verify message content intent. |
|
||||
| Group messages ignored | Check logs for mention gating drops | Mention bot or set guild/channel `requireMention: false`. |
|
||||
| Typing/token usage but no Discord message | Check whether `messages.groupChat.visibleReplies` is `"message_tool"` and the agent missed `message(action=send)` | Inspect the gateway verbose log for suppressed final payload metadata, verify `messages.groupChat.unmentionedInbound` is not routing the event as quiet room context, or set `messages.groupChat.visibleReplies: "automatic"` to use the legacy final-reply path. |
|
||||
| DM replies missing | `openclaw pairing list discord` | Approve DM pairing or adjust DM policy. |
|
||||
| Symptom | Fastest check | Fix |
|
||||
| ----------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Bot online but no guild replies | `openclaw channels status --probe` | Allow guild/channel and verify message content intent. |
|
||||
| Group messages ignored | Check logs for mention gating drops | Mention bot or set guild/channel `requireMention: false`. |
|
||||
| Typing/token usage but no Discord message | Check whether this is an ambient room event or a missed `message(action=send)` call | Inspect the gateway verbose log for suppressed final payload metadata, verify `messages.groupChat.unmentionedInbound`, read [Ambient room events](/channels/ambient-room-events), or set `messages.groupChat.visibleReplies: "automatic"` to use the legacy final-reply path for normal group requests. |
|
||||
| DM replies missing | `openclaw pairing list discord` | Approve DM pairing or adjust DM policy. |
|
||||
|
||||
Full troubleshooting: [Discord troubleshooting](/channels/discord#troubleshooting)
|
||||
|
||||
|
||||
@@ -1105,6 +1105,7 @@
|
||||
"channels/access-groups",
|
||||
"channels/group-messages",
|
||||
"channels/groups",
|
||||
"channels/ambient-room-events",
|
||||
"channels/broadcast-groups",
|
||||
"channels/channel-routing",
|
||||
"channels/location",
|
||||
|
||||
@@ -824,7 +824,7 @@ The gateway hot-reloads `messages` config after the file is saved. Restart only
|
||||
|
||||
`messages.groupChat.historyLimit` sets the global default. Channels can override with `channels.<channel>.historyLimit` (or per-account). Set `0` to disable.
|
||||
|
||||
`messages.groupChat.unmentionedInbound: "room_event"` submits unmentioned always-on group/channel messages as quiet room context. Mentioned messages, commands, and direct messages remain user requests.
|
||||
`messages.groupChat.unmentionedInbound: "room_event"` submits unmentioned always-on group/channel messages as quiet room context on supported channels. Mentioned messages, commands, and direct messages remain user requests. See [Ambient room events](/channels/ambient-room-events) for complete Discord, Slack, and Telegram examples.
|
||||
|
||||
`messages.visibleReplies` is the global source-event default; `messages.groupChat.visibleReplies` overrides it for group/channel source events. When `messages.visibleReplies` is unset, a harness can provide its own direct/source default; the Codex harness defaults to `message_tool`. Channel allowlists and mention gating still decide whether an event is processed.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user