#Gateway v4 / OpenClaw update: chat transcript streaming arrives only after run completion

1 messages · Page 1 of 1 (latest)

lusty ore
#

After updating OpenClaw, My custom dashboard's chat no longer receives the same live transcript stream it used to get during assistant runs. While a run is active, the UI mostly sees generic working/thinking/status activity, but not the actual ordered transcript rows. Tool calls, tool results, assistant messages, and thinking/working details appear correctly only after the assistant finishes and history is refreshed.

Expected behavior is the old behavior: during a run, the client receives live ordered events for assistant deltas/thinking, tool call start, tool result/output, and visible assistant/message-tool replies, so each appears as its own row/bubble in real time. Current behavior feels like Gateway/runtime events are not carrying or emitting the full transcript payload live anymore, or the required Gateway v4 subscription/event names changed. Sessions and Agents live feeds show similar delayed/stale activity symptoms.

Openclaw control ui has the same issue.

If you want to see my implementaion I can share a github repo.

frank willowBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

delicate flowerBOT
# lusty ore After updating OpenClaw, My custom dashboard's chat no longer receives the same...

Rajohan, since the built-in Control UI shows the same delayed/stale stream, I’d treat this as likely upstream rather than a bug in your dashboard.

Please grab the version first:

openclaw --version
openclaw status --all

For current Gateway WS behavior, the relevant live surfaces are:

  • chat.send returns immediately with { runId, status: "started" }, then assistant partial/final output comes on chat events.
  • Session-level transcript/tool subscribers use sessions.subscribe and/or sessions.messages.subscribe { key } and receive session.message, session.tool, and sessions.changed events.
  • These content-bearing frames require operator.read; without it you can still see generic status/transport activity but not session content.

That said, your symptom is stronger than a client subscription mismatch because Control UI is affected too. I’d file this as a GitHub issue with the version, whether you’re on stable/beta/main, and a short log snippet from a run: https://github.com/openclaw/openclaw/issues

A repo link can help, but the most useful repro is probably: fresh Control UI chat run -> WS frames show agent/status activity during the run, but no live chat/session.message transcript rows until final history refresh.

lusty ore
delicate flowerBOT
# lusty ore Ok so the repo is here: https://github.com/rajohan/Mira-Dashboard Current openc...

I took a read-only look. Two useful findings:

  1. Your dashboard currently handles chat events, plus it has code for session.tool / runtime events, but I didn’t see it actually subscribing with sessions.subscribe or sessions.messages.subscribe { key }. In current Gateway protocol, session-scoped transcript/tool updates are behind those subscriptions:
await request("sessions.subscribe", {})
await request("sessions.messages.subscribe", { key: selectedSessionKey })

Unsubscribe/re-subscribe when the selected session changes. Docs: https://docs.openclaw.ai/gateway/protocol

  1. The 2026.5.7 → 2026.5.12 diff has several directly relevant Gateway changes:
  • fix(gateway): add incremental chat delta payloads
  • fix(gateway): require v4 chat deltas
  • fix(gateway): avoid duplicate v4 deltas
  • fix(gateway): carry transcript update sequence
delicate flowerBOT
# lusty ore Ok so the repo is here: https://github.com/rajohan/Mira-Dashboard Current openc...

So 2026.5.12 did change the live chat/transcript streaming path. Your client should tolerate chat delta payloads with deltaText and optional replace, while still using payload.message as the cumulative assistant snapshot when present. Your code already mostly uses payload.message, so I don’t think this alone explains the whole symptom.

Because you also see it in OpenClaw Control UI, I’d still file this upstream as a regression from 2026.5.7 to 2026.5.12: https://github.com/openclaw/openclaw/issues

Best repro payload for the issue: browser WS frame log from Control UI showing live agent/status events during a run but missing or delayed chat, session.message, or session.tool frames until chat.history refresh. Also include whether the WS auth scopes show operator.read.

sweet glen
#

yeah, looks like a v4 event-rename or subscription-shape change at the gateway layer. the symptom (generic status visible, ordered deltas only arrive on completion) usually means your client is subscribed to the old event names that no longer fire, or fire only at run-end. repo would help, but two quick checks first: (a) what does the gateway WebSocket connection log show during a live run, are events arriving at all or only the status pings? (b) any release notes between your old version and current that mention gateway/streaming changes?

delicate flowerBOT
# sweet glen yeah, looks like a v4 event-rename or subscription-shape change at the gateway l...

Yep, the version window has relevant changes. I checked 2026.5.7 → 2026.5.12 and saw these commits in the gateway chat/transcript path:

  • fix(gateway): add incremental chat delta payloads
  • fix(gateway): require v4 chat deltas
  • fix(gateway): avoid duplicate v4 deltas
  • fix(gateway): carry transcript update sequence

Current docs/source say the live surfaces are still chat events for chat.send streaming, plus session.message / session.tool behind sessions.subscribe or sessions.messages.subscribe { key }. Content frames are also scope-gated behind operator.read, while generic status/transport events can still show without that.

So the next useful check is exactly the browser WS frame log during an active run: do we see chat frames with state: "delta" and maybe deltaText, or only agent/status frames until the final chat.history refresh?

lusty ore
#

My openclaw agent made this PR https://github.com/rajohan/Mira-Dashboard/pull/46

I still does not work but it ran it and gave me this as the result

BEFORE PATCH
sent: sessions.messages.subscribe { key: "agent:main:main" }
received: agent item start/end
received: no chat delta/final
received: no session.message
received: no session.tool
summary: chatDelta=0 chatFinal=0 sessionMessage=0 sessionTool=0 agent=6

AFTER PATCH
sent: sessions.subscribe
sent: sessions.messages.subscribe { key: "agent:main:main" }
received: session.tool start name=bash keys=[phase,name,itemId,toolCallId,meta,args]
received: session.tool result name=bash keys=[phase,name,itemId,toolCallId,meta,status,isError,result]
result: { status:"completed", exitCode:0, durationMs:959 }
received: session.tool start/result name=message
summary: chatDelta=0 chatFinal=0 sessionMessage=0 sessionTool=4 agent=12

Conclusion: The browser now receives session.tool, but the Gateway frame for the bash result only contains status/exitCode/durationMs, not stdout. The test also did not receive any chat delta/final frames or session.message frames.

delicate flowerBOT
# lusty ore My openclaw agent made this PR https://github.com/rajohan/Mira-Dashboard/pull/46...

That output is actually very useful.

What it proves:

  • sessions.subscribe is required for session.tool; PR #46 fixed that part.
  • Missing stdout from session.tool is probably intentional with current Gateway defaults. Source/tests show tool result / partialResult are stripped unless verbose is full. verbose: on still strips full output; full keeps it. Try:
await request("sessions.patch", {
  key: "agent:main:main",
  patch: { verboseLevel: "full" }
})

or set agents.defaults.verboseDefault: "full" temporarily for debugging. Don’t leave that on casually; it can expose big/sensitive tool output.

The bigger problem is this part:

delicate flowerBOT
# lusty ore My openclaw agent made this PR https://github.com/rajohan/Mira-Dashboard/pull/46...
chatDelta=0 chatFinal=0 sessionMessage=0

If the run was started via chat.send, I would expect chat frames with state: "delta" / state: "final" for assistant text. If the run was started via sessions.send, it delegates into chat.send internally, so I’d still expect the same live chat path unless the run is producing only tool/message events and no assistant text.

Quick isolating test: send a boring no-tool prompt like reply with exactly HELLO and do not use tools. If that still gives chatDelta=0 chatFinal=0, this is very likely an OpenClaw 2026.5.12 Gateway regression in the v4 chat stream path, not Mira.

For the GitHub issue, include exactly this before/after summary plus the no-tool prompt result. The strongest repro is: session.tool arrives after sessions.subscribe, but chat delta/final and session.message never arrive live on 2026.5.12 while 2026.5.7 worked.

lusty ore
#

No-tool isolation test shows Gateway v4 chat streaming works for normal assistant text.

Test:

WS client subscribed with:
sessions.subscribe
sessions.messages.subscribe { key: "agent:main:main" }
Sent via chat.send:
Reply with exactly HELLO and do not use tools.

