#14309: fix(ui): resolve chat event session key mismatch
app: web-ui
stale
size: S
## Summary
- Fix session key comparison in `handleChatEvent` to handle agent-scoped keys (`agent:<agentId>:<baseKey>`)
- Add optimistic rendering of the final assistant message instead of waiting for `loadChatHistory` round-trip
## Problem
Chat events from the gateway use agent-scoped session keys (e.g. `agent:main:<key>`), but the UI stores just the base key. The strict `===` comparison caused **all** chat delta and final events to be silently dropped, making the chat appear unresponsive until manual page refresh.
## Changes
- Added `sessionKeyMatches()` helper that compares session keys accounting for the `agent:` prefix
- Added optimistic append of the final assistant message to `chatMessages` on the "final" event
## Test plan
- Verified in Docker-based OpenClaw deployment where gateway token is used as session key
- Confirmed streaming deltas now display in real-time
- Confirmed final message appears instantly without page refresh
Fixes #10132
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
Fixes a session key mismatch bug where chat events from the gateway using agent-scoped keys (`agent:<agentId>:<baseKey>`) were silently dropped because the UI stores only the base key. Adds a `sessionKeyMatches()` helper for flexible comparison and optimistically appends the final assistant message to avoid waiting for the `loadChatHistory` round-trip.
- **Session key matching**: New `sessionKeyMatches` function correctly handles both directions (event key or state key being agent-scoped). The colon-prefixed `endsWith` check prevents false partial matches.
- **Optimistic message append**: The final assistant message is appended immediately on the "final" event, then `loadChatHistory` replaces the entire array with authoritative server data. There's a brief window where a duplicate could flash on slow connections, but it's transient.
- **Missing test coverage**: The existing test file (`chat.test.ts`) doesn't cover agent-scoped key matching or the optimistic append behavior.
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge with low risk — it fixes a real bug that made chat appear unresponsive.
- The session key matching logic is sound, and the optimistic append is a reasonable UX improvement backed by `loadChatHistory` replacing the full array. Minor concerns: potential brief duplicate flash and missing test coverage for the new behavior.
- No files require special attention, though `ui/src/ui/controllers/chat.test.ts` should be updated with new test cases.
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#3721: fix(ui): webchat not displaying chat responses
by maxmaxrouge-rgb · 2026-01-29
86.3%
#9218: Fix Control UI chat resync on gaps and terminal events
by figitaki · 2026-02-05
85.2%
#3182: fix(gateway): use canonical session key in chat.send
by chrisherold · 2026-01-28
84.2%
#15564: fix: webchat messages disappear during concurrent session activity
by Automatedcapitalist · 2026-02-13
83.8%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
82.9%
#19343: Refactor chat state management: reset chat messages and queue on se...
by saurav470 · 2026-02-17
82.7%
#22798: feat(webchat): ChatGPT-style multi-chat threads with generated titles
by opnsec · 2026-02-21
82.5%
#22977: fix(ui): resolve agent names from config in session dropdown
by NikhilGaddam · 2026-02-21
82.3%
#18694: fix(ui): reset session key to main after /new in webchat
by Phineas1500 · 2026-02-17
82.2%
#8774: Fix/frontend session key normalization
by zhaodageng · 2026-02-04
82.1%