Skip to content

fix: persist reasoningLevel 'off' instead of deleting it (#24406)#24559

Merged
steipete merged 1 commit intoopenclaw:mainfrom
echoVic:fix/reasoning-off-persisted
Feb 24, 2026
Merged

fix: persist reasoningLevel 'off' instead of deleting it (#24406)#24559
steipete merged 1 commit intoopenclaw:mainfrom
echoVic:fix/reasoning-off-persisted

Conversation

@echoVic
Copy link

@echoVic echoVic commented Feb 23, 2026

Problem

When a user runs /reasoning off, reasoning content continues to leak into channel messages (Telegram, Matrix, etc.). The WebUI correctly hides reasoning, but channel delivery paths still include it.

Reported in #24406 (Telegram, thinking=low) and #24411 (Matrix, /reasoning off).

Root Cause

In sessions-patch.ts (the WebSocket/API session patch path), when reasoningLevel is set to "off", the code deletes the field from the session entry instead of persisting it:

if (normalized === 'off') {
  delete next.reasoningLevel;  // ← field removed entirely
}

Later, in get-reply-directives.ts, the code checks whether reasoning was explicitly set:

const reasoningExplicitlySet =
  directives.reasoningLevel !== undefined ||
  (sessionEntry?.reasoningLevel !== undefined && sessionEntry?.reasoningLevel !== null);

Since the field was deleted (undefined), reasoningExplicitlySet is false. This triggers the auto-enable path:

if (!reasoningExplicitlySet && resolvedReasoningLevel === 'off' && !thinkingActive) {
  resolvedReasoningLevel = await modelState.resolveDefaultReasoningLevel();
}

For reasoning-capable models (Claude Opus, etc.), this re-enables reasoning — undoing the user's explicit /reasoning off.

Fix

Persist "off" explicitly instead of deleting the field, matching how directive-handling.persist.ts (the inline command path) already handles it correctly:

// Before (broken):
if (normalized === 'off') { delete next.reasoningLevel; }

// After (fixed):
next.reasoningLevel = normalized;  // persists 'off' explicitly

Testing

  • /reasoning offsessionEntry.reasoningLevel === 'off'reasoningExplicitlySet === true → no auto-enable
  • /reasoning on and /reasoning stream continue to work as before
  • null (reset) still deletes the field, allowing model defaults to apply

Fixes #24406
Fixes #24411

Greptile Summary

Fixed reasoning content leak in channel messages (Telegram, Matrix) by persisting reasoningLevel: "off" explicitly instead of deleting it. The previous implementation deleted the field when set to "off", causing get-reply-directives.ts:396-398 to treat it as unset and auto-enable reasoning for capable models (Claude Opus, etc.). The fix aligns with the existing pattern used by elevatedLevel (line 222) and directive-handling.persist.ts:93-95, ensuring the user's explicit /reasoning off command is respected across all delivery paths.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is a simple 3-line change that correctly aligns the implementation with existing patterns for similar fields (elevatedLevel on line 222 of the same file). The change matches the pattern already used in directive-handling.persist.ts:93-95, and the PR description provides clear root cause analysis with references to the specific logic that was broken. The fix ensures consistency across two code paths (WebSocket/API vs inline command) and prevents unintended re-enabling of reasoning.
  • No files require special attention

Last reviewed commit: d385867

)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411
Copy link
Contributor

@steipete steipete left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed for correctness and simpler alternatives; this is the best scoped change for the issue.

@steipete steipete merged commit 52ac763 into openclaw:main Feb 24, 2026
29 checks passed
sagarsaija pushed a commit to sagarsaija/openclaw that referenced this pull request Feb 24, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
plgs2005 pushed a commit to plgs2005/openclaw that referenced this pull request Feb 24, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
margulans pushed a commit to margulans/Neiron-AI-assistant that referenced this pull request Feb 25, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 26, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
(cherry picked from commit 52ac763)
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
(cherry picked from commit 52ac763)

# Conflicts:
#	src/gateway/sessions-patch.ts
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
) (openclaw#24559)

When a user runs /reasoning off, the session patch handler deleted
the reasoningLevel field from the session entry. This caused
get-reply-directives to treat reasoning as 'not explicitly set',
which triggered resolveDefaultReasoningLevel() to re-enable
reasoning for capable models (e.g. Claude Opus).

The fix persists 'off' explicitly, matching how directive-handling.persist.ts
already handles the inline /reasoning off command.

Fixes openclaw#24406
Fixes openclaw#24411

Co-authored-by: echoVic <AkiraVic@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Matrix chat session ignores reasoning setting and prints all reasoning messages regardless [Bug]: Reasoning content leaking to user messages

2 participants