Summary
Tool results (exec stdout/stderr, JSON dumps, command output) are delivered as individual Slack messages in channels even when config fully disables verbose/block streaming. Root cause: the shouldSendToolSummaries gate only treats ChatType === "group" as multi-user, but Slack channels arrive as ChatType === "channel".
Environment
- OpenClaw (npm global install at
/opt/homebrew/lib/node_modules/openclaw)
- Channel: Slack (
chat_type: "channel" per inbound meta)
- macOS 25.4.0 arm64, node v25.6.1
Config (verified correct)
{
"agents": {
"defaults": {
"verboseDefault": "off",
"blockStreamingBreak": "message_end"
}
},
"channels": {
"slack": {
"streaming": { "block": { "enabled": false } }
}
}
}
Observed
In a Slack channel (not DM, not group DM), each tool call posts its output as its own Slack message:
[16:42] Creating it now. ← assistant block reply
[16:42] Expecting value: line 1 column 1 (char 0) ← tool stderr
[16:42] (Command exited with code 1) ← exec wrapper
[16:42] {... full conversations.create JSON ...} ← tool stdout
[16:42] existing slack channels: [...] ← tool stdout
Block-reply streaming is already correctly disabled — that path works. The leak is on the tool-result path.
Root cause
dist/dispatch-JNo_iJw5.js:486:
const shouldSendToolSummaries = ctx.ChatType !== "group" || ctx.IsForum === true;
Slack channels set ctx.ChatType === "channel", so the expression evaluates true → resolveToolDeliveryPayload returns the raw payload → dispatcher.sendToolResult posts it to Slack. The same gate correctly suppresses for WhatsApp groups etc. (where ChatType === "group").
Proposed fix
Treat any multi-user context as suppressing tool summaries by default:
const shouldSendToolSummaries = (ctx.ChatType !== "group" && ctx.ChatType !== "channel") || ctx.IsForum === true;
Or more robustly, drive off an isMultiUser flag so new surfaces don't need the list extending.
Workaround
Patch the bundled dispatch-JNo_iJw5.js line 486 locally (script attached downstream). Idempotent re-apply needed after each OpenClaw update.
Impact
In shared Slack channels the assistant spams the channel with raw tool output — command failures, large JSON blobs, etc. — making it unusable for group work and risking leaking sensitive tool output to other channel members despite explicit config to suppress.
Summary
Tool results (exec stdout/stderr, JSON dumps, command output) are delivered as individual Slack messages in channels even when config fully disables verbose/block streaming. Root cause: the
shouldSendToolSummariesgate only treatsChatType === "group"as multi-user, but Slack channels arrive asChatType === "channel".Environment
/opt/homebrew/lib/node_modules/openclaw)chat_type: "channel"per inbound meta)Config (verified correct)
{ "agents": { "defaults": { "verboseDefault": "off", "blockStreamingBreak": "message_end" } }, "channels": { "slack": { "streaming": { "block": { "enabled": false } } } } }Observed
In a Slack channel (not DM, not group DM), each tool call posts its output as its own Slack message:
Block-reply streaming is already correctly disabled — that path works. The leak is on the tool-result path.
Root cause
dist/dispatch-JNo_iJw5.js:486:Slack channels set
ctx.ChatType === "channel", so the expression evaluatestrue→resolveToolDeliveryPayloadreturns the raw payload →dispatcher.sendToolResultposts it to Slack. The same gate correctly suppresses for WhatsApp groups etc. (whereChatType === "group").Proposed fix
Treat any multi-user context as suppressing tool summaries by default:
Or more robustly, drive off an
isMultiUserflag so new surfaces don't need the list extending.Workaround
Patch the bundled
dispatch-JNo_iJw5.jsline 486 locally (script attached downstream). Idempotent re-apply needed after each OpenClaw update.Impact
In shared Slack channels the assistant spams the channel with raw tool output — command failures, large JSON blobs, etc. — making it unusable for group work and risking leaking sensitive tool output to other channel members despite explicit config to suppress.