openclaw - 💡(How to fix) Fix v5.22 regressions: group-chat over-suppression + sticky image re-attachment in always-on Discord channels

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

After upgrading from 2026.5.7 → 2026.5.22, two distinct regressions surfaced that together cause significant noise and reduced reliability in always-on Discord group-chat agents:

  1. Group-chat over-suppression: the "Be extremely selective: reply only when directly addressed or clearly helpful." line is now injected for every silentReplyPolicy value except "disallow". In v5.7 it was gated to === "allow" only. This biases agents in always-on channels (where the user expects engagement on every message) toward NO_REPLY / non-substantive replies.

  2. Sticky image re-attachment: an image attached once is silently re-attached to every subsequent prompt because the post-turn prompt-text regex re-extracts the persisted ~/.openclaw/workspace/.openclaw-cli-images/<sha256>.<ext> path from the conversation transcript. The model then receives unrelated images on every turn and starts treating them as context.

Both have been root-caused below.


Root Cause

Confirmed via source read. No state file is involved — the stickiness lives entirely in the replayed prompt transcript.

  • File: dist/images-CHOq0BQv.js
  • Function: detectImageReferences (lines 202–270)
  • Offending pattern: the final catch-all PATH_PATTERN loop at line 269 matches any string ending in an image extension anywhere in the prompt — including text quoted from prior turns and synthetic <system-reminder> blocks describing past tool calls.

Contributing:

  • dist/helpers-BpzSVpXp.js line 180–184 appendImagePathsToPrompt splices the absolute image path into the prompt text.
  • dist/helpers-BpzSVpXp.js line 240–259 prepareCliPromptImagePayload — on every turn, when no fresh params.images is supplied, falls back to loadPromptRefImages(prompt), which feeds the entire prompt (history + system-reminders) back through detectImageReferences. That re-resolves the prior path, re-loads the bytes, re-writes to .openclaw-cli-images/, and re-appends. Sticky loop.
  • dist/helpers-BpzSVpXp.js line 223 cleanup = async () => {} is a no-op, so .openclaw-cli-images/ grows unbounded.
  • Backend default imagePathScope: "workspace" (cli-backend-*.js line ~52) places files at content-addressed ~/.openclaw/workspace/.openclaw-cli-images/<sha256>.<ext>. The digest is stable across turns and the directory never auto-cleans.

Fix Action

Fix / Workaround

Workaround in place

The context-engine plugin SDK (dist/plugin-sdk/src/context-engine/types.d.ts:23) exposes systemPromptAddition (prepend-only). There is no transform/strip hook to remove a line from the assembled system prompt — so users cannot patch this from a plugin today. Either a built-in fix or a systemPromptTransform hook is needed.

(1) is the minimum hot-patch.

Code Example

// v5.7 (correct)
const canUseSilentReply = !messageToolOnly && params.silentToken && params.silentReplyPolicy === "allow";

// v5.22 (broken)
const canUseSilentReply = !messageToolOnly && params.silentToken && params.silentReplyPolicy !== "disallow";
RAW_BUFFERClick to expand / collapse

Two v5.22 regressions affecting always-on Discord channels (group-chat over-suppression + sticky image re-attachment)

Summary

After upgrading from 2026.5.7 → 2026.5.22, two distinct regressions surfaced that together cause significant noise and reduced reliability in always-on Discord group-chat agents:

  1. Group-chat over-suppression: the "Be extremely selective: reply only when directly addressed or clearly helpful." line is now injected for every silentReplyPolicy value except "disallow". In v5.7 it was gated to === "allow" only. This biases agents in always-on channels (where the user expects engagement on every message) toward NO_REPLY / non-substantive replies.

  2. Sticky image re-attachment: an image attached once is silently re-attached to every subsequent prompt because the post-turn prompt-text regex re-extracts the persisted ~/.openclaw/workspace/.openclaw-cli-images/<sha256>.<ext> path from the conversation transcript. The model then receives unrelated images on every turn and starts treating them as context.

Both have been root-caused below.


Environment

  • OpenClaw: 2026.5.22 (a374c3a) (current latest on npm)
  • Install location: /opt/homebrew/lib/node_modules/openclaw/
  • Platform: macOS (darwin 25.5.0)
  • Affected: 9 always-on Discord agents (group-chat channels with single-user, single-agent expectation)

Regression 1 — group-chat "Be extremely selective" un-gated

Location

  • File: dist/get-reply-DOTqK3jN.js
  • Function: buildGroupChatContext() (line 596)
  • Offending push: line 612lines.push("Be extremely selective: reply only when directly addressed or clearly helpful.")
  • Gating predicate: line 608

Diff vs v5.7

// v5.7 (correct)
const canUseSilentReply = !messageToolOnly && params.silentToken && params.silentReplyPolicy === "allow";

// v5.22 (broken)
const canUseSilentReply = !messageToolOnly && params.silentToken && params.silentReplyPolicy !== "disallow";

The condition flipped from "only when policy is allow" to "for every policy except disallow". That means default/unset/empty silentReplyPolicy now triggers the line. In v5.7, the default did not.

Secondary change: the silentReplyRewrite === true escape hatch that previously also suppressed the line is no longer consulted at this site.

Impact

  • Every always-on Discord agent (intended for direct 1:1 use) gets the "Be extremely selective" line injected on every turn.
  • Agents start replying with NO_REPLY to direct user messages, or with terse non-engagement, breaking the user's expected single-human/single-agent contract.
  • groupActivation: "always" does not rescue this — normalizeGroupActivation is only consulted at lines 634 (resolveGroupSilentReplyBehavior) and 2574 (shouldInjectGroupIntro). buildGroupChatContext never reads groupActivation, so setting it to "always" has zero effect on the selective-reply line.

Workaround in place

We applied channel-level systemPrompt overrides across all 9 agent channels that explicitly tell the agent to ignore the "Be extremely selective" instruction in that channel. This is counter-injection, not removal — the offending line is still in the assembled prompt, just contradicted later. It works but is brittle.

Requested fix

Either:

  • (a) Restore the v5.7 gating: change line 608 back to === "allow".
  • (b) Add a per-channel skip via groupActivation: "always" (wire groupActivation into buildGroupChatContext and skip the line when it's "always").

(a) is the minimal one-character-class diff and restores known-good behavior.

Plugin SDK note

The context-engine plugin SDK (dist/plugin-sdk/src/context-engine/types.d.ts:23) exposes systemPromptAddition (prepend-only). There is no transform/strip hook to remove a line from the assembled system prompt — so users cannot patch this from a plugin today. Either a built-in fix or a systemPromptTransform hook is needed.


Regression 2 — sticky image re-attachment

Symptom

User sends one image in a Discord message. On every subsequent turn — even ones with no new attachment — the model receives a <system-reminder> saying Called the Read tool with the following input: {"file_path":"/Users/trevor/.openclaw/workspace/.openclaw-cli-images/<sha256>.jpg"} and re-receives the image bytes. The agent treats it as user-supplied context and references it in replies. Over multiple turns the same image gets re-injected indefinitely.

Root cause

Confirmed via source read. No state file is involved — the stickiness lives entirely in the replayed prompt transcript.

  • File: dist/images-CHOq0BQv.js
  • Function: detectImageReferences (lines 202–270)
  • Offending pattern: the final catch-all PATH_PATTERN loop at line 269 matches any string ending in an image extension anywhere in the prompt — including text quoted from prior turns and synthetic <system-reminder> blocks describing past tool calls.

Contributing:

  • dist/helpers-BpzSVpXp.js line 180–184 appendImagePathsToPrompt splices the absolute image path into the prompt text.
  • dist/helpers-BpzSVpXp.js line 240–259 prepareCliPromptImagePayload — on every turn, when no fresh params.images is supplied, falls back to loadPromptRefImages(prompt), which feeds the entire prompt (history + system-reminders) back through detectImageReferences. That re-resolves the prior path, re-loads the bytes, re-writes to .openclaw-cli-images/, and re-appends. Sticky loop.
  • dist/helpers-BpzSVpXp.js line 223 cleanup = async () => {} is a no-op, so .openclaw-cli-images/ grows unbounded.
  • Backend default imagePathScope: "workspace" (cli-backend-*.js line ~52) places files at content-addressed ~/.openclaw/workspace/.openclaw-cli-images/<sha256>.<ext>. The digest is stable across turns and the directory never auto-cleans.

Impact

  • Unrelated images leak into every subsequent conversation turn (information leakage + bias).
  • Wasted model spend re-loading large image bytes on every turn.
  • .openclaw-cli-images/ directory grows unbounded.

Requested fix

Ranked, lowest-risk first:

  1. Skip self-written paths in detection — in dist/images-CHOq0BQv.js ~line 269, the final PATH_PATTERN loop should skip path matches that point inside any .openclaw-cli-images/ directory. These are sink files OpenClaw itself wrote — they are never user-authored references and should not be re-resolved.
  2. Use a sentinel instead of a real pathappendImagePathsToPrompt (helpers line 180) could emit something like [openclaw-image-internal: <basename>] and resolve via a separate non-regex channel.
  3. Wire real cleanup — replace the no-op at helpers line 223 with an unlink-after-turn so the directory doesn't grow unbounded.

(1) is the minimum hot-patch.


Combined ask

These two regressions interact badly: in an always-on Discord agent that received an image once, every subsequent turn now (a) carries the "Be extremely selective" suppression line and (b) re-attaches the old image, biasing the agent to under-engage on a turn that contains unrelated image context. The agent then often responds with irrelevant commentary on the sticky image instead of substantive engagement on the user's actual text.

If both fixes can land together in 2026.5.23 (or backport into the 5.24-beta line), it would fully resolve the always-on Discord experience.

Happy to test a beta build or pre-release patch and report back.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING