In these docs

Execution Layer for Odoo

Messaging: Discuss to WhatsApp.

Governed AI messaging in the Execution Layer, new in version 1.1: Discuss, record chatter, and WhatsApp through Odoo's own integration, with confirm-by-default previews, per-user levels, approvals, rate limits, and a message log of every send.

Available now · Odoo 19 Updated 20 September 2026

New in version 1.1, the Execution Layer lets an AI client send messages: Discuss channels, group chats and direct messages, notes and comments on any record’s chatter, and WhatsApp. Every send runs the same governed pipeline as every other write: identity, policy, the user’s messaging level, approval where configured, idempotency, atomic execution, read-back, evidence.

The default posture is the whole story: nothing sends until a person reads the exact words and says yes.

What a sent message looks like

Every internal message carries a non-optional footer: 🤖 AI message · which client · sent as which user. Colleagues always see a machine wrote it, and under whose account.

The AI acts as the connected Odoo user: the message’s author is that person, direct messages and @mentions resolve to internal users only, and it can post only into conversations that user is a member of. An ambiguous name is refused with candidates (AMBIGUOUS_TARGET), a non-member target with NOT_A_MEMBER, and @everyone is off by default and works only in channels.

The tools

Messaging adds five tools to the catalogue (part of the 20 total):

ToolKindWhat it does
list_conversationsreadThe user’s channels, group chats and DMs, plus open WhatsApp conversations with their 24-hour-window state. Metadata only, never message text.
send_messagewriteSend into a channel, group, or DM, or post a note or comment on a record’s chatter.
list_whatsapp_templatesreadThe WhatsApp templates and their placeholders; only Meta-approved, active templates are sendable.
send_whatsappwriteSend a template (or, if enabled, a free-form reply) through Odoo’s WhatsApp queue.
get_whatsapp_statusreadDelivery state (queued, sent, delivered, read, or error) of the WhatsApp messages this connection sent.

A chatter comment notifies the record’s followers, which Odoo may deliver by email; a note stays internal. There is no email-send tool and no SMS: those are not messaging features.

Confirm each message: the default gate

Every user starts at the Confirm each message level. The first send_message call comes back unsent, as CONFIRMATION_REQUIRED, carrying the exact rendered preview (text, destination, mentions, recipient count) and a one-time cnf_ token. The token is a hash of the exact arguments: single-use, expiring, bound to those exact words. The AI shows the person the preview, the person says yes, and the AI retries the identical call with the token. If even one word changed, the retry fails with CONFIRMATION_STALE and nothing sends. The message a person confirmed is provably the message that went out.

Per-user levels, per channel

Two new columns in Users & permissions: a Discuss level and a WhatsApp level per user. Off removes the send tool from that user's AI entirely.

Four levels, set separately for Discuss and WhatsApp, admin-only to change:

  • Off: the send tool does not exist for this user’s AI.
  • Confirm each message (default): the preview-token gate above, on every send.
  • Approval in Odoo: sends route through the approval queue under the new outbound_messaging and outbound_whatsapp risk classes, and the approver reads the actual message body in the payload preview before releasing it.
  • Unrestricted: for the rare user you trust that far. Bulk WhatsApp sends above the threshold still require approval, even here.

Global switches (Configuration → Settings → Messaging) sit above all of this: Discuss on or off, WhatsApp on or off (off by default), free-form WhatsApp on or off (off by default), @everyone, the bulk-send threshold, and hourly rate caps that can also be overridden per user.

WhatsApp, the careful way

WhatsApp runs through Odoo’s own Enterprise WhatsApp integration and your own Meta business account. The Execution Layer never talks to Meta itself; it drives the same channel a person uses in Odoo. It requires Odoo Enterprise with the WhatsApp app installed and a configured account, and the status card in Settings tells you honestly which of those is missing.

  • Template-first: only Meta-approved, active templates send (list_whatsapp_templates shows them); anything else is TEMPLATE_NOT_APPROVED.
  • Free-form replies work only inside an open 24-hour customer window, and only when their separate switch is on; outside the window the AI gets WHATSAPP_WINDOW_CLOSED and is pointed back to templates.
  • Bulk (above the threshold, default 5 recipients) always needs approval.
  • Sends are queued in Odoo’s WhatsApp queue: the receipt reports the message persisted and queued, and never claims Meta delivered it; get_whatsapp_status reports the real delivery state later, for this connection’s own sends only.

The evidence trail

Evidence → Messages: every send with its destination, reach, preview, and the human gate it passed: confirmed, approved, or unrestricted.

Every send lands three ways: a row in the message log (destination, kind, recipients reached, a preview, the control it passed, the linked audit entry), the full before-and-after evidence on the action log like any other write, and, if you want it, an “AI sent a message” alert on every send. The receipt re-reads the stored message after commit (body, author, conversation, mentions) and fails closed with VERIFICATION_FAILED on any mismatch.

Honest limits

The messaging tools send; they do not read message contents (list_conversations is metadata only, and get_whatsapp_status sees only this connection’s own sends). WhatsApp bodies carry no AI mark to the customer: attribution lives in the Odoo-side conversation, the message log, and the audit. And there is no side door: the generic write tools refuse mail.message, the Discuss models, and every whatsapp.* model outright, so messages leave only through the governed messaging tools.

Messaging behaviour is covered by its own adversarial cases in the test suite, including the payload-bound confirmation, the membership and mention refusals, the WhatsApp window, and the no-side-door rule.