Skip to content

[Bug]: Reasoning/thinking content leaks to WhatsApp channel #24954

@sbmilburn

Description

@sbmilburn

Summary

Version: 2026.2.22-2
Platform: Linux x64, WhatsApp channel
Severity: High — exposes internal reasoning to end users

When thinkingDefault is set to "low" (or reasoning is enabled via /reasoning on), the model's internal reasoning/thinking content is sent as a separate message to the WhatsApp channel before the actual response. The runtime correctly reports Reasoning: on (hidden unless on/stream) but the "hidden" part isn't working — reasoning is delivered to the channel as a visible message.

Steps to reproduce

  1. Configure OpenClaw with thinkingDefault: "low" (or use /reasoning on)
  2. Send any message via WhatsApp
  3. Observe two messages returned: first the reasoning content, then the actual response

Expected behavior

Reasoning content should be suppressed from channel output. The runtime header says hidden unless on/stream, implying it should only be visible in the web UI or when explicitly streamed — not sent as a WhatsApp message.

Actual behavior

A separate message prefixed with Reasoning: (in italics) is sent to WhatsApp containing the model's internal chain-of-thought, followed by the actual response as a second message.

OpenClaw version

2026.2.22

Operating system

Ubuntu 24.04

Install method

npm

Logs, screenshots, and evidence

## Example Output (WhatsApp)

**Message 1 (should not be sent):**
> Reasoning:
> _Good, I'm all caught up. Now let me greet Shane. It's Monday, February 23, 2026, 1:15 PM. I'm using anthropic/claude-sonnet-4-6 (direct), which is the direct model..._
> _Quick rundown of what I know:_
> _- Active task: SwitchBitch training (paused, Phase 1 ready to go)_
> _- Blog "Viernes Writes" just launched today with first post "Static"_
> _..._

**Message 2 (correct response):**
> Hey Shane! Heads up — running on `anthropic/claude-sonnet-4-6` direct...

## Relevant Config


{
  "agents": {
    "defaults": {
      "model": {
        "primary": "openrouter/anthropic/claude-sonnet-4.6"
      }
    }
  }
}


No explicit `thinkingDefault` set in config (using runtime default). Runtime reports: `thinking=low`, `Reasoning: on (hidden unless on/stream)`.

There is no user-facing config key to suppress reasoning output for normal sessions (only `heartbeat.includeReasoning` exists for heartbeats). The suppression should be automatic for channel delivery.

## Log Evidence

### Leak #2 (3:11 PM PST / 23:11:45 UTC)

The run completes, then **two separate messages** are sent back-to-back within 5ms:


23:11:45.541Z info web-auto-reply  "text":"Reasoning:\n_Active task is the reasoning leak bug investigation. Shane did a /new to try to reproduce._"  auto-reply sent (text)
23:11:45.546Z info web-auto-reply  "text":"Hey Shane. Monday afternoon, 3:11 PM. You're on opus right now..."  auto-reply sent (text)


### Leak continues in same session (23:15:56 UTC)

Same pattern — reasoning emitted as first chunk, actual reply as second:


23:15:56.510Z info web-auto-reply  "text":"Reasoning:\n_So the reasoning leaked again on this /new session start. Let me update..._\n_Key observations:_\n_- Reproduced on opus-direct..."  auto-reply sent (text)
23:15:56.516Z info web-auto-reply  "text":"Confirmed reproducible. So the pattern is clear now..."  auto-reply sent (text)


**Key finding:** The `web-auto-reply` module treats reasoning content as a separate deliverable text chunk. Both chunks are sent via `auto-reply sent (text)` — no filtering of thinking blocks before they reach the outbound path. The reasoning chunk is prefixed with `"Reasoning:\n_"` and italicized, suggesting formatting is applied but suppression is not.

**Non-leaking responses** (tool-call-heavy, same session) produced only one `auto-reply sent (text)` per response — no reasoning chunk. The chunking/splitting logic appears to differ based on response structure.

Impact and severity

Affected: WhatsApp chats
Impact: annoying

Additional information

  • Affects both Sonnet (direct Anthropic) and Opus (direct Anthropic) — cross-model
  • Confirmed on WhatsApp channel; untested on other channels
  • /reasoning off is a potential workaround but loses extended thinking benefits
  • No user-facing config key to suppress reasoning for normal sessions (only heartbeat.includeReasoning for heartbeats)
  • Runtime reports thinking=low, Reasoning: on (hidden unless on/stream) — "hidden" is not being honored for channel delivery

Report of a similar issue (with few details) reported in #24605

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions