openclaw - ✅(Solved) Fix Safeguard compaction mode causes duplicate user messages with lossless-claw [1 pull requests, 1 comments, 2 participants]

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…
GitHub stats
openclaw/openclaw#75972Fetched 2026-05-03 04:43:39
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
3
Timeline (top)
closed ×1commented ×1cross-referenced ×1mentioned ×1

Root Cause

Three factors combine to produce duplicate messages:

Fix Action

Workaround

Changed agents.defaults.compaction.mode from safeguard to default in openclaw.json:

{
  "agents": {
    "defaults": {
      "compaction": {
        "mode": "default"
      }
    }
  }
}

default mode performs true rolling-window compression without re-injecting old messages.

PR fix notes

PR #551: fix: prevent afterTurn replay of compacted instructions

Description (problem / solution / changelog)

Summary

Fixes lossless-claw's afterTurn ingestion path so compacted/safeguard context cannot replay old user instructions back into stored LCM context.

This was prompted by openclaw/openclaw#75972. The issue was closed as not actionable in OpenClaw core, but the failure mode was real in lossless-claw's external context-engine integration.

What changed

  • Reconcile the session transcript tail before assistant-only afterTurn ingestion, so foreground user messages that OpenClaw writes outside the mutable afterTurn message array are not skipped/misaligned and later treated as new.
  • Ignore non-persistable/custom runtime-context messages instead of storing unknown roles as assistant messages.
  • When autoCompactionSummary is present, skip ingesting dedupedNewMessages whose normalized content is already covered by that summary.
  • Add regression tests for transcript reconciliation and summary/new-message overlap dedupe.

Validation

  • npm run build
  • pnpm vitest run test/engine.test.ts -t 'auto-compaction summary|summary-overlap|summary-short-overlap'
  • npm test — 817 passed / 44 files

References openclaw/openclaw#75972.

Changed files

  • .changeset/fix-afterturn-transcript-reconcile.md (added, +5/-0)
  • .changeset/fix-summary-overlap-dedup.md (added, +5/-0)
  • src/engine.ts (modified, +173/-3)
  • test/engine.test.ts (modified, +136/-8)

Code Example

const ingestBatch = [];
if (params.autoCompactionSummary) {
    ingestBatch.push({role: "user", content: params.autoCompactionSummary});
}
ingestBatch.push(...dedupedNewMessages);

---

{
  "agents": {
    "defaults": {
      "compaction": {
        "mode": "default"
      }
    }
  }
}
RAW_BUFFERClick to expand / collapse

Symptom

Agent repeatedly executes old instructions. User messages appear duplicated in the assembled context, causing the agent to see the same instruction twice and act on it again.

Root Cause

Three factors combine to produce duplicate messages:

1. Safeguard mode re-injects compressed messages

When compaction.mode is safeguard, OpenClaw's built-in compaction keeps the original messages in the JSONL transcript as a "safety net" after compressing them into a summary. This is by design — safeguard mode's purpose is to never lose data.

2. Lossless-claw afterTurn ingests both the summary AND the original messages

Lossless-claw's afterTurn hook receives params.autoCompactionSummary (the safeguard summary) and dedupedNewMessages (new messages from the JSONL, including the ones safeguard kept). It ingests both:

const ingestBatch = [];
if (params.autoCompactionSummary) {
    ingestBatch.push({role: "user", content: params.autoCompactionSummary});
}
ingestBatch.push(...dedupedNewMessages);

This causes the same user message to appear in LCM's messages table twice — once from the safeguard summary, once from the retained original.

3. OpenClaw 4.29 changed compaction trigger timing

4.29 fixed a tool-result overflow check to use the resolved runtime context token budget instead of the native contextWindow. This means compaction now triggers more readily in long tool-heavy sessions. Before 4.29, many sessions never triggered compaction at all, so the safeguard + lossless-claw interaction was never exercised.

Evidence

  • LCM messages table for coder agent (conv 895): 198 messages, but JSONL source only has 151 — 47 extra messages from compaction re-injection
  • 4 pairs of duplicate user messages found in assembled context
  • context_items table shows the same user message at different ordinals (e.g., ordinal 80 and 88 both contain the same "submit changes" instruction)
  • Built-in compaction-duplicate-user-messages dedup module only catches duplicates within a 60-second window (DUPLICATE_USER_MESSAGE_WINDOW_MS = 60000), so it misses safeguard re-injected messages that arrive later

Workaround

Changed agents.defaults.compaction.mode from safeguard to default in openclaw.json:

{
  "agents": {
    "defaults": {
      "compaction": {
        "mode": "default"
      }
    }
  }
}

default mode performs true rolling-window compression without re-injecting old messages.

Why It Worked Before 4.29

  1. Compaction triggered less often due to the old token budget calculation, so safeguard's re-injection path was rarely exercised
  2. Earlier lossless-claw versions may not have had the autoCompactionSummary ingestion logic
  3. Custom config parameters (contextThreshold: 0.75, leafChunkTokens: 25000, delegationTimeoutMs: 600000) may have further increased compaction frequency

Suggested Fix

Lossless-claw's afterTurn hook should skip ingesting dedupedNewMessages that are already covered by autoCompactionSummary, or the built-in dedup window should be expanded to catch safeguard re-injected messages. Alternatively, when compaction.mode is safeguard, the autoCompactionSummary content should be deduplicated against dedupedNewMessages before ingestion.

Environment

  • OpenClaw 4.29.x
  • lossless-claw extension
  • compaction.mode: "safeguard"

extent analysis

TL;DR

Change the compaction.mode from safeguard to default to prevent duplicate messages.

Guidance

  • Verify that the compaction.mode is set to safeguard in the openclaw.json file.
  • Check the LCM messages table for duplicate user messages.
  • Consider updating the lossless-claw afterTurn hook to skip ingesting dedupedNewMessages that are already covered by autoCompactionSummary.
  • Review the context_items table to ensure that user messages are not duplicated at different ordinals.

Example

{
  "agents": {
    "defaults": {
      "compaction": {
        "mode": "default"
      }
    }
  }
}

Notes

This solution assumes that the issue is caused by the safeguard mode re-injecting compressed messages. If the issue persists after changing the compaction.mode, further investigation into the lossless-claw afterTurn hook or the built-in deduplication module may be necessary.

Recommendation

Apply the workaround by changing the compaction.mode to default, as this is a straightforward solution that has been shown to work.

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