Skip to content

[Bug]: systemPromptHash in buildClaudeLiveFingerprint causes phantom claude-cli session restarts on every turn for chat channels #81041

@benjamin1492

Description

@benjamin1492

[Bug]: systemPromptHash in buildClaudeLiveFingerprint causes phantom claude-cli session restarts on every turn for chat channels

Summary

When OpenClaw routes a chat channel (Telegram, Discord, Slack, iMessage, Signal, WhatsApp) through the claude-cli backend, the live-session fingerprint computed by buildClaudeLiveFingerprint (in src/agents/cli-runner/claude-live-session.ts) hashes the entire system prompt, including the per-turn volatile sections that OpenClaw injects on every inbound message:

  • channel-specific guidance ("You are in a Telegram direct conversation…")
  • inbound metadata block ([Tue 2026-05-12 09:33 EDT], message_id, sender envelope)
  • heartbeat poll text
  • runtime status line (model, agent, capabilities, thinking level)

Every turn's prompt has a different hash → fingerprint diverges → the runtime decides the live claude-cli subprocess no longer matches the requested session and rotates to a fresh CLI subprocess. The new subprocess has no memory of the previous turn, so the agent loses context between adjacent messages from the same user in the same chat session.

This is claude-cli-only: the API backend (Anthropic Messages, OpenAI, OpenRouter) replays full message history per request and does not maintain a fingerprinted persistent process, so this code path doesn't apply.

Symptom (user-facing)

[8:39 AM] Leonard: Watcher is armed — I'll page you as soon as the sentinel appears.
            Anything else you want to tee up in the meantime?
[8:44 AM] User:    still working on it?
[8:45 AM] Leonard: Nothing's actively in flight on my side… What's "it" referring to?

The agent has no recollection of its own message from 6 minutes earlier. Looks like
amnesia from the user's perspective. Reproduces consistently on Telegram/Discord; likely
all chat channels that inject any per-turn metadata.

Why it happens

src/agents/cli-runner/claude-live-session.ts line 276:

return JSON.stringify({
  command: params.context.preparedBackend.backend.command,
  workspaceDirHash: sha256(params.context.workspaceDir),
  provider: params.context.params.provider,
  model: params.context.normalizedModel,
  systemPromptHash: sha256(params.context.systemPrompt),   // ← THE BUG
  authProfileIdHash: ,
  authEpochHash: ,
  extraSystemPromptHash: params.context.extraSystemPromptHash,
  mcpConfigHash: ,
  skillsFingerprint,
  argv: stableArgv,
  env: 
});

params.context.systemPrompt contains everything OpenClaw assembles for the turn,
including inbound_meta, channel section ("Group Chat Context", "Reactions"), heartbeat
text, sender allowlist, current date/time, and the runtime banner. Most of those are
intentionally per-turn-volatile (that's their whole purpose).

The fingerprint already separately hashes extraSystemPromptHash (which catches static
config changes — the agent's persona prompt, SOUL.md, USER.md, AGENTS.md), so dropping
systemPromptHash does not weaken the integrity check. It just removes the per-turn
volatile component that should never have been part of the stability decision in the
first place.

Suggested fix

Remove the systemPromptHash field from buildClaudeLiveFingerprint's output. Diff:

   workspaceDirHash: sha256(params.context.workspaceDir),
   provider: params.context.params.provider,
   model: params.context.normalizedModel,
-  systemPromptHash: sha256(params.context.systemPrompt),
   authProfileIdHash: …,
   authEpochHash: …,
   extraSystemPromptHash: params.context.extraSystemPromptHash,

extraSystemPromptHash already covers the static-config side of the check.

Repro

  1. Configure OpenClaw with a claude-cli backend (Claude Max subscription — see lodekeeper's gist on migrating from API to claude-cli).
  2. Connect a Telegram bot channel.
  3. Have the agent post a message that opens a thought ("I'll let you know when X").
  4. Wait 1–10 minutes; the runtime injects fresh metadata on the next inbound.
  5. User says something referential ("still working on it?"). Agent has no memory of the
    prior turn.

Affected versions

Confirmed on 2026.5.7 (current latest at filing time). Code path appears to have existed
since the live-session fingerprint was introduced; likely affects every release with
buildClaudeLiveFingerprint.

Scope

  • Affected: claude-cli backend + chat channels with per-turn metadata injection.
    Telegram and Discord confirmed; Slack/iMessage/Signal/WhatsApp/Mattermost likely.
  • Not affected: API backends (Anthropic Messages, OpenAI, OpenRouter, Vertex,
    Bedrock, etc.) — they don't keep a fingerprinted persistent process.
  • Not affected: one-shot CLI invocations (openclaw run) — those don't have the
    multi-turn context-loss symptom even when running through claude-cli.

Related issues

Workaround

Locally patching the bundled JS to drop systemPromptHash from the fingerprint output
resolves the symptom. Tested on 2026.5.7 with Telegram + claude-cli; cross-turn context
is retained as expected after the change.

Next step

A PR with the source-level fix and tests will follow shortly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions