Galadri

Communications

Multi-channel messaging built into every agent.

Overview

Galadri agents can send emails with calendar invites, text messages, and make phone calls. Communications are built into the platform runtime, but external organizations bring their own provider identity. Email requires SendGrid. SMS and voice require Twilio. Galadri manages the AI voice layer for calls on top of the customer's Twilio setup.

Every channel works through the same chat endpoint. Ask the agent to "send a booking confirmation email" or "text the user a reminder" and it handles the rest. Communication tools participate in the meta-tool pattern just like any other tool and can be batched alongside data operations and searches.

All communication tools execute as fire-and-forget actions. The agent initiates the message and continues the conversation without waiting for delivery confirmation. The stream emits an "status": "initiated" result immediately so your UI can show that the message was sent.

Text-only delivery

Email and SMS replies are delivered as one finished plain-text message, not as streamed token chunks. They do not include thinking traces, interim tool-planning text, rich results, display directives, suggested follow-up prompts, or mutation cards. Voice calls still stream live speech to the provider, but the voice model also operates without maps, cards, or other chat-only display directives.

Direct APIs

If you want to send messages or place calls without going through /v1/chat, use the Communications API. It documents the direct HTTP endpoints for /v1/emails, /v1/sms, and /v1/calls.

When to use the direct endpoints

Use the Communications API for server-side orchestration, background jobs, or provider flows that already know they want to send an email, text, or phone call. Use chat when you want the agent to decide whether communication is needed as part of a larger task.

Channels

Email (send-email-invite)

Sends HTML emails with optional ICS calendar invite attachments. Supports the full email lifecycle: new invitations, updates to existing events, and cancellations.

Calendar invites include event title, location, start and end time, and description. When an invite is sent, the tool automatically creates a schedule record in the data model so you do not need a separate manage-data call to track the appointment.

Supported actions

FieldTypeDescription
send_emailactionSend a plain HTML email. Requires to, subject, and body_html or body_text.
send_inviteactionSend a calendar invite (.ics) email. Requires to, title, and start_datetime. Automatically creates a schedule record.
cancel_inviteactionCancel a previously sent calendar invite by schedule ID.

Common use cases: booking confirmations, maintenance reminders, service summaries, and document delivery.

Outbound email uses the organization's configured visible sender mailbox. Reply threading prefers standard email headers like Message-ID, In-Reply-To, and References.

Galadri sends outbound email from a chat. subdomain of your business domain, for example service@chat.example.com. Replies go to the same address automatically. Add an MX record for chat.example.com pointing to mx.sendgrid.net, configure SendGrid Inbound Parse for that subdomain, and replies route back to your agent.

The inbound webhook expects SendGrid's signed Parse request headers and rejects unsigned requests before it reads the multipart body. Keep webhook signing enabled and point the Inbound Parse directly at the Galadri inbound parse URL.

Each email credential has three inbound modes: outbound only, inbound for users only, and inbound + callbacks. The credential also owns the handler agent for inbound replies, the inbound AI reply delay, and the optional auto-reply for unknown senders. New email credentials default to a 300 second inbound reply delay. The Console stores this value in seconds, requires a positive integer, and blocks zero because instant AI replies feel unnatural. If the unknown-sender message is left blank, Galadri accepts the inbound email without sending an automatic reply.

Inbound + callbacks still prefers deterministic thread identity first. Standard email reply headers and reply-token addressing win before anything else. If a fresh inbound email from an external contact has no usable thread identity, Galadri scopes the message to that destination mailbox plus sender email, checks the active callback cases tied to that contact, and either binds the one likely case or asks a clarifying follow-up before it routes the message into a user context. If no callback case exists for that scoped contact, the credential's normal unknown-sender behavior applies and no external-contact conversation record is created.

If open and recent cases do not fit, Galadri can run a bounded historical search inside that same mailbox and sender scope. Historical cases require a clear message match before routing, so an old single case is not selected just because it exists.

Outbound emails to non-user contacts also create the destination-scoped callback continuity record immediately when the credential is in inbound + callbacks mode. That lets a later reply from the business attach to the open case instead of starting from a sender-only guess.

When a fresh external-contact callback is bound, Galadri runs the reply through a restricted callback runtime with no Galadri tools available. Built-in tools, custom HTTP tools, and custom MCP tools are omitted from the model-visible schema and rejected again in the execution layer if a model or provider attempts to call one.

After a bound external email callback reply, Galadri applies a conservative internal outcome transition even if the runtime decides no outbound reply is needed. A concrete business update, such as a ready-for-pickup confirmation, marks the callback objective resolved, records a resolve audit event, and relays the update through the callback's stored follow-up channel. That channel is chosen when Galadri first contacts the outside party: originating chat session first, then the user-facing email or SMS channel when available, then push if configured, otherwise no direct user follow-up. Deferred updates keep the case open in monitoring, and clarification replies keep the case awaiting response. Recent resolved cases remain closed for low-signal replies, refresh their resolution for concrete follow-up updates, and reopen only when the follow-up needs more waiting or clarification.

send_email parameters

ParameterTypeDescription
actionrequired"send_email"
torequiredstringRecipient email address.
subjectrequiredstringEmail subject line.
body_htmlstringHTML email body.
body_textstringPlain text fallback.

send_invite parameters

ParameterTypeDescription
actionrequired"send_invite"
torequiredstringRecipient email address.
titlerequiredstringCalendar event title.
start_datetimerequiredstringISO 8601 with timezone offset (e.g., "2026-03-25T10:00:00-04:00").
duration_minutesintegerDuration in minutes (default 60).
locationstringEvent location.
descriptionstringEvent description.

cancel_invite parameters

ParameterTypeDescription
actionrequired"cancel_invite"
schedule_idrequiredstringID of the schedule to cancel.

SMS (send-sms)

Sends text messages to end users via the organization's Twilio account. Supports SMS and MMS (with optional image attachments). The same Twilio credential can also power voice calling in the Console. Phone numbers should be in E.164 format but common US formats are also accepted.

Common use cases: appointment reminders, quick status updates, and urgent alerts. SMS is a plain-text channel. Galadri does not send maps, cards, or interactive UI into the message body.

Each Twilio credential has three inbound text modes: outbound only, inbound for users only, and inbound + callbacks. The credential owns the inbound text handler, the inbound AI reply delay, and the optional automatic reply for unknown numbers. New Twilio credentials default to a 60 second inbound text reply delay. The Console stores this value in seconds, requires a positive integer, and blocks zero because instant AI replies feel unnatural. If that unknown-number response is blank, Galadri accepts the inbound text without replying.

Inbound + callbacks on a Twilio number uses destination-scoped external-contact continuity. Texts and phone calls hitting the same owned number share the same outside-contact record, candidate cases, and recent continuity window. Galadri scopes by the destination number first, then by the outside number, prefers active queries awaiting response, and asks clarifying follow-up questions when more than one callback case could fit. If the AI texts a business first and the business calls back instead, the phone call can still bind to the SMS callback case and relay the post-call result back through the originating chat.

If no open or recent phone-number case fits, Galadri can search older resolved cases inside the same Twilio number and outside phone scope. Older cases require a clear match or a clarification step before Galadri binds the callback.

Outbound SMS messages and outbound calls to non-user numbers create and bind that external-contact continuity record as soon as the outreach is initiated, so callbacks across SMS and phone share the same candidate-case state.

SMS callback replies use the same restricted external-contact runtime as email callbacks: they can ask clarifying questions, but no Galadri tools are available while the outside contact is being matched and handled.

For SMS-originated callback cases, a clear business reply can resolve the callback objective and relay the result through the callback's configured follow-up channel even when no text response is sent to the business. If the original callback case came from an outbound phone call and the business responds by text, that SMS can also resolve the voice callback objective and relay the result through the voice callback's configured follow-up channel. Recent resolved callback cases follow the same conservative reopen policy as email.

