#6611: fix(webchat): persist assistant messages for CLI backends
app: web-ui
gateway
## Summary
- Fixes webchat message persistence when using CLI backends (claude-cli, codex-cli)
- Messages now persist correctly to transcript files and survive page reloads
## Problem
When using CLI backends, assistant messages appeared during the chat session but disappeared after page reload. This happened because:
1. The `chatLink` was not being registered in `onAgentRunStart`, causing agent events to not be properly routed
2. The `agentRunStarted` flag bypassed the normal message persistence path in the gateway
## Solution
1. Register `chatLink` in `onAgentRunStart` callback so agent events are properly mapped to client runIds
2. Add `saveAssistantToTranscript()` function that persists assistant messages directly to the session transcript JSONL file
3. Call this function in `emitChatFinal` when a CLI backend run completes successfully
## Testing
- Tested with claude-cli backend on local OpenClaw instance
- Verified messages persist correctly in session transcript files
- Confirmed messages survive page reload in webchat UI
## Related Issues
Fixes #5660
Fixes #2977
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR fixes missing webchat persistence for CLI-backed runs by (1) registering the agent `runId` to client `runId` mapping in `onAgentRunStart` so agent events route correctly, and (2) appending assistant final text to the session transcript when a run completes.
The overall approach matches the existing gateway architecture: webchat UI reloads come from transcript JSONL (`readSessionMessages`), while live updates come from the agent event bus and chat broadcasts. The new `addChatRun(agentRunId, { clientRunId, sessionKey })` ensures those streams line up for CLI backends.
Main concern: the new persistence helper in `server-chat.ts` appears to resolve the transcript path using `entry.sessionId` rather than the agent’s session id, which can append to a different transcript than the one the UI reload path reads. There’s also a risk of skipped persistence when the transcript file doesn’t exist, and potential duplication if backends already write assistant messages to the transcript.
<h3>Confidence Score: 3/5</h3>
- This PR is likely safe to merge, but there’s a meaningful risk the new transcript append targets the wrong session file for some CLI runs.
- Event routing fix via `onAgentRunStart` is straightforward and aligns with existing `addChatRun` usage elsewhere. The new transcript append is plausible, but it uses `entry.sessionId` for path resolution, which may differ from the agent session id used by `readSessionMessages()` and other transcript writers; that mismatch could negate the intended persistence or misattribute messages. No automated tests were added for this new behavior.
- src/gateway/server-chat.ts (transcript write path resolution); src/gateway/server-methods/chat.ts (runId mapping assumptions)
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#13104: fix: persist user command message in chat transcript
by mcaxtr · 2026-02-10
82.6%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
80.6%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
79.9%
#3721: fix(ui): webchat not displaying chat responses
by maxmaxrouge-rgb · 2026-01-29
79.9%
#8598: fix: emit agent events for CLI agents targeting webchat
by dbottme · 2026-02-04
78.9%
#8344: fix: persist webchat message queue to localStorage across browser r...
by vishaltandale00 · 2026-02-03
78.6%
#11123: Fix webchat→external channel cross-delivery
by jingkang0822 · 2026-02-07
78.3%
#15792: fix: pass agentId to resolveSessionFilePath in additional call sites
by MisterGuy420 · 2026-02-13
78.3%
#15564: fix: webchat messages disappear during concurrent session activity
by Automatedcapitalist · 2026-02-13
78.0%
#16949: fix(gateway): deliver chat:final even when sessionKey is unresolved (…
by ekleziast · 2026-02-15
77.9%