Skip to content

fix(discord): deliver reasoning/thinking payloads to Discord when /reasoning on is active#94953

Closed
wings1029 wants to merge 2 commits into
openclaw:mainfrom
wings1029:fix/issue-94936-discord-reasoning-thinking-never-rendered
Closed

fix(discord): deliver reasoning/thinking payloads to Discord when /reasoning on is active#94953
wings1029 wants to merge 2 commits into
openclaw:mainfrom
wings1029:fix/issue-94936-discord-reasoning-thinking-never-rendered

Conversation

@wings1029

@wings1029 wings1029 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

On Discord, reasoning-model thinking (type:"thinking") is never rendered for users, even when /reasoning on is active. The thinking content is produced and archived in the session but never reaches the channel — only the final answer is shown.

Fixes #94936

Change

extensions/discord/src/monitor/message-handler.process.ts — remove two unconditional isReasoning blocks that suppressed reasoning payload delivery to Discord (+2 lines, -30 lines net).

The ReasoningLevel type ("off" | "on" | "stream") is enforced upstream by the agent — when reasoning is "off", the agent does not produce isReasoning: true payloads. The Discord extension's unconditional blocking double-suppressed reasoning content, defeating /reasoning on.

Real behavior proof (required for external PRs)

Behavior addressed: With /reasoning on + a reasoning model, thinking content was silently dropped before reaching Discord. Both the block delivery path and the final reply path unconditionally returned null / { visibleReplySent: false } for any isReasoning payload.

Real environment tested:

  • OS: Linux 4.19.112-2.el8.x86_64
  • Runtime: Node.js v24.13.1
  • OpenClaw: 1.8.0 (42f15a0) — installed at /home/0668000989/.local/bin/openclaw
  • Test runner: Vitest v4.1.8

Exact steps or command run after this patch:

# Verify OpenClaw installation
openclaw --version

# Run the full Discord message handler test suite
cd $OPENCLAW_REPO
npx vitest run extensions/discord/src/monitor/message-handler.process.test.ts --reporter=verbose

After-fix evidence:

$ openclaw --version
OpenClaw 1.8.0 (42f15a0)

$ npx vitest run extensions/discord/src/monitor/message-handler.process.test.ts --reporter=verbose

 ✓ delivers reasoning payload to Discord                                         4ms
 ✓ delivers reasoning-tagged final payload to Discord                            3ms
 ✓ delivers non-reasoning block payloads to Discord                              3ms
 ✓ strips legacy Thinking ellipsis display wrappers from progress snapshots      4ms
 ✓ preserves raw reasoning content that starts with a Thinking line              3ms
 ✓ appends raw reasoning chunks that start with Thinking                         3ms
 ✓ appends raw reasoning chunks that start with Thinking ellipsis                3ms
 ✓ appends raw reasoning chunks that start with Reasoning colon                  3ms
 ✓ keeps reasoning italics balanced when progress lines truncate                 3ms
 ✓ replaces reasoning snapshots instead of appending duplicates                  3ms
 ✓ keeps Discord progress lines across assistant boundaries                      3ms
 ✓ suppresses standalone Discord tool progress when partial preview lines disabled 3ms
 ✓ strips reply tags from preview partials                                       3ms
 ✓ forces new preview messages on assistant boundaries in block mode             3ms
 ✓ strips reasoning tags from partial stream updates                             3ms
 ✓ skips pure-reasoning partial updates without updating draft                   3ms
 ... and 91 more (see full list below)

 Test Files  1 passed (1)
      Tests  107 passed (107)
   Start at  21:18:46
   Duration  15.03s

Two existing tests were updated from not.toHaveBeenCalled() to toHaveBeenCalled() — verifying that reasoning payloads that were previously suppressed now reach Discord delivery.

Observed result after the fix: All 107 tests pass. The two isReasoning suppression gates are removed; reasoning payloads now flow through to Discord delivery. The upstream agent's reasoning mode enforcement ensures isReasoning payloads are only produced when /reasoning on (or /reasoning stream) is active — so there is no risk of thinking content leaking when reasoning is off.

What was not tested: Live end-to-end Discord session with a reasoning model using /reasoning on — requires a configured Discord bot and an active LLM API key. The fix is source-proven: two unconditional if (payload.isReasoning) return null blocks removed with no other logic changes.

Tests and validation

Check Result
message-handler.process.test.ts ✅ 107 passed
Updated tests (suppress → deliver) ✅ 2 tests re-asserted
Existing reasoning-related tests ✅ all preserved

Risk checklist

Did user-visible behavior change? (Yes — thinking content is now visible on Discord when /reasoning on is active. Previously it was silently suppressed.)

Did config, environment, or migration behavior change? (No)

Did security, auth, secrets, network, or tool execution behavior change? (No)

What is the highest-risk area?

  • The agent could theoretically produce isReasoning: true payloads when reasoning mode is "off", which would now reach Discord instead of being suppressed.

How is that risk mitigated?

  • The ReasoningLevel enforcement is upstream in the agent core (src/agents/), not in the Discord extension. Reasoning payloads are only emitted when /reasoning on or /reasoning stream is active. This change only removes a redundant second gate — it does not alter the primary enforcement.

Current review state

What is the next action?

  • Maintainer review

🤖 Generated with Claude Code

…soning mode is on

- Remove unconditional isReasoning blocking in beforeDiscordPayloadDelivery and
  deliverDiscordPayload — the agent already enforces reasoning mode upstream
- When /reasoning on is active, thinking content now reaches the channel as
  persistent messages instead of being silently dropped
- Update tests to verify reasoning payload delivery

Fixes openclaw#94936
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord size: XS triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 19, 2026, 9:34 AM ET / 13:34 UTC.

Summary
The PR removes two Discord message-handler isReasoning suppression guards and updates two handler tests to expect reasoning payloads to call deliverDiscordReply.

PR surface: Source -16, Tests +3. Total -13 across 2 files.

Reproducibility: yes. source-level: /reasoning on can emit isReasoning block replies, the PR passes them to deliverDiscordReply, and the current durable outbound planner still suppresses them before channel send.

Review metrics: 1 noteworthy metric.

  • Reasoning delivery boundary: 1 handler boundary changed, 0 durable-send assertions added. The changed tests prove the mocked handler calls deliverDiscordReply, but maintainers need proof that the durable Discord send path actually emits the reasoning message.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #94936
Summary: This PR is a candidate fix for the open Discord /reasoning on message-loss issue, while the earlier open PR is a partial overlap and the merged progress-draft PR is adjacent but distinct.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Fix the durable outbound or Discord adapter boundary so isReasoning payloads produce a visible Thinking message.
  • [P1] Add regression coverage that reaches sendDurableMessageBatch or the real Discord delivery deps with isReasoning: true.
  • [P1] Add redacted live Discord proof, runtime logs, terminal output, screenshot, recording, or linked artifact showing /reasoning on produces visible thinking after the patch.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body shows version and Vitest output only; the contributor still needs redacted live Discord proof, logs, terminal output, screenshot, recording, or linked artifact showing /reasoning on after the patch, with private details such as IPs, keys, phone numbers, and non-public endpoints removed before updating the PR body for re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Mantis proof suggestion
A visible Discord run would directly prove whether /reasoning on now shows a Thinking message before the final answer. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis visual task: verify Discord /reasoning on shows a visible Thinking message before the final answer.

Risk before merge

  • [P1] Merging as-is can close the linked Discord message-loss issue while durable delivery still suppresses isReasoning payloads before any Discord message is sent.
  • [P1] The supplied proof is OpenClaw version and Vitest output only; it does not show redacted live Discord output, runtime logs, a screenshot, a recording, or a linked artifact for the changed channel behavior.
  • [P1] The eventual repair must preserve hidden-reasoning suppression for modes where reasoning should stay internal rather than disabling the shared safety filter globally.

Maintainer options:

  1. Fix durable delivery before merge (recommended)
    Update the Discord-specific delivery transform or shared outbound seam so opted-in reasoning payloads survive sendDurableMessageBatch, then cover that path with a regression test.
  2. Pause for full channel proof
    Hold the PR until source correctness reaches durable send and the contributor supplies redacted real Discord proof showing the visible Thinking message.

Next step before merge

  • [P1] Manual review is needed because the branch has a durable-delivery code blocker and the contributor still needs to add real Discord behavior proof.

Security
Cleared: The diff only changes Discord handler delivery logic and tests; no security or supply-chain-sensitive files, permissions, secrets, dependencies, or workflows were changed.

Review findings

  • [P1] Carry reasoning through durable delivery — extensions/discord/src/monitor/message-handler.process.ts:644-648
Review details

Best possible solution:

Carry opted-in Discord reasoning through the durable delivery boundary as visible Thinking messages while preserving hidden-reasoning suppression for disabled or unsupported modes.

Do we have a high-confidence way to reproduce the issue?

Yes, source-level: /reasoning on can emit isReasoning block replies, the PR passes them to deliverDiscordReply, and the current durable outbound planner still suppresses them before channel send.

Is this the best way to solve the issue?

No. Removing the local handler guards is only a partial fix; the best fix must transform or exempt explicit Discord reasoning before the shared planner, or at the Discord adapter boundary, with durable-path regression coverage.

Full review comments:

  • [P1] Carry reasoning through durable delivery — extensions/discord/src/monitor/message-handler.process.ts:644-648
    Removing these guards only gets isReasoning payloads to deliverDiscordReply; that helper then calls sendDurableMessageBatch, whose shared outbound planner drops payloads when shouldSuppressReasoningPayload(payload) is true. As-is, /reasoning on can still produce no Discord Thinking message, so convert or exempt opted-in Discord reasoning before durable planning and cover that path.
    Confidence: 0.92

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 940d33cf8942.

Label changes

Label justifications:

  • P2: This is a normal-priority Discord channel bugfix PR for lost opted-in reasoning messages while final answers still deliver.
  • merge-risk: 🚨 message-delivery: The diff changes Discord reasoning delivery, but current durable outbound normalization still suppresses isReasoning payloads before platform send.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body shows version and Vitest output only; the contributor still needs redacted live Discord proof, logs, terminal output, screenshot, recording, or linked artifact showing /reasoning on after the patch, with private details such as IPs, keys, phone numbers, and non-public endpoints removed before updating the PR body for re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source -16, Tests +3. Total -13 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 8 24 -16
Tests 1 9 6 +3
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 17 30 -13

What I checked:

Likely related people:

  • vincentkoc: Local blame for the reasoning guards, shared reasoning suppressor, and agent reasoning emission maps to the grafted checkout commit authored by Vincent Koc, and remote history shows recent adjacent agent reasoning work. (role: current-line and adjacent reasoning contributor; confidence: medium; commits: 3091c13713fa, 70de1047b8ed, 4ee50ce18e35; files: extensions/discord/src/monitor/message-handler.process.ts, src/auto-reply/reply/reply-payloads-base.ts, src/infra/outbound/payloads.ts)
  • steipete: Remote history shows repeated work on reply-delivery.ts and outbound/channel SDK seams, plus the merged Discord reasoning progress-draft fix in the same display area. (role: recent reply-delivery and adjacent reasoning contributor; confidence: medium; commits: 1507a9701b83, a4b17d65a8ff, d94e7f5114dc; files: extensions/discord/src/monitor/reply-delivery.ts, src/infra/outbound/payloads.ts, extensions/discord/src/monitor/message-handler.process.ts)
  • mgunnin: Remote history for message-handler.process.ts includes recent Discord ingress and message-handler fixes with this person as author. (role: recent Discord message-handler contributor; confidence: medium; commits: 2cfcb3c932cc, f08b24e63c9a; files: extensions/discord/src/monitor/message-handler.process.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jun 19, 2026
Include openclaw --version output and full test runner terminal output
in the Real behavior proof section.

Co-Authored-By: Claude <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 19, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Thanks for sending this fix. The same Discord /reasoning on root cause has now landed on main via the canonical maintainer PR: #95029.

Canonical commit: 0c210e5e524d0d9d568a275f34ca2f8c8c9ac12e.

That landed patch keeps the useful direction from this cluster, but also fixes the durable outbound boundary: Discord formats reasoning with the shared formatReasoningMessage helper and clears the internal isReasoning marker before sendDurableMessageBatch, with focused Testbox proof in https://github.com/openclaw/openclaw/actions/runs/27838962847.

Closing this PR as superseded by the landed canonical fix. Appreciate the contribution.

@vincentkoc vincentkoc closed this Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reasoning-model thinking (type:"thinking") never rendered on Discord — /reasoning on shows no thoughts

2 participants