ParameterTypeDescription
phone_numberrequiredstringRecipient phone number. E.164 format preferred (e.g., "+15551234567").
messagerequiredstringMessage text. Keep under 160 characters for a single SMS segment.
media_urlstringImage URL to attach as MMS.
thread_idstringContinue an existing SMS conversation thread.

SMS opt-in

If the recipient phone number matches the end user's profile phone number, the tool checks the user's sms_opt_in preference. If the user has not opted in, the tool returns an error. Third-party numbers are not subject to this check.

Phone Calls (place-call)

Initiates AI-powered outbound voice calls using the organization's Twilio number for telephony. The Console uses the same Twilio credential flow as SMS, while Galadri keeps the AI voice layer managed behind the scenes. Inbound call behavior and any optional phone-call model override are configured on the Twilio credential that owns that phone number, not on the agent. The AI voice agent can discuss topics, answer questions, and take actions on behalf of the user during the call.

Common use cases: appointment confirmations, follow-ups, and high-touch customer service. Voice is also a text-free delivery surface from the model's perspective. The voice agent does not get chat-only rich display options like maps, cards, or display directives.

Inbound + callbacks for phone calls uses the same destination-scoped external-contact continuity model as SMS. When an outbound call to an external contact creates a callback case, Galadri records the Twilio credential, outside number, active query, and recent continuity state. A call back with one likely case enters a restricted callback runtime, including when the original outreach was an SMS from the same Twilio credential. A business text can likewise resolve a callback that started as an outbound phone call. A call back with multiple possible cases is asked for a callback reference or relevant request details before Galadri binds the call to a user context. The neutral prompt does not read callback case summaries aloud to the caller.

If an external business needs to follow up by email after a phone call, the voice agent is instructed not to rely on a fresh unthreaded email. It should tell the business that Galadri will send an email they can reply to, because that outbound email creates the email callback thread Galadri can route safely.

The restricted callback tool policy is shared across email, SMS, and voice. For phone calls, the ElevenLabs provider-tool manifest reports no Galadri tools for external contacts, and the webhook execution path enforces the same no-tool policy at runtime.

ParameterTypeDescription
phone_numberrequiredstringRecipient phone number. E.164 format preferred (e.g., "+15551234567").
purposerequiredstringThe purpose of the call. Describe what the AI voice agent should discuss or accomplish.

Call opt-in

Similar to SMS, the tool checks the end user's call_opt_in preference when the recipient matches the user's profile phone number.

ElevenLabs provider-tool mode

For persistent ElevenLabs agents, you can avoid Custom LLM entirely and use Galadri's explicit webhook tool path instead. Configure an ElevenLabs server tool named execute_actions pointing to https://api.galadri.com/v1/comms/voice/tool-call/execute_actions.

Pass the active call session in either the X-Call-Session-Id header or the JSON body field call_session_id. Outbound calls expose this as the ElevenLabs dynamic variable galadri_call_session_id.

Also send a shared secret header such as X-Galadri-Tool-Secret using an ElevenLabs secret environment variable. Galadri validates this against ELEVENLABS_TOOL_WEBHOOK_SECRET before trusting the call session id.

Galadri now sends a full per-call system prompt override when starting outbound calls. That override includes the call mission plus the exact allowed tool names, descriptions, and argument structures for the active Galadri agent.

To allow this, enable System prompt and First message under the ElevenLabs agent's Security → Overrides settings.

Outbound calls started through Galadri now default to ELEVENLABS_OUTBOUND_CONTEXT_MODE=dynamic_only. Use both or custom_llm_only only when you intentionally need the advanced Custom LLM path.

Scheduled Communications

Schedules can trigger automated AI communications without a chat request. When a schedule has agent_runtime_utc, agent_runtime_prompt, and agent_comm_channel set, the platform automatically runs the agent at the scheduled time and delivers its response through the specified channel.

How It Works

A cron job runs every 5 minutes and picks up schedules where agent_runtime_utc is in the past. The cron uses a fan-out pattern: a lightweight dispatcher identifies due schedules and creates execution log entries, then fires off parallel worker requests. Each worker runs in its own serverless invocation with its own timeout.

