← Back to PRs

#6611: fix(webchat): persist assistant messages for CLI backends

by JorgeAlan open 2026-02-01 21:35 View on GitHub →
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