Skip to content

fix(telegram): exclude bot messages from DM chat window to prevent duplicate assistant entries#100580

Closed
zhangqueping wants to merge 0 commit into
openclaw:mainfrom
zhangqueping:fix/issue-99117-telegram-dm-duplicate-assistant-context
Closed

fix(telegram): exclude bot messages from DM chat window to prevent duplicate assistant entries#100580
zhangqueping wants to merge 0 commit into
openclaw:mainfrom
zhangqueping:fix/issue-99117-telegram-dm-duplicate-assistant-context

Conversation

@zhangqueping

@zhangqueping zhangqueping commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Problem: In Telegram DM conversations, the same assistant reply appears twice in the prompt context — once from the session transcript (with directive tags like [[reply_to_current]]) and once from the Telegram message cache (the plain delivered message). The existing deduplication uses raw timestamp_ms:body which fails when the two copies differ in directive tags.

Solution: Normalize body text in resolvePromptContextTextDedupeKey by stripping inline directive tags via stripInlineDirectiveTagsForDelivery before building the dedupe key. This allows the existing session/cache merge logic to deduplicate on visible text while preserving timestamp alignment — the cache-backed Telegram row wins over the synthetic transcript row.

What changed: Modified resolvePromptContextTextDedupeKey to strip directive tags from the body before computing the dedupe key. Added a handler-level regression test that writes assistant transcript context with tagged text, exercises the full Telegram inbound handler path, and asserts a single deduplicated cache entry.

What did NOT change: The session/cache merge logic, timestamp alignment, message ordering, group context building, and all non-dedupe code paths.

Fixes #99117

What Problem This Solves

Users in Telegram DMs see duplicated assistant context in the prompt when the assistant used directive tags:

#session:6325109d ... OpenClaw: [[reply_to_current]]Yep — I'm here now...   ← transcript
#736 ... OpenClaw: Yep — I'm here now...                                    ← cache

After the fix, the session transcript entry (with [[reply_to_current]]) and the cache entry (plain text) produce the same dedupe key timestamp_ms:Yep — I'm here now., so the cache-backed Telegram row survives and the synthetic transcript row is filtered out.

Root Cause

resolvePromptContextTextDedupeKey used message.body.trim() directly as the text component of the dedupe key without stripping directive tags. Session transcript entries carry inline directive tags (e.g. [[reply_to_current]]) that the delivered Telegram message lacks. The :body portion of the dedupe key differed, so the two entries were treated as distinct and both appeared in the merged prompt context.

Real behavior proof

Behavior addressed: Assistant messages with directive tags are deduplicated against cache entries with the same visible text.

Real environment tested: Linux x64, Node v24.13.1, openclaw/openclaw main

Exact steps or command run after this patch:

The regression test exercises the full handler path:

  1. Writes assistant transcript context with [[reply_to_current]]-tagged text
  2. Creates a Telegram message cache entry via reply_to_message
  3. Runs the handler, builds prompt context
  4. Asserts a single deduplicated entry with the cache-backed message_id
node scripts/run-vitest.mjs extensions/telegram/src/bot.test.ts -- -t "dedupes direct assistant transcript context"

After-fix evidence:

The test expects exactly one message matching the visible reply text, no directive tags in the final payload, and no session:-prefixed ids:

expect(messages).toEqual([
  expect.objectContaining({
    body: "Yep - I'm here now.",
    is_reply_target: true,
    message_id: "736",
    sender: "OpenClaw",
  }),
]);
expect(messages.filter((m) => m.body === visibleReply)).toHaveLength(1);
expect(JSON.stringify(messages)).not.toContain("[[reply_to_current]]");
expect(messages.some((m) => String(m.message_id).startsWith("session:"))).toBe(false);

Observed result after the fix: The handler-level regression test passes, confirming that the session transcript entry with [[reply_to_current]]Yep — I'm here now. is deduplicated against the cache entry with Yep — I'm here now.. Only one message remains in the conversation context, it uses the cache-backed message_id: "736" (not a synthetic session: id), and no directive tags appear in the final payload.

What was not tested: Live Telegram bot end-to-end scenario — not available in this environment. The regression test exercises the full handler-to-prompt-context path with real session store and message cache fixtures.

Risk checklist

merge-risk: Low

  • Low risk — 2-line change to the existing dedupe key function, using the same stripInlineDirectiveTagsForDelivery already used across the codebase
  • Only affects deduplication — when tags differ between transcript and cache, entries that were incorrectly distinct now merge correctly
  • Timestamp alignment preserved — entries with different timestamps remain distinct
  • Handler-level regression test covers the full prompt-context path
  • No lockfile or dependency changes

@zhangqueping

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot added the channel: telegram Channel integration: telegram label Jul 6, 2026
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@zhangqueping
zhangqueping force-pushed the fix/issue-99117-telegram-dm-duplicate-assistant-context branch from 2c70a1c to c7ded4c Compare July 6, 2026 03:35
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 2:06 AM ET / 06:06 UTC.

Summary
The PR strips inline directive tags from Telegram prompt-context dedupe keys and adds a handler-level regression test for directive-tagged assistant transcript rows versus cached Telegram replies.

PR surface: Source +5, Tests +97. Total +102 across 2 files.

Reproducibility: yes. source-reproducible: current main builds raw session transcript rows and cache rows, then dedupes by exact timestamp/body, so directive-tagged transcript text can survive beside a visible-equivalent cache row. I did not run a live Telegram scenario in this read-only review.

Review metrics: 1 noteworthy metric.

  • Prompt-Context Dedupe Key: 1 function changed. This function decides whether Telegram cache rows suppress synthetic session transcript rows before model-visible context is assembled.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #99117
Summary: This PR is a candidate fix for the canonical Telegram DM duplicate assistant prompt-context issue; overlapping unmerged PRs propose nearby fix shapes, while the earlier merged timestamp fix covers an adjacent duplicate class.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Add redacted live Telegram proof, a short recording, logs, or diagnostic handler output showing one cache-backed assistant context row after a directive-tagged assistant reply; redact IPs, API keys, phone numbers, private endpoints, and other private details.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body describes a handler regression test and CI-style evidence, but external Telegram reply-context PRs still need redacted live Telegram proof, a recording, logs, copied runtime output, or diagnostic handler output before merge; after adding proof, updating the PR body should trigger re-review, or a maintainer can comment @clawsweeper re-review. 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.

Mantis proof suggestion
A Telegram live proof can show whether a DM follow-up after a directive-tagged assistant reply produces one model-visible assistant context row. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram live proof: verify that a Telegram DM follow-up after an assistant reply using [[reply_to_current]] includes only one prior visible assistant context row.

Risk before merge

  • [P1] Real Telegram behavior remains unproven; the submitted evidence is handler regression test/CI proof rather than a redacted live Telegram run or diagnostic runtime output.
  • [P1] Several open candidate PRs target the same canonical issue, so maintainers should land one canonical dedupe shape and avoid merging overlapping variants.

Maintainer options:

  1. Require Real Telegram Or Diagnostic Proof (recommended)
    Keep the branch open but do not merge until the PR body includes redacted live Telegram proof, a recording, logs, or diagnostic handler output showing one cache-backed assistant context row after a directive-tagged reply.
  2. Pick One Canonical Candidate
    If maintainers prefer another open branch for the same issue, keep this PR open only until that branch has proof or lands, then close the duplicate with provenance.
  3. Accept Test-Only Proof Risk
    Maintainers could merge based on handler regression coverage alone, but they would own the remaining uncertainty in model-visible Telegram session context behavior.

Next step before merge

  • [P1] No automated repair is appropriate because the remaining blocker is contributor or maintainer real behavior proof, not a narrow code defect.

Security
Cleared: No security or supply-chain concern found; the diff only changes Telegram prompt-context dedupe logic and tests, with no dependency, workflow, credential, permission, download, or lifecycle-hook changes.

Review details

Best possible solution:

Keep this PR open until a linked canonical PR proves it covers this PR's unique work, or a maintainer confirms closure.

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

Yes, source-reproducible: current main builds raw session transcript rows and cache rows, then dedupes by exact timestamp/body, so directive-tagged transcript text can survive beside a visible-equivalent cache row. I did not run a live Telegram scenario in this read-only review.

Is this the best way to solve the issue?

Yes. Normalizing the body inside the existing timestamp-preserving session/cache dedupe key is narrower than filtering cache messages or dropping timestamps, and it preserves the cache-row preference because cache keys are built before session rows are filtered.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P2: The PR targets a bounded Telegram prompt-context duplication bug with limited channel blast radius and no crash, security bypass, or full workflow outage.
  • merge-risk: 🚨 session-state: The diff changes which Telegram assistant history source survives into model-visible prompt context when session transcript and cache rows overlap.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • 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 a handler regression test and CI-style evidence, but external Telegram reply-context PRs still need redacted live Telegram proof, a recording, logs, copied runtime output, or diagnostic handler output before merge; after adding proof, updating the PR body should trigger re-review, or a maintainer can comment @clawsweeper re-review. 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.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The change affects Telegram DM context behavior that can be demonstrated with a short live Telegram proof run after a directive-tagged assistant reply.
Evidence reviewed

PR surface:

Source +5, Tests +97. Total +102 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 7 2 +5
Tests 1 99 2 +97
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 106 4 +102

What I checked:

  • PR close coverage proof: PR close coverage proof kept this PR open against fix: Telegram replies duplicate recent context after sent replies #98769: PR B is related and merged, but the source report explicitly identifies it as an adjacent partial overlap that did not cover PR A's directive-tag body-mismatch work.
  • linked superseding PR: fix: Telegram replies duplicate recent context after sent replies #98769 (fix: Telegram replies duplicate recent context after sent replies) is merged at 2026-07-02T05:15:11Z.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • mikasa0818: Authored merged PR 95390, which added direct Telegram session-transcript prompt-context support and touched the same handler/test surface. (role: feature introducer; confidence: high; commits: d0159e522cd3, 4e8f2268e038, cfe42294fc07; files: extensions/telegram/src/bot-handlers.runtime.ts, extensions/telegram/src/bot.test.ts, extensions/telegram/src/session-transcript-context.ts)
  • obviyus: Authored the final tightening commit in merged PR 95390 and is tied to the same Telegram session/cache prompt-context path. (role: recent area contributor and merger; confidence: high; commits: ec4b75dab0bf; files: extensions/telegram/src/bot-handlers.runtime.ts, extensions/telegram/src/session-transcript-context.ts, extensions/telegram/src/message-cache.ts)
  • rabsef-bicrym: Authored merged PR 98769, the adjacent Telegram duplicate-context timestamp-alignment fix that this PR must preserve. (role: adjacent fix author; confidence: medium; commits: 467d09b4edb4; files: extensions/telegram/src/message-cache.ts, extensions/telegram/src/outbound-message-context.ts, extensions/telegram/src/bot-message-dispatch.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.
Review history (2 earlier review cycles)
  • reviewed 2026-07-06T03:52:24.238Z sha c7ded4c :: needs real behavior proof before merge. :: [P2] Dedupe bot replies instead of dropping the cache copy | [P2] Add braces around the new early returns
  • reviewed 2026-07-06T04:45:38.052Z sha 3ba5d20 :: needs real behavior proof before merge. :: [P2] Dedupe at the session/cache merge

@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. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. labels Jul 6, 2026
@clawsweeper
clawsweeper Bot temporarily deployed to qa-live-shared July 6, 2026 04:48 Inactive
@zhangqueping
zhangqueping force-pushed the fix/issue-99117-telegram-dm-duplicate-assistant-context branch from 3ba5d20 to 0f9e093 Compare July 6, 2026 05:51
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 6, 2026
@zhangqueping
zhangqueping force-pushed the fix/issue-99117-telegram-dm-duplicate-assistant-context branch from 0f9e093 to 936136a Compare July 7, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram mantis: telegram-visible-proof Mantis should capture Telegram visible proof. 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: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. 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.

[Bug]: Telegram prompt context includes duplicate assistant entries from session transcript + channel cache

1 participant