diff --git a/docs/channels/group-messages.md b/docs/channels/group-messages.md index c1858bf1d96..f62842ab89e 100644 --- a/docs/channels/group-messages.md +++ b/docs/channels/group-messages.md @@ -13,7 +13,7 @@ Note: `agents.list[].groupChat.mentionPatterns` is now used by Telegram/Discord/ ## Current implementation (2025-12-03) -- Activation modes: `mention` (default) or `always`. `mention` requires a ping (real WhatsApp @-mentions via `mentionedJids`, safe regex patterns, or the bot’s E.164 anywhere in the text). `always` wakes the agent on every message but it should reply only when it can add meaningful value; otherwise it returns the silent token `NO_REPLY`. Defaults can be set in config (`channels.whatsapp.groups`) and overridden per group via `/activation`. When `channels.whatsapp.groups` is set, it also acts as a group allowlist (include `"*"` to allow all). +- Activation modes: `mention` (default) or `always`. `mention` requires a ping (real WhatsApp @-mentions via `mentionedJids`, safe regex patterns, or the bot’s E.164 anywhere in the text). `always` wakes the agent on every message but it should reply only when it can add meaningful value; otherwise it returns the exact silent token `NO_REPLY` / `no_reply`. Defaults can be set in config (`channels.whatsapp.groups`) and overridden per group via `/activation`. When `channels.whatsapp.groups` is set, it also acts as a group allowlist (include `"*"` to allow all). - Group policy: `channels.whatsapp.groupPolicy` controls whether group messages are accepted (`open|disabled|allowlist`). `allowlist` uses `channels.whatsapp.groupAllowFrom` (fallback: explicit `channels.whatsapp.allowFrom`). Default is `allowlist` (blocked until you add senders). - Per-group sessions: session keys look like `agent::whatsapp:group:` so commands such as `/verbose on` or `/think high` (sent as standalone messages) are scoped to that group; personal DM state is untouched. Heartbeats are skipped for group threads. - Context injection: **pending-only** group messages (default 50) that _did not_ trigger a run are prefixed under `[Chat messages since your last reply - for context]`, with the triggering line under `[Current message - respond to this]`. Messages already in the session are not re-injected. diff --git a/docs/concepts/agent-loop.md b/docs/concepts/agent-loop.md index 43158c563bc..dd6e45c8792 100644 --- a/docs/concepts/agent-loop.md +++ b/docs/concepts/agent-loop.md @@ -124,7 +124,8 @@ See [Plugin hooks](/plugins/architecture#provider-runtime-hooks) for the hook AP - assistant text (and optional reasoning) - inline tool summaries (when verbose + allowed) - assistant error text when the model errors -- `NO_REPLY` is treated as a silent token and filtered from outgoing payloads. +- The exact silent token `NO_REPLY` / `no_reply` is filtered from outgoing + payloads. - Messaging tool duplicates are removed from the final payload list. - If no renderable payloads remain and a tool errored, a fallback tool error reply is emitted (unless a messaging tool already sent a user-visible reply). diff --git a/docs/help/faq.md b/docs/help/faq.md index 521d9cc405f..d882a4af702 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -1030,7 +1030,7 @@ for usage/billing and raise limits as needed. - If the completion origin only carries a channel, OpenClaw falls back to the requester session's stored route (`lastChannel` / `lastTo` / `lastAccountId`) so direct delivery can still succeed. - If neither a bound route nor a usable stored route exists, direct delivery can fail and the result falls back to queued session delivery instead of posting immediately to chat. - Invalid or stale targets can still force queue fallback or final delivery failure. - - If the child's last visible assistant reply is a silent token (`NO_REPLY` / `ANNOUNCE_SKIP`), OpenClaw intentionally suppresses the announce instead of posting stale earlier progress. + - If the child's last visible assistant reply is the exact silent token `NO_REPLY` / `no_reply`, or exactly `ANNOUNCE_SKIP`, OpenClaw intentionally suppresses the announce instead of posting stale earlier progress. - If the child timed out after only tool calls, the announce can collapse that into a short partial-progress summary instead of replaying raw tool output. Debug: diff --git a/docs/tools/subagents.md b/docs/tools/subagents.md index a5ebe3c95d2..9c8525a1bbd 100644 --- a/docs/tools/subagents.md +++ b/docs/tools/subagents.md @@ -235,7 +235,8 @@ Sub-agents report back via an announce step: - The announce step runs inside the sub-agent session (not the requester session). - If the sub-agent replies exactly `ANNOUNCE_SKIP`, nothing is posted. -- If the latest assistant text is a silent token such as `NO_REPLY`, announce output is suppressed even if earlier visible progress existed. +- If the latest assistant text is the exact silent token `NO_REPLY` / `no_reply`, + announce output is suppressed even if earlier visible progress existed. - Otherwise delivery depends on requester depth: - top-level requester sessions use a follow-up `agent` call with external delivery (`deliver=true`) - nested requester subagent sessions receive an internal follow-up injection (`deliver=false`) so the orchestrator can synthesize child results in-session