For each due schedule:

  1. Dispatch — The cron creates a schedule_executions record, advances the schedule (recurring) or clears it (one-shot), and dispatches the worker.
  2. Agent resolution — The worker uses the schedule's agent_id if set, otherwise falls back to the organization's first active agent.
  3. AI execution — The agent_runtime_prompt is run through the AI pipeline as a synthetic message. The agent can call tools, look up data, and generate a contextual response.
  4. Channel delivery — The agent's reply is routed to the agent_comm_channel: email, sms, call, or webhook.
  5. Logging — The execution record is updated with status (success or failed), latency, and any error message. View execution history in the Console under Logs > Scheduled.

agent_runtime_utc vs start_time_utc

These fields serve different purposes. start_time_utc is when the actual event happens (e.g., oil change at 9am on September 8). agent_runtime_utc is when the AI fires (e.g., September 5 to send a 3-day reminder). They can be the same if the trigger should happen at event time. For pure automations with no calendar event, start_time_utc can be omitted entirely.

Example: Create a schedule with automated SMS reminder
{
  "actions": [
    {
      "tool": "manage-data",
      "args": {
        "action": "create",
        "table": "schedules",
        "data": {
          "title": "Oil Change - Firestone Main St",
          "start_time_utc": "2026-09-08T13:00:00Z",
          "location_name": "Firestone Complete Auto Care",
          "location_address": "456 Main St, Phoenix, AZ",
          "agent_runtime_utc": "2026-09-05T14:00:00Z",
          "agent_runtime_prompt": "Remind the user about their upcoming oil change at Firestone on Main St this Monday at 9am. Include the address and suggest they check their tire pressure too.",
          "agent_comm_channel": "sms",
          "recurring": false
        }
      }
    }
  ]
}

Recurring Schedules

When recurring is true, the cron advances agent_runtime_utc forward by frequency_interval units of frequency_type after each execution. The event time ( start_time_utc) does not change.

Supported frequencies

FieldTypeDescription
hourlyfrequency_typeAdvances by N hours.
dailyfrequency_typeAdvances by N days.
weeklyfrequency_typeAdvances by N weeks (7 * N days).
monthlyfrequency_typeAdvances by N months.
yearlyfrequency_typeAdvances by N years.

Webhooks

Set agent_comm_channel to "webhook" to receive the agent's scheduled response as an HTTP POST to your server instead of delivering it to an end user via email, SMS, or voice.

The webhook URL is configured on the agent (either via scheduled_webhook_url or a webhook credential). If a signing secret is configured, the request includes an HMAC-SHA256 signature header for verification.

Webhook payload
{
  "event": "scheduled_communication",
  "schedule_id": "sch_abc123",
  "organization_id": "org_def456",
  "end_user_id": "usr_ghi789",
  "agent_reply": "Hi Jane, your oil change is coming up this Monday at Firestone on Main St. Don't forget to check your tire pressure!",
  "tool_calls": [],
  "schedule_title": "Oil Change - Firestone Main St",
  "triggered_at": "2026-09-05T14:02:31Z"
}

Webhook headers

FieldTypeDescription
Content-Typeheaderapplication/json
X-Galadri-EventheaderAlways "scheduled_communication".
X-Galadri-SignatureheaderHMAC-SHA256 hex digest of the request body, signed with your webhook signing secret. Present only if a signing secret is configured.

Use webhooks for push notifications

Webhooks are the recommended way to build push notification flows. Configure a recurring schedule with a webhook channel, and your server receives the agent's contextual response on each execution. Route it to your own notification infrastructure (FCM, APNs, etc.) from there.

Provider Ownership

External organizations bring their own transport providers. Email requires a customer-owned SendGrid account. SMS and voice require a customer-owned Twilio account and number. Galadri still manages the AI voice layer for phone calls on top of the customer's Twilio setup.

Provider mapping

