openclaw - 💡(How to fix) Fix Bug: Text before tool calls is lost in Feishu streaming card reply mode

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…

When the model outputs text before invoking a tool call (stopReason=toolUse), the pre-tool text is silently discarded in Feishu streaming card reply mode. Only the final assistant reply (stopReason=stop) is visible to the user. This results in missing content in Feishu messages.

Root Cause

Root Cause Analysis

Fix Action

Fix / Workaround

Two independent dispatch systems

OpenClaw has two reply dispatch systems:

  1. ACP dispatch (dispatch-acp): Used for ACP sessions/subagents. Controlled by acp.stream.deliveryMode config ("live" | "final_only").
  2. Feishu card reply dispatcher: Used for Feishu DM/group messages. Uses replyMode=streaming with Feishu interactive cards. Not controlled by acp.stream.deliveryMode.

Code Example

feishu[default][msg:om_xxx]: reply mode resolved (effectiveReplyMode=auto, replyMode=streaming, chatType=p2p)
RAW_BUFFERClick to expand / collapse

Bug: Text before tool calls is lost in Feishu streaming card reply mode

Summary

When the model outputs text before invoking a tool call (stopReason=toolUse), the pre-tool text is silently discarded in Feishu streaming card reply mode. Only the final assistant reply (stopReason=stop) is visible to the user. This results in missing content in Feishu messages.

Environment

  • OpenClaw version: 2026.5.18 (installed via npm)
  • Channel: Feishu (primary affected channel)
  • Model: any model that outputs text before tool calls
  • Reply mode: streaming (default for Feishu p2p)

Steps to Reproduce

  1. Ask the assistant a question that requires tool use AND where the model outputs explanatory text before calling the tool, e.g.: "Query the weather, and detail the execution steps."
  2. The model produces an assistant reply with text like "Step 1... Step 2..." then stops with stopReason=toolUse to invoke a tool
  3. After the tool returns, the model produces a second assistant reply with the results, stopping with stopReason=stop
  4. Only the second reply text is visible in the Feishu message; the first reply text is lost

Expected Behavior

All text produced by the model across the entire turn (including text before tool calls) should be accumulated and delivered together in the final reply, or the streaming card should preserve previously rendered content when a new model invocation starts within the same turn.

Actual Behavior

The pre-tool text is rendered into the Feishu streaming card during the first model invocation. When the model stops with toolUse and a new invocation begins, the streaming card is overwritten with the new invocation content, discarding the previously rendered text. Only the post-tool text remains visible.

Root Cause Analysis

Two independent dispatch systems

OpenClaw has two reply dispatch systems:

  1. ACP dispatch (dispatch-acp): Used for ACP sessions/subagents. Controlled by acp.stream.deliveryMode config ("live" | "final_only").
  2. Feishu card reply dispatcher: Used for Feishu DM/group messages. Uses replyMode=streaming with Feishu interactive cards. Not controlled by acp.stream.deliveryMode.

Why acp.stream.deliveryMode=live does not fix this

Setting acp.stream.deliveryMode to "live" only affects the ACP dispatch path. Feishu messages go through the Feishu card reply dispatcher, which is a completely separate system. The acp.stream.deliveryMode config has no effect on Feishu streaming card behavior.

Evidence from gateway logs

Every Feishu message shows:

feishu[default][msg:om_xxx]: reply mode resolved (effectiveReplyMode=auto, replyMode=streaming, chatType=p2p)

This confirms Feishu uses replyMode=streaming, not ACP dispatch.

Evidence from session history

Session history shows two assistant messages in a single turn:

SeqRoleContentstopReason
153assistant"Step 1: Identify the task… Step 2: Select the tool… Step 3: Execute the query"toolUse
155assistant"Step 4: Analyze the data and organize the results…" + weather tablesstop

Only seq 155 content was visible in the Feishu card. Seq 153 text was rendered into the streaming card but then overwritten when the new model invocation started.

The overwrite mechanism

The Feishu streaming card reply dispatcher updates a single interactive card in-place as the model streams text. When the model stops with toolUse and a new invocation begins within the same turn, the dispatcher starts updating the same card with the new invocation output, replacing the previous content instead of appending to it.

Previously Incorrect Analysis

The initial version of this issue incorrectly attributed the bug to ACP dispatch final_only mode and resetTurnState() clearing finalOnlyOutputText. While that mechanism exists, it is not the cause for Feishu because Feishu does not use ACP dispatch for message delivery. The actual cause is the Feishu streaming card reply dispatcher overwriting previously rendered content when a new model invocation starts.

Suggested Fix

The Feishu streaming card reply dispatcher should preserve previously rendered content across model invocations within the same turn. Options:

  1. Accumulate text across invocations: Before starting a new streaming update for a subsequent model invocation, prepend the previously rendered text from earlier invocations in the same turn.
  2. Use a new card for each invocation: Instead of overwriting the same card, send a new card for each model invocation so all intermediate text is preserved as separate messages.
  3. Buffer until turn completion: Similar to final_only mode, buffer all text across invocations and only render the complete card when the turn finishes (stopReason=stop).

Workarounds

  • Model-side: Avoid outputting text before tool calls; only output all text in the final reply after all tool calls are complete. This is a behavioral workaround and depends on model compliance.
  • Disable streaming cards: If Feishu reply mode can be configured to non-streaming, this may preserve content (untested).

Impact

Any scenario where the model outputs explanatory text before invoking a tool will lose that text in Feishu. This includes:

  • Step-by-step explanations followed by tool calls
  • "Let me look that up…" style preambles before search/query tools
  • Any multi-step workflow with interleaved text and tool calls

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 - 💡(How to fix) Fix Bug: Text before tool calls is lost in Feishu streaming card reply mode