Skip to content

chat.history: surface idempotencyKey on hydrated user messages for client-side correlation #79844

Description

@datus1982

What

chat.send accepts an idempotencyKey parameter on user messages. The gateway persists this to the transcript (verified at dist/chat-3xUbD00m.js:303: ...params.idempotencyKey ? { idempotencyKey: params.idempotencyKey } : {}) and reads it back via transcriptHasIdempotencyKey() for de-duplication.

But chat.history does NOT include idempotencyKey in the hydrated message envelope it returns. The __openclaw field on user messages from chat.history contains only:

{ "importedFrom": "...", "cliSessionId": "...", "externalId": "..." }

Why it matters

Client-side chat surfaces (LCARS portal /comms; the openclaw control-ui chat tab) want to correlate locally-generated optimistic bubbles with their server-confirmed counterparts. With idempotencyKey echoed:

Client: optimistic bubble generated with idempotencyKey=X
        send → 202 (runId, messageSeq)
        chat.history later returns user msg { content, __openclaw: { externalId, idempotencyKey: X } }
        Client: matches X → resolves the optimistic bubble exactly

Without it, clients fall back to text-equality matching (fragile) or role-FIFO heuristics (interleaving bugs).

Suggested fix

When chat.history hydrates a user message that was sent with idempotencyKey, include it in the __openclaw envelope:

{
  "__openclaw": {
    "importedFrom": "...",
    "cliSessionId": "...",
    "externalId": "...",
    "idempotencyKey": "<the one supplied at send time>"
  }
}

The data is already persisted; this is a hydrate-side change to surface it through the existing wire shape.

Use case

LCARS portal /comms (https://github.com/datus1982/lcars Phase 1 work) currently has a known limitation in pending-pair correlation because of this gap. Documented in commit b613782's message:

Issue #3 deferred — needs gateway-correlation design work (verify whether the gateway echoes idempotencyKey on the persisted user message).

Echoing idempotencyKey would make pending-bubble matching trivial and remove the FIFO-by-role fallback heuristic that has known interleaving edge cases.

Environment

  • openclaw 2026.5.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions