email— external mail over your verified domains, delivered and tracked for you.a2a— internal delivery between Dairo inboxes. It lands as a signed agent-to-agent receipt on both ends.telegram— external chat over a Telegram bot you connect. Messages people send the bot arrive in your mailbox; your agent replies with the same send call.slack— external chat over a Slack app your customers install. Mentions and DMs arrive as messages; your agent replies the same way.
channel enum also reserves values for channels that are not open yet, such as
whatsapp. Dairo never returns a channel that is not live, so any value you read is one
you can act on.
The channel field
channel is a first-class field. It appears wherever the medium matters:
Because
channel rides on the message itself, one inbox can hold a mix: an email reply
and an a2a hop live side by side in the same thread, each tagged with how it arrived.
Send on a channel
Sending is one call toPOST /v1/messages. For an email inbox, the channel field is an
optional hint (email or a2a), not a switch you must set. When you omit it, Dairo
classifies by recipient:
- Every recipient is a Dairo inbox → the internal
a2ahop, a signed receipt on both ends. - Any external (non-Dairo) recipient →
emailover your verified domain.
channel overrides that classification:
channel: "email"forces the email path even when every recipient is a Dairo inbox.channel: "a2a"forces the internal hop and requires every recipient to be a Dairo inbox. A send with any external recipient is rejected with400, so an explicita2arequest can never deliver over public email.
channel it actually went out on.
A Telegram or Slack inbox is different: it always delivers over its own channel, and the
inbox’s channel wins over any
channel hint on the request. Those channels are driven by
the inbox, not passed as a send hint.channelMetadata: the per-channel extension point
Channel-specific fields ride in achannelMetadata bag rather than as top-level columns,
so adding a channel never reshapes the common fields. What it carries depends on the
channel:
The flat, familiar fields —
from, to, cc, bcc, subject, channel, direction,
status — stay exactly where they are on every channel.
Events are channel-agnostic
Delivery webhooks use themessage.* namespace, not a per-channel
prefix. message.sent, message.delivered, message.bounced, message.complained, and
message.received fire the same way whichever channel a message traveled over, so a
receiver written once keeps working as channels are added.