You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On OpenClaw 2026.5.3 with messages.groupChat.visibleReplies = "message_tool" (the schema-migration default applied by doctor --fix) and a Slack-backed agent (claude-cli/claude-opus-4-7), an assistant turn that produces thinking → text → end_turn with zero mcp__openclaw__message tool calls completes cleanly, persists the final text to the claude-cli transcript, and is silently dropped by the Slack delivery layer. From the user's perspective the agent goes silent in the Slack thread — indistinguishable from "still thinking" or "stuck".
The current contract is consistent with visibleReplies = "message_tool" as documented, but:
There is no log line in gateway.log indicating that delivery was suppressed. The failure is invisible without grepping the claude-cli per-session JSONL.
There is no runtime safety net (auto-promote, hard diagnostic, or fallback) when a group-chat turn closes without the required tool call.
The agent calls mcp__openclaw__message correctly on most turns (~5/6 on the affected agent during the observation window). The failure mode is concentrated on [thinking,text]-only turn shapes — typically meta-discussion or short conversational replies where the model doesn't reach for tools. This is the same turn shape called out as still-broken in open issue #66459.
Environment
OpenClaw: 2026.5.3 (verified via openclaw status → app 2026.5.3)
Runtime: Node v24.15.0, Linux 6.8.0-87-generic, Hetzner CPX32
Pre-existing thread in a Slack group channel where the agent has already replied successfully via mcp__openclaw__message earlier in the day.
User posts a meta question in the thread that doesn't naturally invite tool use (e.g. asking the agent how its scheduling/triggers work, or a short conversational follow-up).
Agent's claude-cli session enqueues the inbound message normally:
queue-operation enqueue → dequeue → user message → assistant turn
Assistant emits the turn as: one thinking content block (encrypted signature, ~1700 output tokens), then one text content block, then stop_reason: end_turn. No tool_use blocks.
The text content is persisted to ~/.claude/projects/<cwd-mangled>/<sessionId>.jsonl.
No corresponding outbound entry appears in the OpenClaw delivery-mirror file ~/.openclaw/agents/<agent>/sessions/<sessionId>-topic-<thread_ts>.jsonl.
No chat.postMessage / Slack API send appears in journalctl --user -u openclaw-gateway.service for that channel ID in the relevant window.
No warning, error, or diagnostic log line is emitted indicating that delivery was suppressed.
Slack thread shows the user's message and nothing after.
Evidence — observed turn shape
Successful prior turn in the same session, same thread (mcp__openclaw__message was called):
Same requestId and msg_id on both thinking and text entries — this is one Anthropic API response, split into two transcript records as streaming chunks landed. The turn is structurally complete and clean.
Delivery-mirror file for the affected thread (last entry far predates the failed turn):
~/.openclaw/agents/podavach-shopify/sessions/aa828b52-167b-41e8-b6de-ff2e8970ee75-topic-1777885573.897639.jsonl
last entry: 2026-05-04T09:47:03.096Z (~2.5h before failed turn)
Gateway journal for the channel ID during 12:19:00 – 12:35:00 window:
These fire then [diagnostic] stuck session recovery skipped: reason=active_reply_work action=keep_lane — the gateway sees that work is in progress and stays out of the way, which is the right thing to do. But when the work finishes with no tool call, nothing fills the gap.
What it is NOT
Not a stale-binary trap ([Bug]: Telegram forum topic final replies generated but not delivered on 2026.5.2 #76554's correction).openclaw status self-reports app 2026.5.3, MainPID 116231 was started post-upgrade at 2026-05-04 10:06:53 UTC, the npm package on disk is openclaw@2026.5.3. Verified with ps -o etime,start,cmd against the systemd MainPID. The systemd unit Description=OpenClaw Gateway (v2026.5.2) is a stale cosmetic label in the unit file; the running binary is ~/.nvm/versions/node/v24.15.0/lib/node_modules/openclaw/dist/index.js and is 5.3.
Not an auth / billing / model fallback issue. Other turns in the same session before and after the failed turn delivered correctly via mcp__openclaw__message. Provider/auth healthy.
Not a streaming.mode regression. Slack streaming is null on the affected account (no streaming configured); failure is in the final delivery path, not partial-stream coalescing.
Expected behavior
When a group-chat turn closes under messages.groupChat.visibleReplies = "message_tool" with zero mcp__openclaw__message tool calls AND a non-empty final text content block, the runtime should do at least one of:
(a) Auto-promote on turn-end. Detect this turn shape and dispatch the final assistant text block to the originating chat using the channel's natural delivery path (same path DMs use). Preserves operator intent (model is still encouraged to call the tool) without dropping the reply.
(b) Hard diagnostic. Emit a gateway-log line at warn or error level:
[stream] turn closed with 0 message-tool emissions in group chat;
visibleReplies=message_tool suppressed N text chunks
sessionId=<id> sessionKey=<key> requestId=<req>
So operators can grep the failure rather than discovering it days later in a user complaint. Currently the failure is utterly silent in the gateway log; we had to grep mcp__openclaw__messagetool_use entries against assistant text entries in the per-session claude-cli JSONL to find it.
(c) Per-channel/runtime hint surfaced to the agent. For sessions destined to group-chat threads under visibleReplies = "message_tool", attach a system-prompt hint like requiredDeliverySurface: "tool:mcp__openclaw__message" so the agent does not have to relearn the contract on every turn.
Today the runtime appears to do none of these.
Suggested fix direction
In order of operator-utility-per-engineering-cost:
Hard diagnostic (cheapest, highest debugging-value). One log line whenever a group-chat turn closes with zero mcp__openclaw__message tool calls under visibleReplies = "message_tool". No behavior change, just observability. Solves the "silently lost reply" UX class even before any auto-promote work.
Per-account opt-in fallback modevisibleReplies = "message_tool_or_last_text" so operators can opt into the safety net without giving up the explicit-tool default fleet-wide.
Related issues
[Bug]: Telegram forum topic final replies generated but not delivered on 2026.5.2 #76554 — Telegram forum topic final replies generated but not delivered on 2026.5.2. Closed (after the 5.2-vs-5.3 stale-binary correction). Same family on Telegram. Workaround D ("agent calls message(action=send) directly") is the explicit Telegram analog of the dance Slack agents must do under visibleReplies = "message_tool".
Reproduced on a real workload, not a synthetic test. Single agent across a Slack channel migration cohort. Not yet swept across the other 6 agents on the same host but the schema migration applied identically across all 7.
Reproduces on [thinking,text]-only turn shapes; cannot trivially force the model into this shape, so a deterministic minimal repro is not yet attached. Happy to capture more transcripts if useful.
Workspaces use claude-cli SDK sessions; an OpenAI-Codex / native-Anthropic provider was not tested for this surface in 5.3.
Summary
On OpenClaw
2026.5.3withmessages.groupChat.visibleReplies = "message_tool"(the schema-migration default applied bydoctor --fix) and a Slack-backed agent (claude-cli/claude-opus-4-7), an assistant turn that producesthinking → text → end_turnwith zeromcp__openclaw__messagetool calls completes cleanly, persists the final text to the claude-cli transcript, and is silently dropped by the Slack delivery layer. From the user's perspective the agent goes silent in the Slack thread — indistinguishable from "still thinking" or "stuck".The current contract is consistent with
visibleReplies = "message_tool"as documented, but:gateway.logindicating that delivery was suppressed. The failure is invisible without grepping the claude-cli per-session JSONL.The agent calls
mcp__openclaw__messagecorrectly on most turns (~5/6 on the affected agent during the observation window). The failure mode is concentrated on[thinking,text]-only turn shapes — typically meta-discussion or short conversational replies where the model doesn't reach for tools. This is the same turn shape called out as still-broken in open issue #66459.Environment
2026.5.3(verified viaopenclaw status→app 2026.5.3)v24.15.0, Linux6.8.0-87-generic, Hetzner CPX32T9FGQDB9D, group channelC0B0XQ03ZN3(is_group_chat: true), thread replyclaude-cli/claude-opus-4-7(claude-cliv2.1.116/ claude-cli session metadata reportsversion 2.1.126for the inner SDK)podavach-shopify{ "messages": { "groupChat": { "visibleReplies": "message_tool" } }, "channels": { "slack": { "accounts": { "podavach-shopify": { "dm": { "enabled": true, "groupEnabled": true }, "replyToMode": "off", "replyToModeByChatType": { "direct": "...", "group": "...", "channel": "..." }, "requireMention": true, "streaming": null } } } } }Reproduction
Pre-existing thread in a Slack group channel where the agent has already replied successfully via
mcp__openclaw__messageearlier in the day.thinkingcontent block (encrypted signature, ~1700 output tokens), then onetextcontent block, thenstop_reason: end_turn. Notool_useblocks.textcontent is persisted to~/.claude/projects/<cwd-mangled>/<sessionId>.jsonl.~/.openclaw/agents/<agent>/sessions/<sessionId>-topic-<thread_ts>.jsonl.chat.postMessage/ Slack API send appears injournalctl --user -u openclaw-gateway.servicefor that channel ID in the relevant window.Evidence — observed turn shape
Successful prior turn in the same session, same thread (
mcp__openclaw__messagewas called):Failed turn ~3 minutes later in the same session, same thread (no tool call):
Same
requestIdandmsg_idon boththinkingandtextentries — this is one Anthropic API response, split into two transcript records as streaming chunks landed. The turn is structurally complete and clean.Delivery-mirror file for the affected thread (last entry far predates the failed turn):
Gateway journal for the channel ID during 12:19:00 – 12:35:00 window:
Recurring stuck-session diagnostics earlier in the day on the same thread (different sessions / earlier turns) suggest this is not a one-off:
These fire then
[diagnostic] stuck session recovery skipped: reason=active_reply_work action=keep_lane— the gateway sees that work is in progress and stays out of the way, which is the right thing to do. But when the work finishes with no tool call, nothing fills the gap.What it is NOT
openclaw statusself-reportsapp 2026.5.3, MainPID 116231 was started post-upgrade at2026-05-04 10:06:53 UTC, the npm package on disk isopenclaw@2026.5.3. Verified withps -o etime,start,cmdagainst the systemd MainPID. The systemd unitDescription=OpenClaw Gateway (v2026.5.2)is a stale cosmetic label in the unit file; the running binary is~/.nvm/versions/node/v24.15.0/lib/node_modules/openclaw/dist/index.jsand is 5.3.stop_reason: end_turn, no streaming abort, no proxy in the path (claude-cli direct).isError=false, noACP_TURN_FAILED/AcpRuntimeError.final_onlydeliveryMode issue ([Bug]: deliveryMode="final_only" silently drops long tool-loop replies when no phase=final chunk is emitted #76828).acp.stream.deliveryModeis unset; the relevant gate ismessages.groupChat.visibleReplies, notacp.stream.deliveryMode.mcp__openclaw__message. Provider/auth healthy.streaming.moderegression. Slackstreamingis null on the affected account (no streaming configured); failure is in the final delivery path, not partial-stream coalescing.Expected behavior
When a group-chat turn closes under
messages.groupChat.visibleReplies = "message_tool"with zeromcp__openclaw__messagetool calls AND a non-empty final text content block, the runtime should do at least one of:(a) Auto-promote on turn-end. Detect this turn shape and dispatch the final assistant text block to the originating chat using the channel's natural delivery path (same path DMs use). Preserves operator intent (model is still encouraged to call the tool) without dropping the reply.
(b) Hard diagnostic. Emit a gateway-log line at warn or error level:
So operators can grep the failure rather than discovering it days later in a user complaint. Currently the failure is utterly silent in the gateway log; we had to grep
mcp__openclaw__messagetool_useentries againstassistant textentries in the per-session claude-cli JSONL to find it.(c) Per-channel/runtime hint surfaced to the agent. For sessions destined to group-chat threads under
visibleReplies = "message_tool", attach a system-prompt hint likerequiredDeliverySurface: "tool:mcp__openclaw__message"so the agent does not have to relearn the contract on every turn.Today the runtime appears to do none of these.
Suggested fix direction
In order of operator-utility-per-engineering-cost:
mcp__openclaw__messagetool calls undervisibleReplies = "message_tool". No behavior change, just observability. Solves the "silently lost reply" UX class even before any auto-promote work.visibleReplies = "message_tool". Mirrors the suggested fix in [Bug]: deliveryMode="final_only" silently drops long tool-loop replies when no phase=final chunk is emitted #76828 (auto-promote-last-commentary onfinal_only). Preserves the explicit-tool ergonomic for normal flows; covers the long tail of[thinking,text]-only meta turns.visibleReplies = "message_tool_or_last_text"so operators can opt into the safety net without giving up the explicit-tool default fleet-wide.Related issues
message(action=send)directly") is the explicit Telegram analog of the dance Slack agents must do undervisibleReplies = "message_tool".deliveryMode="final_only"silently drops long tool-loop replies when nophase=finalchunk emitted. Closed. Adjacent code path; suggested fix direction (auto-promote-last-commentary, hard diagnostic) generalizes cleanly to this issue.[thinking,text]turn on 2026.4.11. Open. Same turn shape as this report. The Telegram-side observation is the precise structural match.messagetoolaccountIdto the calling agent's own Slack account when omitted #73619 — DefaultmessagetoolaccountIdto the calling agent's own Slack account when omitted. Open. Reduces the cost of relying on explicit-tool delivery, complementary to (a) above.Notes / scope
[thinking,text]-only turn shapes; cannot trivially force the model into this shape, so a deterministic minimal repro is not yet attached. Happy to capture more transcripts if useful.