Skip to content

fix(auto-reply): prevent duplicate transcript entries for followup queue messages#17340

Closed
Facens wants to merge 1 commit into
openclaw:mainfrom
Facens:fix/followup-queue-duplicate-transcript
Closed

fix(auto-reply): prevent duplicate transcript entries for followup queue messages#17340
Facens wants to merge 1 commit into
openclaw:mainfrom
Facens:fix/followup-queue-duplicate-transcript

Conversation

@Facens

@Facens Facens commented Feb 15, 2026

Copy link
Copy Markdown

Summary

  • Bug: When messages arrive while the agent is busy (followup queue), the assistant response is written to the session transcript twice — once by the embedded agent during its normal run, and once by the delivery-mirror mechanism in routeReply. This produces duplicate assistant messages in the transcript, which can confuse the model on subsequent interactions.
  • Fix: Add mirror: false to the routeReply call inside sendFollowupPayloads in src/auto-reply/reply/followup-runner.ts. Since the agent already persists its response in the session transcript, the delivery-mirror copy is redundant for followup queue messages.
  • Change: One-line addition — mirror: false parameter to the existing routeReply({ ... }) call at line 97.

Details

routeReply accepts an optional mirror parameter (defined in src/auto-reply/reply/route-reply.ts). When mirror is not explicitly false and a sessionKey is provided, the reply is mirrored into the session transcript. For followup queue runs, sessionKey is always provided (line 94: sessionKey: queued.run.sessionKey), so the mirror fires unconditionally. But the embedded agent that processes the followup already saves the response to the transcript as part of its normal execution, creating the duplicate.

Setting mirror: false disables only the delivery-mirror copy; the agent's own transcript persistence is unaffected.

Test plan

  • Send a message while the agent is processing another request (trigger followup queue)
  • Verify the assistant response appears exactly once in the session transcript
  • Verify the reply is still delivered to the originating channel
  • Verify that non-followup routeReply calls (which do not set mirror: false) continue to mirror as before

Contribution checklist

  • Local validation: pnpm build && pnpm check && pnpm test — all passing
  • Focused scope: single bug fix, one-line change
  • Clear "what" + "why" in description
  • AI-assisted (Claude Code) — fully tested, code reviewed and understood by author

🤖 Generated with Claude Code

Greptile Summary

Adds mirror: false parameter to routeReply call in followup queue handler to prevent duplicate assistant responses in session transcripts. The embedded agent already persists its response during execution, so the delivery-mirror copy is redundant for followup messages.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Single-line focused fix that addresses a clear duplication bug. The change is well-documented, has existing test coverage for the mirror: false behavior (route-reply.test.ts:380-395), and doesn't affect other call sites. The embedded agent's transcript persistence is independent of the mirror mechanism.
  • No files require special attention

Last reviewed commit: 5c74271

(4/5) You can add custom instructions or style guidelines for the agent here!

…eue messages

When messages arrive while the agent is busy, the followup queue
processes them and routes the response via routeReply. The delivery-mirror
mechanism in routeReply writes the assistant response to the session
transcript, but the embedded agent already persists the response during
its normal run. This causes duplicate assistant messages in the transcript,
which can confuse the model on subsequent interactions.

Add mirror: false to the routeReply call in sendFollowupPayloads to
suppress the redundant delivery-mirror copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Mar 15, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #pr-thunderdome-dangerzone on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: XS stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants