Skip to content

fix(telegram): duplicate assistant messages in conversation context#100333

Closed
crabkun wants to merge 1 commit into
openclaw:mainfrom
crabkun:fix/context-dedup-body-only
Closed

fix(telegram): duplicate assistant messages in conversation context#100333
crabkun wants to merge 1 commit into
openclaw:mainfrom
crabkun:fix/context-dedup-body-only

Conversation

@crabkun

@crabkun crabkun commented Jul 5, 2026

Copy link
Copy Markdown

What Problem This Solves

Fixes an issue where users sending messages via Telegram would receive duplicate assistant replies in the conversation context passed to the model, doubling token usage and potentially confusing the model with repeated entries.

Each assistant reply appears twice: once from the session transcript (with a session:-prefixed message ID) and once from the Telegram message cache (with the actual Telegram message ID). Both carry the same visible text but slightly different timestamps, causing the dedup key to differ and both copies to be retained.

Why This Change Was Made

The dedup key in resolvePromptContextTextDedupeKey was timestamp_ms:body, which fails when the same assistant text appears in both sources with timestamps differing by milliseconds (session transcript gets the generation timestamp, Telegram cache gets the delivery timestamp).

This change removes the timestamp component from the dedup key, using only the message body text. The overall dedup logic (removing session-transcript entries that already exist in the Telegram cache) remains unchanged; only the matching criterion is tightened.

User Impact

  • Telegram users no longer receive duplicated assistant replies in the model conversation context
  • Token usage is reduced for every turn that previously carried duplicates
  • No impact on non-Telegram channels or message delivery

Evidence

  • Reproduced before fix: every assistant turn produced a #message_id entry and a #session:<id> entry with identical text in the model context
  • After fix: verified with multiple message exchanges that assistant replies appear exactly once in the context, while legitimate session-only narration entries (e.g., tool progress text) are preserved correctly
  • Tested on OpenClaw 2026.7.1-beta.1 with deepseek/deepseek-v4-pro

The dedup key was `timestamp_ms:body` which fails when the same
assistant reply appears in both the session transcript and the
Telegram message cache with slightly different timestamps.

Using body-only dedup prevents duplicate entries in the
conversation context passed to the model.
@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: XS labels Jul 5, 2026
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 9:36 AM ET / 13:36 UTC.

Summary
The PR changes Telegram prompt-context text deduplication to use only trimmed message body instead of timestamp plus body.

PR surface: Source -3. Total -3 across 1 file.

Reproducibility: yes. at source level. The PR makes the key only body text, and that key directly controls whether session transcript rows are removed before Telegram prompt context is sent to the model.

Review metrics: 1 noteworthy metric.

  • Dedupe Key Fields: 1 removed, 0 added. The PR removes timestamp from the key that decides whether session transcript rows remain in model-visible Telegram context.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Replace body-only matching with a timestamp/assistant-identity-safe dedupe repair.
  • [P1] Add focused regression coverage for repeated same-text distinct turns and the duplicate assistant context shape.
  • [P1] Attach redacted live Telegram prompt-context proof or logs after the repair.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body describes testing but does not include inspectable after-fix proof such as redacted logs, terminal output, a trajectory, screenshot, recording, or linked artifact. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging the body-only key can silently drop distinct session transcript rows whenever another Telegram cache row has the same text, changing model-visible context for Telegram users.
  • [P1] The PR lacks inspectable after-fix real behavior proof for the Telegram prompt-context path.
  • [P1] The open canonical directive-tag duplicate-context issue likely needs a narrower normalized assistant-cache match rather than a global body-only key.

Maintainer options:

  1. Require A Narrow Context Dedupe Fix (recommended)
    Replace the body-only key with a timestamp/assistant-identity-safe repair and focused regression coverage before reconsidering merge.
  2. Close After Canonical PR Lands
    If the broader linked candidate lands with proof, close this branch as superseded rather than merging a competing dedupe rule.
  3. Waive The Session-State Risk
    Maintainers could intentionally accept body-only matching, but that owns possible loss of repeated same-text context rows.

Next step before merge

  • [P1] Contributor or maintainer follow-up is needed because the code direction is too broad and missing proof cannot be supplied by an automated repair lane.

Security
Cleared: No concrete security or supply-chain concern found; the diff is limited to Telegram runtime code and adds no dependencies, workflows, permissions, credentials, downloads, or lifecycle hooks.

Review findings

  • [P1] Preserve timestamp and identity in prompt dedupe — extensions/telegram/src/bot-handlers.runtime.ts:193
Review details

Best possible solution:

Keep timestamp and sender/assistant identity as part of the dedupe safety boundary, then fix the remaining duplicate-context case with narrow normalized assistant-cache matching and live Telegram proof.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level. The PR makes the key only body text, and that key directly controls whether session transcript rows are removed before Telegram prompt context is sent to the model.

Is this the best way to solve the issue?

No. Body-only matching is broader than the known duplicate-context problem; the safer fix is a narrow normalized assistant/cache match that preserves timestamp and identity guardrails.

Full review comments:

  • [P1] Preserve timestamp and identity in prompt dedupe — extensions/telegram/src/bot-handlers.runtime.ts:193
    This changes the key to just the trimmed body, so any cache row with the same text suppresses a session transcript row regardless of timestamp or sender. Since buildPromptContextForMessage uses this key to remove sessionPromptMessages before building model context, repeated replies like "OK" on different turns, or same-text user/cache rows, can erase legitimate history. Keep the timestamp/identity guardrail and add a narrow normalized assistant-cache match for the real drift/directive case instead.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against db96218c0562.

Label changes

Label justifications:

  • P2: This is a bounded Telegram prompt-context bugfix PR with limited channel blast radius, but it is not a crash, security bypass, or full workflow outage.
  • merge-risk: 🚨 session-state: The diff changes which Telegram session/cache prompt rows are retained or dropped in model-visible conversation context.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body describes testing but does not include inspectable after-fix proof such as redacted logs, terminal output, a trajectory, screenshot, recording, or linked artifact. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source -3. Total -3 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 1 4 -3
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 1 4 -3

What I checked:

Likely related people:

  • Ayaan Zaidi: Recent commits changed Telegram prompt-context and dispatch behavior in the same handler and message-cache area. (role: recent area contributor; confidence: medium; commits: 3ad465d32b3b, 63cbb350566d; files: extensions/telegram/src/bot-handlers.runtime.ts, extensions/telegram/src/message-cache.ts, extensions/telegram/src/bot-message-dispatch.ts)
  • rabsef-bicrym: Authored the merged Telegram outbound context timestamp-alignment fix that overlaps the timestamp-drift duplicate class. (role: adjacent fix author; confidence: high; commits: c8dba85b5d41; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/message-cache.ts, extensions/telegram/src/outbound-message-context.ts)
  • jalehman: Merged the adjacent Telegram duplicate-context timestamp fix that this PR touches conceptually. (role: adjacent merger / reviewer; confidence: medium; commits: c8dba85b5d41; files: extensions/telegram/src/bot-message-dispatch.ts, extensions/telegram/src/message-cache.ts, extensions/telegram/src/outbound-message-context.ts)
  • Peter Steinberger: History shows earlier outbound Telegram reply-cache context work and the current checkout blame on the prompt-context merge file after a large source-tree rewrite. (role: original adjacent cache contributor; confidence: medium; commits: 3cf806d17215, 9c5ea29e384d; files: extensions/telegram/src/outbound-message-context.ts, extensions/telegram/src/send.ts, extensions/telegram/src/message-cache.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026
@steipete

Copy link
Copy Markdown
Contributor

Superseded by the broader maintainer rewrite in #102469, landed as b58029f4fd6c987f575e0cec61e3915513fa5f56.

The canonical fix preserves a single durable projection path for chunked, rich-fallback, media, and streamed Telegram delivery while requiring a complete contiguous projection before suppressing transcript history. Focused Testbox coverage passed 779/779 tests, exact-head CI passed, and native Telegram Desktop Mantis proof passed: https://github.com/openclaw/openclaw/actions/runs/29133087432

Thanks for the contribution and the original reproduction.

@steipete steipete closed this Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants