-
-
Notifications
You must be signed in to change notification settings - Fork 52.6k
Description
Summary
When reasoning/thinking is enabled (e.g. reasoningLevel: "on"), internal reasoning text is sent as user-visible replies through channel delivery (iMessage, etc.). Users see the model's chain-of-thought as actual messages.
Root Cause
Two code paths in dist/reply-DptDUVRg.js explicitly inject reasoning text into outbound reply payloads:
-
Streaming block-reply path (~line 54893-54900):
onBlockReply(the channel delivery callback) is called with formatted reasoning text. The conditionshouldEmitReasoninggates ononBlockReplybeing truthy — meaning reasoning is emitted specifically when a channel callback exists, which is backwards.// Before fix (line 54893): const shouldEmitReasoning = Boolean(ctx.state.includeReasoning && formattedReasoning && onBlockReply && ...) // onBlockReply is the channel delivery callback — this means reasoning only emits TO channels
-
Final payload builder (~line 56715-56716): Unconditionally appends reasoning text to
replyItemswhenreasoningLevel === "on":const reasoningText = params.lastAssistant && params.reasoningLevel === "on" ? formatReasoningMessage(...) : ""; if (reasoningText) replyItems.push({ text: reasoningText });
This
replyItemsarray feeds directly into channel delivery.
Suggested Fix
-
In the streaming path, emit reasoning through a separate
onReasoningStreamcallback (for logging/UI) instead ofonBlockReply(channel delivery). Invert theonBlockReplycondition so reasoning is suppressed when a channel callback is present. -
Remove the unconditional
reasoningTextpush from the final payload builder entirely — reasoning should not be appended to outbound reply items.
Environment
- OpenClaw v2026.2.9
- Any channel (iMessage confirmed, likely affects all channels)
- Reasoning/thinking must be enabled