Bug type
Behavior bug
Beta release blocker
No
Summary
When the CLI-runner reseeds an invalidated claude-cli session from the OpenClaw transcript, chat clients render the entire internal reseed prompt – "Continue this conversation using the OpenClaw transcript below as prior session history. […] <conversation_history>…</conversation_history><next_user_message>…</next_user_message>" – as a user chat bubble instead of showing only the actual user message.
Steps to reproduce
- Run the gateway with the
claude-cli CLI-runner backend (reseedFromRawTranscriptWhenUncompacted: true is the bundled default) and chat normally so a session has some short, uncompacted history.
- Let a "safe invalidation" occur so the next message reseeds the fresh CLI session from the raw transcript (per
docs/gateway/cli-backends.md: missing CLI transcript, system-prompt/MCP change, or session-expired retry; on our instance occurrences cluster at the daily session rotation around midnight and after config-change gateway restarts – we could not isolate one deterministic trigger).
- Send a message from the client; the reseed wrapper becomes the first user message of the fresh claude-cli session.
- Open/reload the chat history in a client (observed in the iOS app; the wrapper comes from the gateway history import, so any history-API client should be affected).
Note: whenever the reseed path runs, the display bug follows unconditionally – the gateway history import has no handling for the reseed envelope (see evidence below), so the trigger frequency is a property of session invalidation, not of the display bug itself.
Expected behavior
The chat shows only the message the user actually typed. The reseed wrapper is internal prompt scaffolding for the fresh CLI session and should never surface in any client's chat history.
Actual behavior
The user bubble contains the full reseed wrapper: the "Continue this conversation using the OpenClaw transcript below…" instruction, the <conversation_history> block (with prior User:/Assistant: turns), and the actual message wrapped in <next_user_message>. Screenshot in the first comment (the small bubble above is what the user actually typed; the large bubble is what the app renders for it).
The same unfiltered import surfaces other synthetic claude-cli messages too. When a message arrives after hours of idle and the runner revives the CLI session, Claude Code's own default continuation prompt and canned reply are persisted to the CLI transcript and then rendered in the chat as a user bubble "Continue from where you left off." followed by an assistant bubble "No response requested." (both literal strings ship in the Claude Code binary; per the transcript timestamps both were written in the same second – the end user typed neither).
OpenClaw version
2026.6.11 (e085fa1)
Operating system
Gateway: macOS 26.5.1 (arm64, M1) · Client: iOS App Store app (ai.openclawfoundation.app)
Install method
npm global install (Homebrew node), gateway as launchd LaunchAgent
Model
anthropic/claude-fable-5 (also observed on claude-opus-4-8)
Provider / routing chain
openclaw → cli-runner → claude-cli (Claude Code CLI backend)
Logs
First user message of the fresh claude-cli session file (~/.claude/projects/<workspace>/<session>.jsonl):
Continue this conversation using the OpenClaw transcript below as prior session history.
Treat it as authoritative context for this fresh CLI session.
<conversation_history>
User: [prior message]
Assistant: [prior reply]
</conversation_history><next_user_message>[the message the user actually typed]</next_user_message>
Second instance (same defect, observed 2026-07-03 after ~4.5h idle; identical timestamps):
2026-07-03T20:09:03Z user Continue from where you left off.
2026-07-03T20:09:03Z assistant No response requested.
2026-07-03T20:09:04Z user [the actual inbound message]
Code pointers (verified against main @ 6638a57, 2026-07-03):
- The wrapper text is built by
buildCliSessionHistoryPrompt() in src/agents/cli-runner/session-history.ts (called from src/agents/cli-runner/prepare.ts; "Reseed history cap" documented in docs/gateway/cli-backends.md).
- The wrapper is sent to the CLI process as its first user prompt, so it is persisted as the first user message of the native claude-cli session file (multiple occurrences on disk on our instance, e.g. three between Jun 26 and Jul 3).
- The gateway chat-history import (
src/gateway/cli-session-history.ts / cli-session-history.claude.ts) merges those native-session messages into the display history without detecting/stripping the reseed envelope – grepping the display path for conversation_history / next_user_message handling comes up empty.
- The 2026.7.1 changelog contains no related fix.
Impact and severity
Cosmetic/no functional break, but it exposes internal prompt scaffolding (and a condensed replay of prior conversation content) as a fake "user" message. Recurs in day-to-day use (several times per week on our instance). Confuses non-technical end users (family-assistant setup) who see long messages "they never typed". Privacy-adjacent: the <conversation_history> replay can resurface earlier conversation content at an unexpected place in the visible chat.
Additional information
Bug type
Behavior bug
Beta release blocker
No
Summary
When the CLI-runner reseeds an invalidated
claude-clisession from the OpenClaw transcript, chat clients render the entire internal reseed prompt – "Continue this conversation using the OpenClaw transcript below as prior session history. […]<conversation_history>…</conversation_history><next_user_message>…</next_user_message>" – as a user chat bubble instead of showing only the actual user message.Steps to reproduce
claude-cliCLI-runner backend (reseedFromRawTranscriptWhenUncompacted: trueis the bundled default) and chat normally so a session has some short, uncompacted history.docs/gateway/cli-backends.md: missing CLI transcript, system-prompt/MCP change, or session-expired retry; on our instance occurrences cluster at the daily session rotation around midnight and after config-change gateway restarts – we could not isolate one deterministic trigger).Note: whenever the reseed path runs, the display bug follows unconditionally – the gateway history import has no handling for the reseed envelope (see evidence below), so the trigger frequency is a property of session invalidation, not of the display bug itself.
Expected behavior
The chat shows only the message the user actually typed. The reseed wrapper is internal prompt scaffolding for the fresh CLI session and should never surface in any client's chat history.
Actual behavior
The user bubble contains the full reseed wrapper: the "Continue this conversation using the OpenClaw transcript below…" instruction, the
<conversation_history>block (with prior User:/Assistant: turns), and the actual message wrapped in<next_user_message>. Screenshot in the first comment (the small bubble above is what the user actually typed; the large bubble is what the app renders for it).The same unfiltered import surfaces other synthetic claude-cli messages too. When a message arrives after hours of idle and the runner revives the CLI session, Claude Code's own default continuation prompt and canned reply are persisted to the CLI transcript and then rendered in the chat as a user bubble "Continue from where you left off." followed by an assistant bubble "No response requested." (both literal strings ship in the Claude Code binary; per the transcript timestamps both were written in the same second – the end user typed neither).
OpenClaw version
2026.6.11 (e085fa1)
Operating system
Gateway: macOS 26.5.1 (arm64, M1) · Client: iOS App Store app (
ai.openclawfoundation.app)Install method
npm global install (Homebrew node), gateway as launchd LaunchAgent
Model
anthropic/claude-fable-5 (also observed on claude-opus-4-8)
Provider / routing chain
openclaw → cli-runner → claude-cli (Claude Code CLI backend)
Logs
Code pointers (verified against
main@ 6638a57, 2026-07-03):buildCliSessionHistoryPrompt()insrc/agents/cli-runner/session-history.ts(called fromsrc/agents/cli-runner/prepare.ts; "Reseed history cap" documented indocs/gateway/cli-backends.md).src/gateway/cli-session-history.ts/cli-session-history.claude.ts) merges those native-session messages into the display history without detecting/stripping the reseed envelope – grepping the display path forconversation_history/next_user_messagehandling comes up empty.Impact and severity
Cosmetic/no functional break, but it exposes internal prompt scaffolding (and a condensed replay of prior conversation content) as a fake "user" message. Recurs in day-to-day use (several times per week on our instance). Confuses non-technical end users (family-assistant setup) who see long messages "they never typed". Privacy-adjacent: the
<conversation_history>replay can resurface earlier conversation content at an unexpected place in the visible chat.Additional information
stripEnvelopeFromMessages()and the "Conversation info (untrusted metadata)" block on inbound channel messages) – this is the separate CLI reseed code path (default-on since fix(anthropic): enable Claude CLI session-expired history reseed #80934), which runs only on session invalidation.buildCliSessionHistoryPrompt()function (confirms the code pointer); [Feature]: Surface CLI session resets (reason=system-prompt) to the active conversation #96553 (surfacing CLI session resets) is adjacent but requests intentional surfacing, not this accidental leak.