LayBuild has three ways in: the web chat widget, WhatsApp through Meta's Cloud API, and the REST API. There is no Slack, email, SMS, Telegram, Messenger or voice channel. All three channels write to the same conversation and message tables and go through the same agent, so a knowledge base change or a guardrail setting applies everywhere at once. The differences live at the edges: how a customer is identified, what message types are accepted, and what the channel allows you to send back.
This post walks through that shared model, then the places where WhatsApp in particular behaves differently, because those are the ones that surprise teams after launch.
The shared model: one Conversation table with a channel field
Every conversation is a row in one Conversation table. It carries a channel value (WEB, WHATSAPP or API), an optional channelId, a status (OPEN, HANDOFF or CLOSED), the AI agent handling it, an optional assigned human, the organization it belongs to, and the customer's 1 to 5 rating. Messages hang off it in a Message table with a role (USER, ASSISTANT, AGENT for a human teammate, or SYSTEM), the text, a message type, and an externalId for the provider's own message ID.
We chose a single table over per-channel tables because almost everything downstream is channel-blind. Retrieval, the grounding check, PII redaction on output, handoff, CSAT, the audit log and outbound webhooks all work on a conversation and its messages. They do not need to know whether the text arrived over a socket or a Meta webhook.
Web widget (widget.js -> /embed iframe) WhatsApp (Meta Cloud API webhook) REST API
| Socket.io | POST /api/whatsapp/webhook | /api/conversations
v v v
+----------------------------------------------------------------------------------------+
| Conversation (channel, channelId, status, agentId, orgId, rating) + Message rows |
+----------------------------------------------------------------------------------------+
|
v
Message queue -> LangGraph agent (guardrails, retrieve, generate,
grounding check, output guardrail, handoff)
|
+---------------------+----------------------+
v v
Socket.io to the widget and dashboard WhatsApp reply via Cloud APIOn the way out, the reply is saved as an ASSISTANT message and then delivered according to the channel. For web conversations it goes over Socket.io to the widget and to anyone watching in the dashboard. For WhatsApp conversations the same saved reply is also sent through the Cloud API to the customer's number, and the WhatsApp message ID is written back to the message so delivery status updates can find it.
How each channel identifies a customer
The widget identifies a visitor by the name and email they enter, or by a verified email your site passes in with an HMAC hash (the Next.js widget post covers that). WhatsApp identifies a customer by phone number: the first message from a number creates a customer record for it and opens a WHATSAPP conversation whose channelId is that number. Later messages from the same number join the open or handed-off conversation instead of starting a new one.
Those are separate identities. The same person who chats on your website with their email and then messages your WhatsApp number shows up as two customers with two conversation histories. LayBuild does not merge them. That matters for long-term memory, which is stored per customer: facts the agent learned about someone on the widget are not available when they write on WhatsApp.
Where WhatsApp differs
Only text gets an AI answer
WhatsApp messages of type image, audio, voice note or video are not processed. LayBuild saves a placeholder message so your team can see something arrived, replies to the customer with a fixed notice that media is not supported on this channel, and stops. The agent never sees the content.
Text messages go to the agent. Button and list replies are converted to their title text. Documents, locations and contact cards are turned into a one-line text placeholder (for example the file name, or the location name and address) and that placeholder is what the agent receives; the file itself is not read. If your customers tend to send screenshots of error messages, plan for those conversations to reach a person.
The 24-hour customer service window
Meta limits when a business can send free-form messages. A customer message opens a 24-hour customer service window; while it is open you can send normal service messages, and once it closes you can only send pre-approved template messages (Meta's send-messages guide, checked September 2026).
AI replies are not affected in practice, because they go out seconds after the customer's message. Human replies are where this bites. If a conversation is handed off and your team answers the next day, the reply is sent as free-form text and Meta will refuse it once the window has closed. LayBuild logs the failed delivery; it does not convert the reply to a template for you. Admins can check whether a given number is still inside its window (the check looks at the last customer message on WhatsApp for that number), and templates can be managed and sent from the WhatsApp settings. The practical rule: staff WhatsApp handoffs so a person answers within the day, and keep an approved template for "we have an update on your request, reply to continue".
Handoff keywords are per channel
On the widget and API, a customer's request for a human hands off only when your organization has turned on human handoff (it is off by default), or after 25 AI turns. WhatsApp has its own list of handoff keywords in the WhatsApp settings, which defaults to agent, human, support, help and representative, and it checks it before the AI runs. The match is a substring match, so "I need help with my invoice" contains "help" and goes straight to your team. If you want the AI to answer WhatsApp questions that contain those words, edit the list.
Length and formatting
Answers from the agent are capped at 8,000 characters on every channel. WhatsApp text replies are cut at 4,096 characters before sending. The built-in prompts already ask the model for short, plain-text replies without markdown headings or tables, because the same answer has to render in both a chat bubble and WhatsApp. When an attached API tool returns product data, the WhatsApp renderer can turn it into up to 3 reply buttons or a list of up to 10 rows, which the widget shows differently.
Compliance keywords and opt-outs
WhatsApp messages also pass through checks that do not exist on the widget: opt-out and opt-in keywords are recorded and acknowledged, numbers that opted out do not get AI replies, and a short list of patterns for commerce categories that Meta's policy prohibits is refused and logged to the moderation queue. The Meta webhook itself is verified with the app secret signature, and in production requests without a configured app secret are rejected.
The REST API channel today
The REST API lets an authenticated user create a conversation with a first message (POST /api/conversations), read its messages, close, reopen and rate it. Real-time messages after that go over the same Socket.io connection the widget uses. One honest gap: the schema has an API channel value, but conversations created through the REST endpoint are currently stored with the default WEB channel, so you cannot filter API-originated conversations separately in the dashboard yet. See the developer docs for the endpoints.
What is not supported
- Channels other than the three above. If you need email or Slack, you would forward messages into the REST API from your own integration.
- Media understanding on any channel: no image reading, no voice transcription.
- Merging one person's identities across channels.
- Automatic template fallback when a WhatsApp human reply falls outside the 24-hour window.
Outbound webhooks (conversation created, message received, handoff, conversation closed) fire for conversations on every channel, so a CRM or ticketing integration can treat them uniformly. There is no retry queue for failed webhook deliveries; deliveries are logged so you can see what failed.
Where to go next
If you are adding the widget to a React site, read how to embed the LayBuild widget in a Next.js App Router site. For what happens when a conversation moves to a person on any channel, see safe human handoff and escalation, and for wiring conversations into your own systems, custom webhooks for support automation.