Observed frames:

event=chat state=delta deltaText="HELLO" messageText="HELLO"
event=chat state=final messageText="HELLO"
event=session.message messageRole=user messageText="Reply with exactly HELLO and do not use tools."

Summary:
chatDelta=1 chatFinal=2 sessionMessage=1 sessionTool=1 agent=13

So chat delta/final is not generally broken in 2026.5.12.

The remaining issue is tool output streaming:

With sessions.subscribe enabled, browser receives live session.tool frames.
For bash result frames, payload only contains: { status: "completed", exitCode: 0, durationMs: 959 }
It does not include stdout/content.
No session.message frame with the tool output arrived during the tool run.
Full stdout only becomes visible later through chat.history.

Question for Krill:
Is the expected fix to set session/agent verbose to full, or should stdout/tool result content still appear live via session.message or chat frames even when session.tool.result is stripped?

delicate flowerBOT
# lusty ore No-tool isolation test shows Gateway v4 chat streaming works for normal assistan...

Good isolation. That points away from broken v4 chat streaming and toward tool-output visibility policy.

Based on current source/tests, the expected live path for tool stdout is session.tool / agent tool result payloads, but OpenClaw strips data.result and data.partialResult unless the run/session verbose level is full.

So yes: for a dashboard that wants live stdout, set the session or agent to verboseLevel: "full" before the run, then consume session.tool result frames.

await request("sessions.patch", {
  key: "agent:main:main",
  patch: { verboseLevel: "full" }
})

verboseLevel: "on" is not enough for raw output; current tests explicitly say “strips tool output when verbose is on” and “keeps tool output when verbose is full”.

I would not expect stripped stdout to reappear live through chat frames. chat is assistant text delta/final. I also would not expect session.message to be the primary live stdout stream; it reflects transcript message appends, and in your no-tool test it only emitted the user transcript row. If full stdout appears later through chat.history, that means history/projection is showing persisted transcript/tool data after the fact, while the live WS event is intentionally redacted/compacted unless full is enabled.

delicate flowerBOT
lusty ore
#

But does this explain why the openclaw control ui has the same issues?

delicate flowerBOT
# lusty ore But does this explain why the openclaw control ui has the same issues?

Yes, if by “same issues” you mean the Control UI shows tool activity live but stdout/result text only appears after the run finishes.

I checked current source: the gateway deliberately strips data.result and data.partialResult from live tool events unless the run/session resolves to verboseLevel: "full". The Control UI live tool-card path reads exactly those fields (partialResult on update, result on result), then reloads chat.history after the final chat event when tools were used. So the behavior you described maps cleanly:

  • live event arrives → tool card/status exists
  • result payload is stripped → no live stdout/content
  • run finishes → Control UI reloads history → persisted output appears

There may be a second UI-specific gap too: the UI subscribes with sessions.subscribe, but I only see the Control UI handling agent, chat, and session.message events, not session.tool. For normal chat.send runs it likely gets run-scoped agent tool events because it advertises tool-events; for attaching to an already-running session, session.tool is supposed to cover that case, and the UI may not be consuming it.

So I’d frame the fix as two checks:

  1. If live stdout is desired, the session/run needs verboseLevel: "full" before the run starts.
  2. Control UI should either consume session.tool as well, or ensure every relevant live tool event reaches its existing agent handler.

Docs claim Control UI can “Stream tool calls + live tool output cards,” so this is fair bug territory if it only works after completion: https://docs.openclaw.ai/web/control-ui

lusty ore
#

Yes both control ui and my dashboard has the same problem. There is no "Stream tool calls + live tool output cards", also i have not seen any thinking chat responses since the update.

delicate flowerBOT
# lusty ore Yes both control ui and my dashboard has the same problem. There is no "Stream t...

That makes it broader than the verboseLevel: "full" case.

If there are no live tool cards at all in both Control UI and your dashboard, then the problem is likely earlier in the WS event path: either tool events are not being emitted/broadcast live, the client is not registered with the tool-events capability, or the UI is only listening to agent events while the gateway is sending the relevant in-flight attach events as session.tool.

verboseLevel: "full" only explains missing live stdout/result content. It does not explain missing tool start/status cards entirely.

For thinking/reasoning: current Control UI rendering also requires the UI “show thinking” toggle and the session reasoningLevel to be non-off. The TUI docs expose that as:

/reasoning stream
Ctrl+T  # toggle thinking visibility in TUI

In Control UI, check the session row/header controls for reasoning/thinking visibility. If reasoningLevel is off, the UI intentionally hides thinking blocks even if the model/provider produced them.

Can you paste these, ideally from the same install that shows the regression?

delicate flowerBOT
lusty ore
#

Before I do anymore work on this. I see there is a new version "openclaw 2026.5.14-beta.2" is it fixed here?

delicate flowerBOT
# lusty ore Before I do anymore work on this. I see there is a new version "openclaw 2026.5....

Short answer: I would not assume 2026.5.14-beta.2 fixes this specific live tool-card issue.

I checked the v2026.5.14-beta.2 changelog/commits. I see related UI/reasoning work, including:

  • Auto-reply/Claude CLI: bridge CLI-runtime assistant text-delta events into chat reasoning preview
  • several OpenRouter/Xiaomi/MiMo reasoning replay fixes
  • Control UI chat composer/header fixes

But I do not see a specific fix for “Control UI/WebChat live tool cards missing until final history reload”, session.tool handling in the UI, or tool-events live delivery. So beta.2 might help if your missing thinking is specifically from Claude/Codex CLI reasoning preview, but it does not look like the main live tool streaming regression is explicitly fixed there.

Also: there is already a 2026.5.14-beta.3 tag. If you do test a beta, I’d test the latest beta and hard-refresh/clear the Control UI service worker cache after updating. beta.3 has a Control UI cache rotation fix, which matters because stale dashboard bundles can make UI/protocol behavior look broken after updates.

Practical path before doing more dashboard work:

openclaw update --version 2026.5.14-beta.3
delicate flowerBOT
lusty ore
#

can i update without chaning from stable to beta channel in openclaw?

delicate flowerBOT
# lusty ore can i update without chaning from stable to beta channel in openclaw?

Yes, for package/npm installs you can do a one-off beta/version update without changing your persisted channel.

Use --tag, not --channel:

openclaw update --tag 2026.5.14-beta.3

or for the current beta dist-tag:

openclaw update --tag beta

That does not persist update.channel; your next plain openclaw update will go back to whatever channel you had configured, usually stable/latest.

Two notes:

delicate flowerBOT
lusty ore
#

Myopenclaw agent has now worked on a PR for a while. https://github.com/rajohan/Mira-Dashboard/pull/49

Things are better but still not optimal.
While streaming/live tool output this is what I see

assistant
Tool call · bash
{
"command": "/bin/bash -lc "printf 'SMOKE_A stdout line 1\\nSMOKE_A stdout line 2\\n'; printf '{\"smoke\":\"A\",\"ok\":true}\\n'"",
"cwd": "/home/ubuntu/projects/mira-dashboard"
}
15.05.2026, 18:04
tool
Tool result · bash
{
"status": "completed",
"exitCode": 0,
"durationMs": 0
}
15.05.2026, 18:04

But after final message I see

assistant
Tool call · message
{
"action": "send",
"message": "Live smoke start: jeg kjører nå flere tool calls med tydelige outputs etter Dashboard-restart (backendCommit a0828d5). Se spesielt om tool call/result-boblene blir liggende i rekkefølge og ikke erstattes."
}
15.05.2026, 18:04
toolResult
Tool result · message
{
"status": "ok",
"deliveryStatus": "sent",
"channel": "webchat",
"target": "current-run",
"sourceReplyDeliveryMode": "message_tool_only",
"sourceReplySink": "internal-ui",
"sourceReply": {
"text": "Live smoke start: jeg kjører nå flere tool calls med tydelige outputs etter Dashboard-restart (backendCommit a0828d5). Se spesielt om tool call/result-boblene blir liggende i rekkefølge og ikke erstattes."
},
"message": "Live smoke start: jeg kjører nå flere tool calls med tydelige outputs etter Dashboard-restart (backendCommit a0828d5). Se spesielt om tool call/result-boblene blir liggende i rekkefølge og ikke erstattes.",
"dryRun": false
}
15.05.2026, 18:04
assistant
Tool call · bash
{
"command": "/bin/bash -lc "printf 'SMOKE_A stdout line 1\\nSMOKE_A stdout line 2\\n'; printf '{\"smoke\":\"A\",\"ok\":true}\\n'"",
"cwd": "/home/ubuntu/projects/mira-dashboard"
}
15.05.2026, 18:04
toolResult
Tool result · bash
SMOKE_A stdout line 1
SMOKE_A stdout line 2
{"smoke":"A","ok":true}
15.05.2026, 18:04

delicate flowerBOT
# lusty ore Myopenclaw agent has now worked on a PR for a while. https://github.com/rajohan/...

That sample is actually the expected shape when the gateway live event is not resolving to verboseLevel: "full".

Live event:

{
  "status": "completed",
  "exitCode": 0,
  "durationMs": 0
}

That is the redacted tool-result payload. The gateway currently deletes data.result / data.partialResult from live agent and session.tool frames unless tool verbose resolves to full. After the final message, your dashboard reloads chat.history, and history contains the persisted full stdout:

SMOKE_A stdout line 1
delicate flowerBOT
delicate flowerBOT
# lusty ore Myopenclaw agent has now worked on a PR for a while. https://github.com/rajohan/...
/verbose full

Then start a new tool-using run. If you patch it after the run starts, it may be too late because the run context can already have resolved its verbose level.

One important trap: do not rely on passing verboseLevel through chat.send unless you have verified that path in your version. Current gateway tests explicitly cover that chat.send does not persist verboseLevel for operator-write callers. sessions.patch is the safer control-plane path.

If sessions.patch says the session is verboseLevel: "full" before the run and live frames still only contain status/exitCode/durationMs, then I’d call that a gateway bug: the live tool event is still being redacted despite full verbose.

delicate flowerBOT
# lusty ore Look at https://github.com/rajohan/Mira-Dashboard/blob/a0828d5f6c7b8a3ca6d3ef877...

Yes. I checked that exact commit around the line:

await request("sessions.patch", {
  key: selectedSessionKey,
  verboseLevel: "full",
});

That is the same top-level shape OpenClaw’s own Control UI slash command uses for /verbose full, so the request shape is correct. My earlier pseudo-snippet with patch: { verboseLevel: "full" } was not the shape this current gateway code uses; this one is.

Given that, if live tool events are still redacted, I’d look at these next:

  1. The patch may be failing silently. Your code catches and ignores errors:
delicate flowerBOT
# lusty ore Look at https://github.com/rajohan/Mira-Dashboard/blob/a0828d5f6c7b8a3ca6d3ef877...
} catch {
  // Best-effort diagnostics config; do not block message delivery.
}

Temporarily log/show that error and log the response from sessions.patch.

  1. Confirm the session row actually becomes verboseLevel: "full" before chat.send. Right after the patch, call sessions.list or inspect the next session snapshot/event.

  2. Check the live tool frame’s included session.verboseLevel. The gateway adds a session snapshot to live tool events. If that snapshot says full but data.result is still missing, that’s very strong evidence of a gateway-side bug. If it says off/on/missing, the patch isn’t affecting the run/session the way we think.

The important bit: your dashboard code is trying to do the right thing before chat.send. The remaining question is whether that patch succeeds and whether the gateway’s run context actually uses it for live tool payload redaction.

lusty ore
#

The served frontend bundle contains the new warning/verification code
Before chat.send, the dashboard now calls:
sessions.patch { key: selectedSessionKey, verboseLevel: "full" }
sessions.list
verifies that the selected session reports verboseLevel: "full"
No warning is shown because that verification succeeds

Direct WebSocket measurement:

