send_email
Sends a transactional email from the agent. The call returns amessage_id you can pass to check_email_status to look up the final delivery state (delivered, bounced, complained, …) and an event-by-event timeline.
Recipient allowlist (enforced)
send_email will only send to:
- The authenticated subscriber’s email address, OR
- The agent owner’s email address, OR
- Any address matched by
details.email_recipient_allowlist— an array of full addresses or@domain.comwildcards configured in the agent’s Details tab.
to, cc, and bcc. If even one entry fails, the whole call is rejected with the offending addresses listed in details.rejected_to / rejected_cc / rejected_bcc. There is no way to email an arbitrary stranger.
Parameters
Custom headers
Pass arbitrary headers via theheaders map:
- Header names must be ASCII letters, digits, or standard header punctuation.
- Values must be plain strings.
- Reserved — rejected:
- Envelope-routing headers (
To,From,Cc,Bcc,Reply-To,Subject,Date,Message-ID,Content-Type,Content-Transfer-Encoding,MIME-Version). Use the dedicated parameters instead. - Any header in the reserved
X-Agentheya-*namespace.
- Envelope-routing headers (
{ error, details: { rejected_headers: ["..."], hint } }.
Scheduling
Pick exactly one of:scheduled_at: "2026-08-05T11:52:01.858Z"— absolute UTC timestamp. Must be in the future.send_in: "5m"— relative delay. Supported forms:30s,5m,1h,2d,1w(and the longer aliasessec/secs,min/mins,hr/hrs,day/days,wk/wks).
scheduled_at. On success the tool returns status: "scheduled". Scheduled emails go out at the resolved time even if the conversation has long ended.
Attachments
Each entry attaches one file. The combined payload (all attachments plus body) cannot exceed 40 MB.
Exactly one of
content and path must be set per item — setting both, or neither, is rejected.
Example (one local + one remote + one inline image):
Replying to a received email
Setin_reply_to_inbound_id to the id of an email this agent received (visible on the inbound row in the Emails dashboard). When set:
- The standard
In-Reply-ToandReferencesheaders are filled in automatically from the original message, so the recipient’s mail client threads the new message under the original conversation. - An authoritative reply linkage is recorded — the Emails dashboard shows the original inbound and the outgoing reply in each other’s “Same thread” panel even when the subject line drifts away from
Re: ….
- The id must belong to an email this agent received. Cross-agent ids return a structured error.
- If a subscriber is calling, the id must belong to an email the agent received from that same subscriber.
In-Reply-To or References in headers, those values win over the auto-fill.
Returns
On immediate-send success:message_id is the handle for check_email_status — store it if you’ll need to look up delivery state later.
On rejection by the allowlist:
{ error, details: { hint, ... } }.
Call from your own custom tool
Notes
- The
Fromaddress is fixed to<agent_name> <noreply@...>and cannot be overridden. - A scheduled email will still be sent unless explicitly cancelled — even if the conversation ends. Gate destructive flows behind
confirm_action+commit_action. - Final delivery status (delivered, bounced, complained) appears in the agent’s activity feed; it is not returned synchronously by this call.