Skip to content

feat(chatwoot-adapter): relay the operator's own outbound sends to Chatwoot (#615)#29

Merged
rmyndharis merged 1 commit into
mainfrom
feat/chatwoot-relay-own-sends
Jul 3, 2026
Merged

feat(chatwoot-adapter): relay the operator's own outbound sends to Chatwoot (#615)#29
rmyndharis merged 1 commit into
mainfrom
feat/chatwoot-relay-own-sends

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

Summary

Relays the operator's own outbound WhatsApp messages — composed on a linked phone, the WhatsApp mobile app, or the OpenWA REST API — into the mapped Chatwoot conversation as outgoing messages, so an ongoing thread stops looking one-sided (#615).

Problem

The adapter only subscribed to message:received and dropped every fromMe message. WhatsApp delivers messages composed on a linked device through a different path (message:sent), so an operator replying from their phone alongside Chatwoot produced a broken, one-sided thread — the contact's replies showed, the operator's phone messages never did.

Changes

  • Relay own sends. Subscribe to message:sent and post fromMe messages as Chatwoot outgoing, into the contact's existing mapped conversation. Gated by a new relayOwnMessages setting (default on; turn it off to keep phone-composed messages out of the helpdesk).
  • Relay-into-existing only. An own send to a chat that isn't mapped yet is skipped rather than opening a new conversation. This avoids splitting a contact who has migrated to @lid — whose @c.us mapping isn't always resolvable — into a duplicate; the chat still appears once the contact replies.
  • Echo-suppression. An agent's own Chatwoot reply is also fromMe and returns on message:sent. The outbound path marks the WhatsApp id it sent and the own-send handler skips anything already seen, serialized on a per-chat lock.
  • @lid migration. A send to a migrated contact resolves to the @lid address, so message:sent carries chatId=@lid while the mapping is keyed @c.us. The handler canonicalizes the chat id (ctx.engine.canonicalChatId) for the lock key and does a dual lookup (raw then canonical), so a resolvable migrated contact's send lands in its existing conversation.
  • Media/robustness. Type-based placeholders for caption-less media sends (photo/video/audio/document) so they never post an empty bubble, and a defensive log when a send returns no message id.

Compatibility

Version 0.4.0; minOpenWAVersion 0.8.7 (uses the new canonicalChatId host capability). Existing behavior is unchanged for inbound relay, outbound agent replies, and handover.

…atwoot (#615)

Messages composed on a linked phone / the WhatsApp app / the OpenWA API arrive
on message:sent (not message:received) and were never relayed, so an ongoing
Chatwoot thread went one-sided. Subscribe to message:sent and relay fromMe
messages as 'outgoing' into the contact's EXISTING mapped conversation, gated
by a new relayOwnMessages setting (default on). An own send to a chat not yet
mapped is skipped (never creates a conversation), so a contact WhatsApp has
migrated to @lid can't be split off into a duplicate.

Echo-suppression: the adapter's own Chatwoot-agent replies also surface on
message:sent, so outbound.relay marks the WA id it sent and handleSent skips
anything already seen, serialized on a per-chat lock keyed by the canonical
(@lid-resolved) chat id.

@lid migration: a send to a migrated contact resolves to the @lid address, so
message:sent carries chatId=@lid while the mapping is keyed @c.us. handleSent
canonicalizes the chat id (ctx.engine.canonicalChatId, best-effort) for the
lock key and does a dual lookup (raw then canonical) so a resolvable migrated
contact's send lands in its existing conversation. Requires OpenWA 0.8.7.

Also: type-based placeholders for caption-less media sends (photo/video/etc)
so they never post an empty bubble, and a defensive log when a send returns no
message id.
@rmyndharis rmyndharis merged commit 3326dce into main Jul 3, 2026
1 check passed
@rmyndharis rmyndharis deleted the feat/chatwoot-relay-own-sends branch July 3, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant