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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions