openclaw - ✅(Solved) Fix bug: session.message events from sessions.send not rendered in webchat UI or TUI [1 pull requests, 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#56914Fetched 2026-04-08 01:46:05
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×1referenced ×1

When a user message is injected into a session via sessions.send (e.g. from MCP tools like post_control_chat_message, the CLI, or any non-webchat surface), the message is written to the transcript and an agent run is triggered — but the user message itself never appears in the webchat Control UI or TUI. Only the assistant reply renders.

Root Cause

sessions.sendchat.sendemitSessionTranscriptUpdate → gateway broadcasts session.message event with the injected user message.

Neither the webchat UI (ui/src/ui/app-gateway.ts) nor the TUI have a handler for evt.event === "session.message". The event is broadcast and silently dropped on both surfaces.

Fix Action

Fixed

PR fix notes

PR #56940: fix: render injected user messages from sessions.send in webchat UI

Description (problem / solution / changelog)

Summary

Messages injected via sessions.send (MCP tools, CLI, other agents) were invisible in the webchat Control UI and TUI — only the assistant reply would appear, making the conversation look one-sided.

Root Cause

The gateway broadcasts session.message events when sessions.send injects a user message, but:

  • ui/src/ui/app-gateway.ts had no handler for this event type, causing it to be silently dropped in the webchat UI
  • src/tui/tui.ts had no handler for session.message, causing it to be silently dropped in the TUI

Changes

  • Added session.message event handler in ui/src/ui/app-gateway.ts
    • Filters by sessionKey and role === "user", then appends to chatMessages
    • Uses senderLabel for multi-sender attribution when available
  • Added handleSessionMessageEvent to src/tui/tui-event-handlers.ts
    • Calls chatLog.addUser() with the injected message text and optional sender label prefix
  • Wired handleSessionMessageEvent into src/tui/tui.ts event dispatcher
  • Added addUser to EventHandlerChatLog type interface
  • Added tests in src/tui/tui-event-handlers.test.ts covering the new handler

Testing

New unit tests added for handleSessionMessageEvent:

  • Appends user message when sessionKey matches
  • Ignores events for different sessions
  • Ignores non-user role messages
  • Prefixes message with senderLabel when present
  • Ignores messages with no extractable text

Fixes openclaw/openclaw#56914

Changed files

  • src/agents/tools/sessions-helpers.ts (modified, +1/-0)
  • src/agents/tools/sessions-list-tool.test.ts (modified, +57/-0)
  • src/agents/tools/sessions-list-tool.ts (modified, +1/-0)
  • src/tui/tui-event-handlers.test.ts (modified, +81/-0)
  • src/tui/tui-event-handlers.ts (modified, +30/-1)
  • src/tui/tui.ts (modified, +4/-1)
  • ui/src/ui/app-gateway.ts (modified, +27/-0)
  • ui/src/ui/views/overview.ts (modified, +4/-4)
RAW_BUFFERClick to expand / collapse

Summary

When a user message is injected into a session via sessions.send (e.g. from MCP tools like post_control_chat_message, the CLI, or any non-webchat surface), the message is written to the transcript and an agent run is triggered — but the user message itself never appears in the webchat Control UI or TUI. Only the assistant reply renders.

Root cause

sessions.sendchat.sendemitSessionTranscriptUpdate → gateway broadcasts session.message event with the injected user message.

Neither the webchat UI (ui/src/ui/app-gateway.ts) nor the TUI have a handler for evt.event === "session.message". The event is broadcast and silently dropped on both surfaces.

Impact

  • Messages posted into Control Chat from external sources (MCP, CLI, other agents) are invisible in the UI
  • The operator sees assistant replies but not what triggered them — the conversation appears broken / one-sided
  • Affects any message entering the session from outside the webchat UI itself

Reproduction

  1. Set up an MCP server that calls sessions.send or post_control_chat_message into the main session
  2. Open the webchat Control UI for that session
  3. Trigger a message injection from the MCP client
  4. Observe: assistant reply appears, but the injected user message does not

Expected behaviour

The user message should appear in the chat UI in the correct position, attributed to its sender (using senderLabel if available), before the assistant reply — the same as if the message had been sent from the webchat UI directly.

Suggested fix

Add a session.message event handler in ui/src/ui/app-gateway.ts (and the TUI equivalent) that:

  1. Checks payload.sessionKey === state.sessionKey
  2. Checks payload.message.role === "user"
  3. Appends the message to chatMessages (same path as assistant finals in handleChatEvent)

The senderLabel is already populated on injected messages via extractInboundSenderLabel in chat-sanitize.ts, so multi-sender attribution should work automatically.

Context

  • Webchat handler: ui/src/ui/app-gateway.ts — no session.message case in the event switch
  • Gateway emitter: src/gateway/server.impl.ts L926+ — onSessionTranscriptUpdate listener broadcasts session.message
  • Transcript update call: src/gateway/server-methods/chat.ts L1571 — emitSessionTranscriptUpdate called from emitUserTranscriptUpdate
  • session.message payload includes: sessionKey, message (with role, senderLabel, content), messageSeq

extent analysis

Fix Plan

To fix the issue, we need to add a session.message event handler in ui/src/ui/app-gateway.ts and the TUI equivalent. Here are the steps:

  • Add a new case to the event switch in ui/src/ui/app-gateway.ts to handle the session.message event.
  • Check if the payload.sessionKey matches the current state.sessionKey and if the payload.message.role is "user".
  • If both conditions are met, append the message to chatMessages.

Example code:

// ui/src/ui/app-gateway.ts
switch (evt.event) {
  // ...
  case 'session.message':
    if (payload.sessionKey === state.sessionKey && payload.message.role === 'user') {
      const newMessage = {
        ...payload.message,
        senderLabel: payload.message.senderLabel,
      };
      state.chatMessages.push(newMessage);
    }
    break;
  // ...
}

Verification

To verify that the fix worked, follow these steps:

  • Set up an MCP server that calls sessions.send or post_control_chat_message into the main session.
  • Open the webchat Control UI for that session.
  • Trigger a message injection from the MCP client.
  • Observe: the injected user message should appear in the chat UI, attributed to its sender, before the assistant reply.

Extra Tips

  • Make sure to update the TUI equivalent to handle the session.message event as well.
  • Test the fix with different scenarios, such as multiple message injections and different sender labels.

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