Summary
In 2026.4.22, the runtime-level "Working… / tool: … / tool args …" progress messages (normally hidden in group chats) are leaking into Slack group DMs (MPIMs) as real, user-visible messages. This exposes internal tool names and arguments (including fetched URLs and message/reaction targets) to group participants.
This happens even when no agent has verboseDefault set anywhere in config — implying the global fallback default for shouldEmitVerboseProgress() is effectively "on" for this surface, or the gate intended to suppress group delivery isn't firing.
Environment
- Version: OpenClaw 2026.4.22 (upgraded from 2026.4.20, same day)
- Channel: Slack
- Chat type: Slack MPIM (multi-person IM / group DM)
- Agent: default main agent, Anthropic claude-opus-4-7
- Config: no
verbose* keys present anywhere; agents.defaults.thinkingDefault: "medium", per-agent thinkingDefault: "high" for main (not relevant to this bug)
Repro
- Slack MPIM with bot + 2 human users.
- Human sends a URL into the MPIM (no mention of bot).
- Bot is configured to consider whether to react / respond; on this turn it decided to call
web_fetch then message (react with emoji) and emit NO_REPLY.
- The two tool invocations resulted in two separate real Slack messages posted by the bot into the MPIM:
Working…
• web_fetch from https://www.reddit.com/r/AncientAliens/s/<redacted> (max 3000 chars)
• tool: web_fetch
• web_fetch from https://www.reddit.com/r/AncientAliens/s/<redacted> (max 3000 chars)
Working…
• message message 1776999987.800299, emoji alien
• tool: message
• message message 1776999987.800299, emoji alien
The bot's correct NO_REPLY was honored (no final reply), but the internal trace still shipped.
Expected
No "Working…" or tool-trace messages should be emitted to Slack group chats (MPIM or channel). These are runtime diagnostics, not user-facing content.
Code analysis
Trace generator: /app/dist/dispatch-BbwSt8e4.js:583-596 (maybeSendWorkingStatus):
const maybeSendWorkingStatus = async (label) => {
if (suppressDelivery) return;
const normalizedLabel = normalizeWorkingLabel(label);
if (!shouldEmitVerboseProgress() || !shouldSendToolStartStatuses || ...) return;
...
const payload = { text: `Working: ${normalizedLabel}` };
...
};
Two gates:
-
shouldSendToolStartStatuses (line 482):
const shouldSendToolStartStatuses = ctx.ChatType !== "group" || ctx.IsForum === true;
Intent: suppress tool-start statuses in group chats unless it's a forum.
-
shouldEmitVerboseProgress() (line 218-229):
const currentLevel = normalizeVerboseLevel(entry?.verboseLevel ?? "");
if (currentLevel) return currentLevel !== "off";
return params.fallbackLevel !== "off";
With no session-level verbose set and config verboseDefault unset, fallback resolves to "off" via nullish coalescing, so this gate should return false.
Hypothesis on why both gates failed here:
-
Gate 1 (ChatType): Slack's ingress has two paths that set ChatType for MPIMs differently:
/app/dist/extensions/slack/prepare-BH5U3jEx.js:149-151: isGroup = channelType === "mpim"; chatType = isDirectMessage ? "direct" : isGroup ? "group" : "channel" — correct.
/app/dist/extensions/slack/prepare-BH5U3jEx.js:1261,1343: ChatType: isDirectMessage ? "direct" : "channel" — wrong for MPIMs (forces channel, loses the group distinction).
If the second path fired for this turn, shouldSendToolStartStatuses evaluates to true and the trace is allowed through.
-
Gate 2 (verbose): unclear how this returned true given no verboseDefault is set. Possibly a fallback resolution bug introduced in 2026.4.22, or a default changed somewhere. Haven't pinpointed.
The two-gate design is correct; the implementation has at least one broken gate (MPIM ChatType branch inconsistency), and possibly a second (verbose fallback).
Impact
- Information leak: internal tool names, arguments, and target message IDs posted to group chats.
- Trust: users in group chats see what looks like bot noise/spam.
- Silent: affected operators may not notice until a participant complains.
Workaround
Set agents.defaults.verboseDefault: "off" explicitly in config. This forces gate 2 to always return false regardless of the fallback-resolution bug:
{
"agents": {
"defaults": {
"verboseDefault": "off"
}
}
}
Not a proper fix — masks the root cause — but stops the leak immediately.
Suggested fix direction
- Audit
/app/dist/extensions/slack/prepare-BH5U3jEx.js and normalize all MPIM paths to set ChatType: "group".
- Re-check
shouldEmitVerboseProgress fallback when both sessionEntry.verboseLevel and agents.defaults.verboseDefault are unset — should default to "off", not "on".
- Consider adding a second hard gate in
maybeSendWorkingStatus that refuses to emit to any non-direct-message surface regardless of verbose state, to make this class of leak impossible.
Related
#50690 — "Prevent fake-progress messages with a runtime pre-send policy layer" (related policy layer idea)
#67199, #54919, #52537, #55790, #66607, #59416, #69440, #67888, #64830 — other thinkingDefault / session-default cascade issues (not this bug, but same class of "defaults silently ignored")
Screenshot
User-provided Slack screenshot of the leak is available on request (redacted for MPIM participants' names).
Summary
In 2026.4.22, the runtime-level "Working… / tool: … / tool args …" progress messages (normally hidden in group chats) are leaking into Slack group DMs (MPIMs) as real, user-visible messages. This exposes internal tool names and arguments (including fetched URLs and message/reaction targets) to group participants.
This happens even when no agent has
verboseDefaultset anywhere in config — implying the global fallback default forshouldEmitVerboseProgress()is effectively "on" for this surface, or the gate intended to suppress group delivery isn't firing.Environment
verbose*keys present anywhere;agents.defaults.thinkingDefault: "medium", per-agentthinkingDefault: "high"for main (not relevant to this bug)Repro
web_fetchthenmessage(react with emoji) and emitNO_REPLY.The bot's correct
NO_REPLYwas honored (no final reply), but the internal trace still shipped.Expected
No "Working…" or tool-trace messages should be emitted to Slack group chats (MPIM or channel). These are runtime diagnostics, not user-facing content.
Code analysis
Trace generator:
/app/dist/dispatch-BbwSt8e4.js:583-596(maybeSendWorkingStatus):Two gates:
shouldSendToolStartStatuses(line 482):Intent: suppress tool-start statuses in group chats unless it's a forum.
shouldEmitVerboseProgress()(line 218-229):With no session-level verbose set and config
verboseDefaultunset, fallback resolves to"off"via nullish coalescing, so this gate should returnfalse.Hypothesis on why both gates failed here:
Gate 1 (ChatType): Slack's ingress has two paths that set
ChatTypefor MPIMs differently:/app/dist/extensions/slack/prepare-BH5U3jEx.js:149-151:isGroup = channelType === "mpim"; chatType = isDirectMessage ? "direct" : isGroup ? "group" : "channel"— correct./app/dist/extensions/slack/prepare-BH5U3jEx.js:1261,1343:ChatType: isDirectMessage ? "direct" : "channel"— wrong for MPIMs (forces channel, loses the group distinction).If the second path fired for this turn,
shouldSendToolStartStatusesevaluates totrueand the trace is allowed through.Gate 2 (verbose): unclear how this returned
truegiven noverboseDefaultis set. Possibly a fallback resolution bug introduced in 2026.4.22, or a default changed somewhere. Haven't pinpointed.The two-gate design is correct; the implementation has at least one broken gate (MPIM ChatType branch inconsistency), and possibly a second (verbose fallback).
Impact
Workaround
Set
agents.defaults.verboseDefault: "off"explicitly in config. This forces gate 2 to always return false regardless of the fallback-resolution bug:{ "agents": { "defaults": { "verboseDefault": "off" } } }Not a proper fix — masks the root cause — but stops the leak immediately.
Suggested fix direction
/app/dist/extensions/slack/prepare-BH5U3jEx.jsand normalize all MPIM paths to setChatType: "group".shouldEmitVerboseProgressfallback when bothsessionEntry.verboseLevelandagents.defaults.verboseDefaultare unset — should default to"off", not"on".maybeSendWorkingStatusthat refuses to emit to any non-direct-message surface regardless of verbose state, to make this class of leak impossible.Related
#50690— "Prevent fake-progress messages with a runtime pre-send policy layer" (related policy layer idea)#67199,#54919,#52537,#55790,#66607,#59416,#69440,#67888,#64830— otherthinkingDefault/ session-default cascade issues (not this bug, but same class of "defaults silently ignored")Screenshot
User-provided Slack screenshot of the leak is available on request (redacted for MPIM participants' names).