Overview
The Channels API lets your agent initiate messages on the channels it’s connected to — WhatsApp, SMS, email, web chat, and more — from anywhere your code runs: a tool, a scheduled job, a webhook, or a trigger. It’s the outbound half of a two-way conversation: inbound messages wake your agent, andChannels.* sends messages back out.
Every
Channels.* send is recorded to the recipient’s conversation thread with your agent. When the user replies, your agent picks up with full context — the outbound message is already part of the conversation it remembers. See Proactive Messaging for the full model.Channels.send
Free-form text on any connected channel
Channels.email.send
Rich email — subject, HTML, cc/bcc, attachments
Channels.whatsapp.sendTemplate
Approved templates to start or re-open a conversation
Where you can call it
Channels.* works in any execute context. Recipient resolution differs slightly by context:
| Context | Available? | Notes |
|---|---|---|
| Tools | ✅ | Has conversational context — you can target the current user with their userId, or any user. |
| Jobs | ✅ | No conversational context — target an explicit userId, phoneNumber, or email. |
| Webhooks | ✅ | No conversational context — target an explicit recipient. |
| Triggers | ✅ | Same as webhooks — target an explicit recipient. |
| Pre/Post-processors | ✅ | Available, but most sending happens in tools and jobs. |
Channels.send()
Send a free-form text message on a connected channel.The channel to send on. One of:
'whatsapp', 'sms', 'email', 'webchat', 'teams', 'instagram', 'messenger'.The recipient. Provide exactly one of the fields below.
A Lua user ID. Works on every channel — the recipient’s channel address is resolved from their conversation history with your agent.
A phone number in E.164 format (e.g.
+14155552671). Valid for whatsapp and sms only — lets you reach a number with no prior conversation (cold start).An email address. Valid for the
email channel only (cold start). For richer email, prefer Channels.email.send.The message text. Supports the same response formatting components (
::: blocks) as inline replies, where the channel renders them.ChannelSendOutput
Examples:
- To the current user
- Cold start (phone)
- From a job
Channels.email.send()
Send a rich email — subject, plain-text and/or HTML body, cc/bcc, and attachments.The recipient. Provide exactly one of
to.userId or to.email.A Lua user ID — the email address is resolved from the user’s conversation history.
A literal email address (cold start).
The email subject line.
Plain-text body. Provide
text, html, or both — at least one is required.HTML body.
Carbon-copy recipients.
Blind-carbon-copy recipients.
Files to attach. Each is
{ filename, contentType, url } — the file is fetched from the public url at send time. Combined attachment size is capped at 28 MB.ChannelSendOutput (with messageId set to the provider message ID where available).
Example:
Channels.whatsapp.sendTemplate()
Send a pre-approved WhatsApp template. Use this to start a conversation, or to reach a user whose 24-hour messaging window has closed (where free-form sends aren’t allowed).The recipient — exactly one of
to.userId or to.phoneNumber (E.164).The name of an approved template on the agent’s WhatsApp channel. List available templates with
Templates.whatsapp.list.The template language, e.g.
'en_US'.Meta template component objects supplying the header / body / button parameter values — e.g.
{ type: 'BODY', parameters: [{ type: 'text', text: 'Tuesday at 3pm' }] }. The component type is 'HEADER', 'BODY', or 'BUTTON'; the parameter type is 'text', 'image', 'video', 'document', or 'coupon_code'.A plain-text summary of what the template said. This is the text recorded to the conversation thread so your agent remembers the outreach when the user replies. Recommended whenever the template body isn’t self-explanatory.
ChannelSendOutput
Example:
Channels.whatsapp.sendTemplate is the canonical way to send a WhatsApp template as part of a conversation — it records the send to the recipient’s thread and respects the recipient resolution above. The lower-level Templates.whatsapp.send (batch send by channel ID and phone numbers) remains available for bulk/campaign sends.Options
All three methods accept an optionaloptions object:
Pin the send to a specific channel configuration (for agents with more than one channel of the same type). The configuration must belong to your agent.
What to do when a WhatsApp free-form send hits a closed 24-hour window:
'queue'(default) — queue the message and deliver it after the user re-engages (the API returnsqueued: true).'fail'— reject the send so you can fall back toChannels.whatsapp.sendTemplate.
ChannelSendOutput
Every send method resolves to the same shape:The channel accepted the message. Independent of
persisted.The message was recorded to the recipient’s conversation thread with your agent. A delivered-but-unpersisted send returns
delivered: true, persisted: false plus a warning — it does not throw.WhatsApp only.
true means the 24-hour window was closed and the message is queued — delivered stays false until the recipient re-engages, at which point the queued text is delivered and recorded. See Proactive Messaging.Error handling
Channels.* throws when a send is rejected (invalid recipient, unconfigured channel, provider rejection, or onClosedWindow: 'fail' on a closed window). Wrap calls in try/catch where a failure should be handled gracefully.
A successful call may still report partial success — delivered: true with persisted: false (plus a warning) means the message went out but couldn’t be recorded to the conversation thread. This is not an error and won’t throw; check the flag if recording matters to your flow.
Channels & recipients at a glance
| Channel | Cold start (no prior conversation) | Warm only (userId) |
|---|---|---|
whatsapp | ✅ via phoneNumber (template required if window closed) | ✅ |
sms | ✅ via phoneNumber | ✅ |
email | ✅ via email | ✅ |
webchat | — | ✅ |
teams | — | ✅ |
instagram | — | ✅ |
messenger | — | ✅ |
TypeScript types
Next steps
Proactive Messaging
The full model: Channels.send vs user.send() vs templates, and per-channel windows
Channel Capabilities
Per-channel limits, sender resolution, and compliance
Proactive Send Recipe
Schedule outreach with defineJob + Channels.send
Templates API
List and batch-send approved WhatsApp templates