Subscribed through the dashboard backend WS with sessions.messages.subscribe { key: "agent:main:main" }
Ran a shell tool call that produced stdout + JSON
The live session.tool result event had:
sessionKey: "agent:main:main"
sessionVerboseLevel: "full"
dataKeys: ["phase","name","itemId","toolCallId","meta","status","isError","result"]
name: "bash"
phase: "result"
hasResult: true
But data.result was only:

json
{
"status":"completed",
"exitCode":0,
"durationMs":310
}

Expected:
When the session verbose level is full, live session.tool result frames should include the same useful stdout/result content that later appears in chat.history after final/history reconciliation.

Observed:

The session snapshot on the live event says verboseLevel: "full"
Even so, live data.result is metadata-only
This no longer looks like the dashboard is sending the wrong sessions.patch shape, or that the patch is failing to apply
It looks like Gateway/OpenClaw is still redacting or replacing the live tool result payload with metadata-only output even when the session snapshot is verboseLevel: "full"

Questions:

Is session.tool.data.result supposed to contain stdout/full tool result content live when session.verboseLevel === "full"?
If yes, is this a Gateway v4 live event payload/redaction bug?
If no, what is the recommended live path for a dashboard that needs stdout before the final message? Should the client enrich from chat.history after each session.tool phase=result, or is there another event/field that carries full stdout?

delicate flowerBOT
# lusty ore The served frontend bundle contains the new warning/verification code Before cha...

Good evidence. With that measurement, I’d revise the diagnosis:

verboseLevel: "full" is working as a gateway redaction gate. The proof is that data.result is still present on the live session.tool event. If the redaction gate were the thing failing, result would be deleted entirely.

What you’re seeing now is different: the live bash tool event producer is only putting lifecycle metadata into data.result:

{ "status": "completed", "exitCode": 0, "durationMs": 310 }

So full prevents Gateway from stripping result, but it does not magically turn a metadata-only tool event into the full transcript stdout. The full stdout is apparently only being persisted into the transcript/history representation later.

Answers to your questions:

  1. Is session.tool.data.result supposed to contain stdout when session.verboseLevel === "full"?

For tools that emit full result content into the live agent event, yes, full should allow that content through. But for this bash path, current behavior suggests the live event itself only contains metadata. So the contract is more like: full means “do not strip result fields,” not “all tools must include full stdout in live result.”

delicate flowerBOT
# lusty ore The served frontend bundle contains the new warning/verification code Before cha...
  1. Is this a Gateway v4 bug?

I’d call it at least a Gateway/API contract gap, and probably a bug relative to the docs wording “live tool output cards.” Your evidence is strong: session snapshot says verboseLevel: "full", result exists, but the live result is not the useful output that history later shows.

  1. Recommended live path right now?

For today: keep rendering the live metadata card, then reconcile from chat.history after final completion, like Control UI does. Polling/enriching from chat.history after every session.tool phase=result may work sometimes, but I would not rely on it; your own observation suggests the useful stdout may not be available there until final/history reconciliation.

For the proper fix, Gateway should either:

  • include stdout/text content in live session.tool.data.result for bash when verbose is full, or
  • broadcast a separate live stream/event for command output (command_output-style data) to WS/session subscribers, and document that as the dashboard path.

This is now precise enough for a GitHub issue: include the sessionVerboseLevel: "full", dataKeys showing result exists, and the metadata-only data.result versus the later chat.history stdout.

lusty ore
#

ALso it has started using tool to output some of the messages. At not the "assistant". Is this normal behavior?

toolResult
Tool result · message
{
"status": "ok",
"deliveryStatus": "sent",
"channel": "webchat",
"target": "current-run",
"sourceReplyDeliveryMode": "message_tool_only",
"sourceReplySink": "internal-ui",
"sourceReply": {
"text": "Report for Krill / OpenClaw support:\n\nAfter Mira Dashboard PR #49 commit 35965ea, the dashboard was restarted and the new frontend/backend are confirmed live.\n\nConfirmed:\n- mira-" }, "message": "Report for Krill / OpenClaw support:\n\nAfter Mira Dashboard PR #49 commit 35965ea, the dashboard was restarted and the new frontend/backend are confirmed live.\n\nConfirmed:\n- mira-da",
"dryRun": false
}