FieldTypeDescription
EmailSendGridHTML emails and calendar invites (.ics attachments).
SMSTwilioText messages and MMS with image attachments.
VoiceTwilio + ElevenLabsTwilio for telephony, ElevenLabs for AI voice synthesis.

Credential Resolution

Credentials resolve in priority order:

  1. Per-agent credentials — If the agent has dedicated credentials configured for the channel, those are used.
  2. Organization credentials — If no agent-level credentials exist, the organization's provider settings are checked.

Custom credentials are encrypted with AES-256-GCM at rest. Configure them in the Galadri Console under Communications Settings. The console now verifies provider setup before you can save it. Email credentials can be outbound only or inbound + outbound. Outbound-only email credentials require sender and sending-domain verification. Inbound-enabled email credentials additionally require MX validation and SendGrid Inbound Parse verification. Twilio credentials continue to verify number capability before save.

Configurable credentials per channel

FieldTypeDescription
EmailSendGridAPI key and a sender address on the chat. subdomain. Each credential can be outbound only or inbound + outbound.
SMSTwilioAccount SID, auth token, and an SMS-capable sending number.
VoiceTwilio + ElevenLabsTwilio Account SID, auth token, and a voice-capable number. Galadri manages the AI voice layer.
WebhookCustomWebhook URL and optional HMAC signing secret.

Example: Booking with Confirmation Email

This example shows a realistic end-to-end flow where an agent with repair booking enabled books an appointment and sends a confirmation email with a calendar invite.

User says: "Book me an oil change at the Firestone on Main St for Tuesday at 10am"

The agent makes three tool calls in sequence:

  • 1. repair-booking (book action) to book the appointment at the shop
  • 2. send-email-invite (send_invite action) to send a calendar invite with the appointment details
  • 3. manage-data (create action on milestones) to log the upcoming service as a milestone
Request
curl -X POST https://api.galadri.com/v1/chat \
  -H "Authorization: Bearer gld_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "main-agent",
    "message": "Book me an oil change at the Firestone on Main St for Tuesday at 10am",
    "end_user_id": "user-123",
    "overrides": { "streaming": true }
  }'
Streaming response (abbreviated)
{"type": "session", "session_id": "550e8400-e29b-41d4-a716-446655440000", "is_new": true}

{"type": "tool_call", "id": "tc_1", "actions": [
  {
    "tool": "repair-booking",
    "args": {
      "action": "book",
      "shop_id": "shop_firestone_main",
      "appointment_datetime": "2026-04-01T10:00:00-07:00",
      "service_description": "Oil change"
    }
  }
]}

{"type": "tool_result", "id": "tc_1", "results": [
  {
    "tool": "repair-booking",
    "status": "success",
    "data": {
      "confirmation_number": "RB-29481",
      "shop_name": "Firestone Complete Auto Care",
      "appointment_time": "2026-04-01T10:00:00-07:00"
    }
  }
]}

{"type": "tool_call", "id": "tc_2", "actions": [
  {
    "tool": "send-email-invite",
    "args": {
      "action": "send_invite",
      "to": "jane@example.com",
      "title": "Oil Change - Firestone on Main St",
      "start_datetime": "2026-04-01T10:00:00-07:00",
      "duration_minutes": 60,
      "location": "Firestone Complete Auto Care, 456 Main St",
      "description": "Oil change appointment. Confirmation: CA-29481"
    }
  }
]}

{"type": "tool_result", "id": "tc_2", "results": [
  {
    "tool": "send-email-invite",
    "status": "initiated",
    "data": {"message": "Calendar invite sent to jane@example.com"}
  }
]}

{"type": "content", "content": "Your oil change is booked at Firestone on Main St for Tuesday, April 1 at 10:00 AM. Confirmation number: CA-29481. I sent a calendar invite to your email."}

Display capabilities and booking confirmation

Communication tools respect the same display capability system as other tools. If booking_confirm is enabled, the agent shows a confirmation UI before executing the booking and sending notifications.

See also: Email tool reference, All tools, and Data Model