openclaw - ✅(Solved) Fix bug(reply-runtime): /reasoning on can lose final answer after block replies [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58627Fetched 2026-04-08 01:59:59
View on GitHub
Comments
1
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
referenced ×2cross-referenced ×1

There appears to be a reply-runtime assembly bug in /reasoning on mode.

Current evidence shows that /reasoning on and /reasoning stream do not follow the same effective message path:

  • /reasoning stream works as expected in current testing
  • /reasoning on can lose the final assistant answer on some channels
  • the session transcript still contains the final assistant text
  • but the channel-delivered final payload does not

This is most visible on DingTalk AI card delivery. Telegram appears unaffected in current testing, which suggests this is not a universal channel failure but a runtime assembly/contract issue with channel-specific exposure.

Root Cause

There appears to be a reply-runtime assembly bug in /reasoning on mode.

Current evidence shows that /reasoning on and /reasoning stream do not follow the same effective message path:

  • /reasoning stream works as expected in current testing
  • /reasoning on can lose the final assistant answer on some channels
  • the session transcript still contains the final assistant text
  • but the channel-delivered final payload does not

This is most visible on DingTalk AI card delivery. Telegram appears unaffected in current testing, which suggests this is not a universal channel failure but a runtime assembly/contract issue with channel-specific exposure.

Fix Action

Fixed

PR fix notes

PR #58650: fix(reply-runtime): preserve final answer in /reasoning on with block replies

Description (problem / solution / changelog)

Summary

  • When /reasoning on is active and the channel registers onBlockReply (e.g. DingTalk AI cards), the final assistant answer could be lost in the assembled reply payload
  • Root cause: finalizeAssistantTexts skips both branches when includeReasoning + onBlockReply + addedDuringMessage are all true, leaving assistantTexts with only earlier block-reply content. buildEmbeddedRunPayloads then ignores fallbackAnswerText because assistantTexts is non-empty
  • Fix: in buildEmbeddedRunPayloads, when reasoningLevel === "on" and assistantTexts does not already contain the final answer (compared via normalizeTextForComparison), append fallbackAnswerText to the answer sources

Test plan

  • New test: includes fallback answer when reasoning is on and assistantTexts has earlier content — verifies the core bug fix
  • New test: does not duplicate when assistantTexts already contains the final answer — verifies deduplication
  • New test: does not append fallback when reasoning is off — verifies no impact on non-reasoning modes
  • All existing payloads tests pass (41 tests)
  • All previously passing subscribe tests remain green
  • Manual verification on DingTalk AI card channel with /reasoning on

Closes #58627

Changed files

  • src/agents/pi-embedded-runner/run.ts (modified, +1/-0)
  • src/agents/pi-embedded-runner/run/attempt.ts (modified, +60/-58)
  • src/agents/pi-embedded-runner/run/payloads.test.ts (modified, +134/-0)
  • src/agents/pi-embedded-runner/run/payloads.ts (modified, +34/-2)
  • src/agents/pi-embedded-runner/run/types.ts (modified, +3/-0)
  • src/agents/pi-embedded-subscribe.ts (modified, +1/-0)
RAW_BUFFERClick to expand / collapse

Summary

There appears to be a reply-runtime assembly bug in /reasoning on mode.

Current evidence shows that /reasoning on and /reasoning stream do not follow the same effective message path:

  • /reasoning stream works as expected in current testing
  • /reasoning on can lose the final assistant answer on some channels
  • the session transcript still contains the final assistant text
  • but the channel-delivered final payload does not

This is most visible on DingTalk AI card delivery. Telegram appears unaffected in current testing, which suggests this is not a universal channel failure but a runtime assembly/contract issue with channel-specific exposure.

Message-path difference

/reasoning on

Reasoning is included in the normal block/final assembly path.

In src/agents/pi-embedded-subscribe.ts, finalizeAssistantTexts(...) only forces final text into assistantTexts in limited cases:

  • when state.includeReasoning && text && !params.onBlockReply
  • or when !addedDuringMessage && !chunkerHasBuffered && text

So if /reasoning on emits block replies earlier in the same assistant message, the final assistant text may never be inserted into assistantTexts.

Later, in src/agents/pi-embedded-runner/run/payloads.ts, buildEmbeddedRunPayloads(...) prefers assistantTexts over fallbackAnswerText derived from lastAssistant:

  • if assistantTexts.length > 0, those are used
  • lastAssistant.text is only used as fallback when assistantTexts is empty

That means the transcript can contain the correct final assistant answer, while the assembled reply payload still omits it.

/reasoning stream

Reasoning is streamed separately through onReasoningStream, so the final answer path is less likely to be shadowed by earlier block-reply state.

Telegram also has channel-side draft/preview lanes that seem to compensate for this class of problem, which likely explains why it behaves correctly while DingTalk card exposes the bug.

Why this is a bug

The runtime transcript and the final delivered reply can diverge:

  • transcript: contains reasoning + final assistant text
  • assembled payload: may contain only reasoning/tool/interstitial text
  • channel: receives an incomplete final reply

This breaks channels that rely primarily on the assembled final payload rather than separate preview/draft lanes.

Scope / impact

This does not appear to affect all channels equally.

  • Observed broken: DingTalk AI card
  • Observed OK: Telegram
  • Likely at risk: channels that depend on final assembled payloads instead of partial/draft lane recovery

Related issues/PRs suggest this is part of a broader family of reasoning/block/final-delivery inconsistencies:

  • #30804
  • #51132
  • #29678
  • #43885
  • #57984

Suggested fixes

Option 1: fix finalizeAssistantTexts(...)

Ensure the final assistant text is preserved for the current turn even if block replies were already emitted earlier in that same assistant message.

Option 2: fix buildEmbeddedRunPayloads(...)

Do not assume assistantTexts.length > 0 means the final answer is already represented. If lastAssistant.text exists but assistantTexts only contain earlier block-derived or interstitial content, merge or replace with the final assistant text.

Option 3: tighten runtime contract

Guarantee that the assembled final payload always includes the final assistant answer, regardless of whether reasoning/tool block replies were emitted earlier in the turn.

Notes

This issue is specifically about /reasoning on. Current evidence indicates /reasoning stream follows a different effective path and is not affected in the same way.

extent analysis

TL;DR

The most likely fix involves modifying finalizeAssistantTexts or buildEmbeddedRunPayloads to ensure the final assistant text is included in the assembled reply payload when /reasoning on is used.

Guidance

  • Review the conditions in finalizeAssistantTexts to ensure the final assistant text is always inserted into assistantTexts, even when block replies are emitted earlier in the same assistant message.
  • Consider modifying buildEmbeddedRunPayloads to merge or replace assistantTexts with lastAssistant.text if the final answer is not already represented.
  • Verify the fix by testing the assembled reply payload on affected channels, such as DingTalk AI card, to ensure it includes the final assistant answer.
  • Check related issues/PRs (#30804, #51132, #29678, #43885, #57984) for potential insights into broader reasoning/block/final-delivery inconsistencies.

Example

No specific code snippet is provided, but the suggested fixes involve modifying the finalizeAssistantTexts and buildEmbeddedRunPayloads functions to handle the final assistant text correctly.

Notes

The issue appears to be specific to /reasoning on and may not affect all channels equally, with Telegram seemingly unaffected due to its channel-side draft/preview lanes.

Recommendation

Apply a workaround by modifying finalizeAssistantTexts or buildEmbeddedRunPayloads to ensure the final assistant text is included in the assembled reply payload, as this is a more targeted fix than upgrading to a potentially non-existent fixed version.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix bug(reply-runtime): /reasoning on can lose final answer after block replies [1 pull requests, 1 comments, 1 participants]