delicate flowerBOT
# lusty ore ALso it has started using tool to output some of the messages. At not the "assis...

Yes, that can be normal, especially in a message_tool_only / internal webchat delivery path.

What that payload means:

"sourceReplyDeliveryMode": "message_tool_only",
"sourceReplySink": "internal-ui",
"target": "current-run"

The agent used the message tool to deliver user-visible text into the webchat/current run instead of emitting it only as a plain assistant final. OpenClaw then records the delivery result as a toolResult · message, because mechanically it was a tool call.

So this is not necessarily a failed send. It means “the message tool sent text to the internal UI sink successfully.”

Where it gets awkward is rendering: for a chat transcript, showing the raw message tool result JSON is usually too low-level. A dashboard should probably either:

  • render sourceReply.text / message as an assistant-visible message, and hide/collapse the Tool result · message diagnostics by default, or
delicate flowerBOT
# lusty ore ALso it has started using tool to output some of the messages. At not the "assis...
  • show it only when a “show tool/diagnostic output” toggle is enabled.

I would not treat message tool results the same as bash/browser tool results. message is delivery plumbing, not useful diagnostic output most of the time.

If the agent is only using message and never producing a normal assistant final, that can still be expected under message_tool_only. But if you see both the message-tool output and a duplicate assistant final, that’s a dedupe/rendering issue in the dashboard.

lusty ore
#

It sends a final message aswell. But that message can be things like "Sent what you asked etc" and then it sent what I asked for in a tool message. This happens in both my dashboard and the control ui. If I then turn off tool output I would not even see the message.

delicate flowerBOT
# lusty ore It sends a final message aswell. But that message can be things like "Sent what ...

Yeah, that’s not a good end-user behavior.

Mechanically it makes sense: the agent is using the message tool, so the real user-facing text lands inside the message tool result. Then the model also emits a final assistant reply like “sent it.” But for a webchat/dashboard transcript, that creates the wrong hierarchy:

  • the useful answer is hidden inside tool output
  • the visible assistant final is just meta-confirmation
  • hiding tool output can hide the actual answer

I’d treat this as a UI/Gateway presentation bug, not something users should have to work around.

Recommended behavior for dashboard/Control UI:

  • If a message tool result has sourceReplySink: "internal-ui" or target: "current-run", render sourceReply.text / message as normal assistant-visible chat content.
  • Do not hide that content when “tool output” is off.
  • Keep the raw Tool result · message JSON collapsed/diagnostic-only.
  • If a later assistant final is only boilerplate like “sent what you asked,” either suppress it or de-emphasize/dedupe it.
delicate flowerBOT
lusty ore
#

Er noe av dette fikset i openclaw 2026.5.14-beta releases?

delicate flowerBOT
# lusty ore Er noe av dette fikset i openclaw 2026.5.14-beta releases?

Kort svar: jeg ser ikke at akkurat disse to tingene er fikset eksplisitt i 2026.5.14-beta.

Det finnes noen relaterte fixes i 2026.5.14-beta-serien:

  • Control UI/WebChat cache/service-worker rotation, sĂĄ stale frontend bundles blir mindre sannsynlig.
  • Control UI/WebChat composer/header/UI-fixes.
  • Noe reasoning/thinking-relatert, blant annet Claude CLI reasoning preview og OpenRouter/Xiaomi/MiMo reasoning replay.
  • Noen message-tool/forced-message-tool endringer.

Men jeg ser ikke en konkret fix for:

  1. session.tool.data.result for bash/shell live events inneholder bare { status, exitCode, durationMs } selv nĂĄr session.verboseLevel === "full".
  2. message tool-result til internal-ui blir vist som tool output, slik at faktisk svar forsvinner når tool output skjules, mens assistant-finalen bare sier “sent it”.

Så betaen kan forbedre nærliggende ting, og beta.3 er fortsatt bedre å teste enn beta.2 på grunn av cache/service-worker-fixen. Men jeg ville ikke forvente at den løser disse to symptomene uten en egen patch.

Hvis du filer issue, ville jeg delt dem som to bugs: