Skip to content

Proactive DMs mint a new conversation after the OpenClaw harness cutover #957

Description

@chughtapan

Split out of #926 as an accepted, deferred regression rather than left as a bullet in a PR body.

What changes

The OpenClaw harness cutover deletes MoltZapService.sendToAgent and the agentConversationCacheRef it maintained. That cache is what made repeated proactive DMs to the same agent land in one conversation.

Outbound on the harness path is HarnessClient.startConversation(names, initialContent), and moltzapd.ts → startConversationForHarness calls agentConversationCreate unconditionally. So after the cutover, every proactive DM to the same peer creates a new conversation.

Why it is being taken rather than fixed inline

Three options were considered:

  • (a) Drop conv:<id> outbound and accept the regression. ← current state
  • (b) Drop conv:<id> outbound but add a reuse-existing-1:1 lookup inside start_conversation.
  • (c) Widen the reply tool to accept an explicit conversationId.

(c) is off the table: 20260728-model-surface-is-start-reply-listen states there is no generic send, and a conversationId-bearing reply is generic send by another name.

(b) is the right end state and is what this issue tracks. It was deferred so the cutover could land as one atomic shape change.

Fix recipe

Inside startConversationForHarness (packages/client/src/moltzapd.ts), before calling agentConversationCreate: when the participant set is exactly [self, one-other], search existing conversations for a matching two-member conversation and return it instead of creating one.

conversationSearch is already wired into the daemon's MCP surface by the read plane, so the lookup needs no new protocol method. Note the existing two-member read semantics — client already treats a two-member conversation as direct (see 5af93a09 fix(client): read a two-member conversation as direct).

Acceptance

A test that calls startConversation([peer], text) twice for the same peer and asserts both messages land in the same ConversationId.

Provenance

Maintainer decision, 2026-08-04: "Proactive DMs; that's fine. lets deal with that later."

Metadata

Metadata

Assignees

No one assigned

    Labels

    v2Aligned input to the v2 track

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions