Skip to content

[Chatwoot Integration] Self-sent messages from linked WhatsApp app appear as outgoing instead of private notes #2446

@39elbarto

Description

@39elbarto

Describe the bug

When using Evolution API with Chatwoot integration, messages sent directly from the linked WhatsApp mobile app (not via Chatwoot) are incorrectly classified as regular outgoing messages. This causes confusion in the Chatwoot conversation timeline because:

  1. Agents see messages they sent externally as "outgoing" public messages
  2. No visual distinction between Chatwoot-originated vs app-originated messages
  3. Conversation history becomes misleading for audit/training purposes

Expected behavior

Messages sent from the linked WhatsApp app should be:

  1. Classified as incoming type (or a new private type)
  2. Marked as private notes in Chatwoot (not visible to customers)
  3. Prefixed with an identifier like [Sent from WhatsApp app] for agent clarity

Actual behavior

Self-sent messages appear as regular outgoing messages in Chatwoot with no distinction from messages sent via the Chatwoot UI.

Environment

Component Version
Evolution API v2.3.7 (develop branch)
Chatwoot v3.13.x
Deployment Docker Compose
Database PostgreSQL 16
Node.js 20.x

Reproduction steps

  1. Set up Evolution API with Chatwoot integration enabled
  2. Link a WhatsApp account via QR code
  3. From the linked phone's WhatsApp app, send a message to any contact
  4. Observe the message in Chatwoot conversation view

Current (buggy) behavior:

  • Message appears as outgoing message in Chatwoot
  • No indication it was sent from the app vs Chatwoot UI

Expected behavior after fix:

  • Message appears as private note with prefix [Sent from WhatsApp app]
  • Agents can see context without confusing the conversation transcript

Root cause analysis

The issue is in src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts:

  1. body.key.fromMe === true is used to determine if message is outgoing
  2. However, fromMe is true for BOTH:
    • Messages sent via Chatwoot (API-originated) → source: 'web'
    • Messages sent from linked WhatsApp app → source is NOT 'web'

The current code doesn't distinguish between these two cases.

Proposed fix

// Detect if message was sent from linked WhatsApp app (not via API/web)
const sentFromWhatsAppApp = body.key.fromMe && body.source !== 'web';

// Reclassify: app-originated messages should be incoming (for private note treatment)
const messageType: 'incoming' | 'outgoing' = body.key.fromMe && !sentFromWhatsAppApp ? 'outgoing' : 'incoming';

// Add prefix for clarity when displayed in Chatwoot
const addSentFromPrefix = (text?: string): string => {
  const normalizedText = text || '';
  return sentFromWhatsAppApp
    ? `📱 [Sent from WhatsApp app]${normalizedText ? `\n${normalizedText}` : ''}`
    : normalizedText;
};

Additionally, when sentFromWhatsAppApp is true:

  • Set message as private note in Chatwoot payload
  • Apply the prefix to message content

Additional context

This fix has been deployed in production on our infrastructure since February 2026 and is working correctly. The change preserves full agent visibility into what was sent externally while preventing confusion in conversation transcripts.

We're happy to submit a PR if this aligns with the project's roadmap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions