Skip to content
Expedify
Triggers — every way a workflow starts

Module · Someone contacted us

WhatsApp Message Received

Lesson 5 of 10 · 5 min

WhatsApp is where most conversations with customers actually happen, and it behaves differently from web chat in one important way: the conversation is long-lived. The same person messages you in March and again in June, on the same thread.

So the node that starts a WhatsApp workflow does more than hand over a message — it hands over the conversation.

The node to place

Look for “WhatsApp Context Input”, not “WhatsApp Message Received”. The second name exists in the product's internals and has no node on the canvas — you cannot drag it, and a workflow cannot use it. Everything below is whatsapp_context_input, which is what the palette offers and what live workflows are built on.

A worked example

A message arrives, with its history

Click the trigger to see the context settings.

The settings that shape what arrives.

trigger_on

What it holds
Type of message to trigger on One of: all_messages · new_conversations · keywords · intent_based Defaults to all_messages.

keywords

What it holds
Keywords to trigger on (if trigger_on is 'keywords')

intents

What it holds
Intents to trigger on (if trigger_on is 'intent_based')

include_history

What it holds
Include conversation history in output Defaults to true.

history_limit

What it holds
Number of previous messages to include Defaults to 10.

context_aware

What it holds
Enable context awareness for workflow switching Defaults to true.

exclude_campaigns

What it holds
Exclude messages that are replies to campaigns Defaults to false.

integration_id

What it holds
Only fire for messages received via this WhatsApp integration (leave blank for any)

What arrives

The outputs are namespaced under the node's own name, which is unusual enough to be worth listing:

{{whatsappcontextinput_1.message_text}}

Holds
What they sent.

{{whatsappcontextinput_1.phone_number}}

Holds
Who sent it.

{{whatsappcontextinput_1.contact}}

Holds
The matched CRM contact, if there is one.

{{whatsappcontextinput_1.conversation}}

Holds
The thread this belongs to.

{{whatsappcontextinput_1.conversation_history}}

Holds
Earlier messages, up to history_limit.

The contact lookup is the quietly useful one. A phone number arrives; the node has already tried to match it to someone in your CRM, so the workflow can greet a known customer by name without a lookup step.

History comes as standard here

Where the web-chat trigger has memory switched off by default, this one has include_history and context_aware on. That reflects the medium: a WhatsApp thread has a past whether you asked for one or not, and answering the latest message without it produces the behaviour everyone recognises from bad support bots.

history_limit defaults to 10. Raise it for a genuinely conversational agent, lower it if the thread is long and the prompt is getting expensive — the same budget argument as web chat, just with a different default.

Filtering what starts a run

  • trigger_on — every message, or only ones that begin a new conversation. New-conversations-only is how you build a greeting that does not fire on every reply.
  • keywords and intents — narrow the trigger to particular messages, the same way the web-chat trigger does.
  • exclude_campaigns — ignore replies to your own outbound campaigns. Worth turning on when a campaign is running, or every “STOP” and “thanks” starts your support workflow.

What WhatsApp requires before any of this works

This is the wall people hit, and it is not a workflow problem. Receiving WhatsApp messages needs a connected provider — an integration on the integration_id field, set up by a person, not by a workflow. Sending has its own rules on top: outside a 24-hour window from the customer's last message, you may only send an approved template, not free text. Build and test on web chat first if you can; the workflow logic is identical and nothing is gated.

Try it

  1. Place a WhatsApp Context Input and confirm it asks you to choose an integration — that requirement is the lesson.
  2. Set trigger_on to new conversations and think about what should differ between a first message and a reply.
  3. Write a note containing {{whatsappcontextinput_1.message_text}} and the matched contact, so you can see what the node resolved.
  4. Raise history_limit and look at what conversation_history actually contains — it is what an agent would be reading.

Next: the inbound voice call — the same family again, with the shortest fuse of all.