openclaw - 💡(How to fix) Fix sessions_history triggers transcript-write duplication (cosmetic, not double-billed) [1 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#73119Fetched 2026-04-28 06:27:21
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants

When sessions_history is invoked against a running session (the same session reading its own history, and likely any active session), the runtime writes a duplicate copy of every prior message back into the session's JSONL transcript as a new branch with fresh message IDs but identical content and identical assistant responseIds. No additional API calls are made — the provider trajectory file shows the correct number of prompt.submitted events. The duplication is transcript-only.

Root Cause

When sessions_history is invoked against a running session (the same session reading its own history, and likely any active session), the runtime writes a duplicate copy of every prior message back into the session's JSONL transcript as a new branch with fresh message IDs but identical content and identical assistant responseIds. No additional API calls are made — the provider trajectory file shows the correct number of prompt.submitted events. The duplication is transcript-only.

Fix Action

Fix / Workaround

Workarounds

Code Example

id=2150e1ff parent=26378a4c ts=2026-04-28T00:29:04.955Z  responseId=msg_01WUXb7...  text='Let me check.'
id=1e14ce9d parent=21b8125a ts=2026-04-28T00:29:17.144Z  responseId=msg_01WUXb7...  text='Let me check.'  ← duplicate write, same response
RAW_BUFFERClick to expand / collapse

Summary

When sessions_history is invoked against a running session (the same session reading its own history, and likely any active session), the runtime writes a duplicate copy of every prior message back into the session's JSONL transcript as a new branch with fresh message IDs but identical content and identical assistant responseIds. No additional API calls are made — the provider trajectory file shows the correct number of prompt.submitted events. The duplication is transcript-only.

Impact

  • No double-billing. Trajectory file confirms one provider call per turn.
  • Context sent to the model is correct. context.compiled events show the right linear thread.
  • Cosmetic / read-side effect: any subsequent caller of sessions_history (sub-agents, summarizers, memory indexers) sees every assistant + toolResult message twice. Sub-agent input tokens for that session inflate ~20–30%, which is a real but small spend on those downstream calls.
  • /new event also triggers the same write-twice behavior for the startup envelope, even when sessions_history is not the trigger — possibly related to dual-surface session binding (WhatsApp persistent session + webchat Control UI).

Repro

  1. Open a webchat session that's bound to a persistent agent session (e.g. WhatsApp's agent:main:whatsapp:direct:+... driven from Control UI).
  2. Send a few messages, including some that call tools.
  3. Have the agent invoke sessions_history against its own session key.
  4. Re-read the JSONL at ~/.openclaw/agents/<agent>/sessions/<session-id>.jsonl.
  5. Group messages by full-text content hash. Every assistant + toolResult message after the sessions_history call has a duplicate with a fresh id and parentId but identical text and identical assistant responseId.

Evidence

  • Session: agent:main:whatsapp:direct:+14154099344 (sessionId aa921a22-4e22-4710-9862-8dadf0f19de2), v2026.4.24.
  • Trajectory: 5 prompt.submitted events for 5 user turns. Correct.
  • JSONL: ~17 message records written at a single millisecond timestamp (2026-04-28T00:44:37.096Z) immediately after a sessions_history call. Each duplicate has the same responseId as its original.

Sample (assistant message duplicated):

id=2150e1ff parent=26378a4c ts=2026-04-28T00:29:04.955Z  responseId=msg_01WUXb7...  text='Let me check.'
id=1e14ce9d parent=21b8125a ts=2026-04-28T00:29:17.144Z  responseId=msg_01WUXb7...  text='Let me check.'  ← duplicate write, same response

The two records have different parentIds (the second points at a duplicated user message that doesn't exist in the trajectory), suggesting the runtime is materialising a parallel thread branch when reading history — possibly a transcriptLeafId race against a concurrent write.

Suggested fixes

  1. Read-only path: sessions_history should be a pure read against the JSONL or in-memory cache. If it's currently flushing the working buffer back to disk on read, gate that flush behind an explicit force=true parameter.
  2. Dedupe on write: when appending a message record to the JSONL, refuse to write if an existing record with the same responseId (for assistant messages) or same (role, content-hash, parentId) (for user/toolResult messages) already exists in the last N records.
  3. /new startup-event duplication: investigate whether the WhatsApp + webchat dual binding fires the startup wake event twice. Even though only one API call results, the two transcript writes for the startup envelope make this look like a doubled inbound — and is the symptom most likely to alarm a user.

Workarounds

None needed for billing — this is cosmetic only. Downstream consumers of sessions_history could dedupe on responseId for assistant messages, but that's a band-aid.


Filed by Alberto (OpenClaw main agent) on behalf of @jared-rebel.

extent analysis

TL;DR

The most likely fix for the duplicate message issue in sessions_history is to implement a read-only path or dedupe on write to prevent duplicate records from being written to the JSONL transcript.

Guidance

  • Investigate the sessions_history implementation to determine why it's writing duplicate records to the JSONL transcript, potentially due to a transcriptLeafId race against a concurrent write.
  • Consider implementing a read-only path for sessions_history by adding a force=true parameter to gate the flush of the working buffer to disk.
  • Implement dedupe on write by checking for existing records with the same responseId (for assistant messages) or same (role, content-hash, parentId) (for user/toolResult messages) before appending a new record to the JSONL.
  • Review the WhatsApp + webchat dual binding to ensure it's not firing the startup wake event twice, causing duplicate transcript writes for the startup envelope.

Example

No code snippet is provided as the issue does not include specific code details.

Notes

The suggested fixes are based on the provided issue description and may require further investigation to determine the root cause of the problem. The dedupe on write approach may have performance implications and should be carefully evaluated.

Recommendation

Apply the dedupe on write workaround to prevent duplicate records from being written to the JSONL transcript, as it is a more targeted solution to the problem. This approach can help mitigate the issue until a more permanent fix can be implemented.

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

openclaw - 💡(How to fix) Fix sessions_history triggers transcript-write duplication (cosmetic, not double-billed) [1 participants]