Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.svantic.com/llms.txt

Use this file to discover all available pages before exploring further.

Notification Channels & Templates

Svantic delivers notifications through configurable channels — email, Slack, webhook, SMS, and phone. Each channel has its own message format, delivery mechanism, and capabilities. Templates control how messages are rendered for each channel and event type.

Channel Types

Email

Delivers formatted HTML emails via the platform’s SMTP service. Best for: Approval requests, daily digests, operation summaries, compliance audit trails. Capabilities: Rich HTML formatting, deep links to the dashboard, supports attachments for reports. Configuration:
{
  "type": "email",
  "name": "Ops team",
  "config": {
    "recipients": ["ops@company.com", "oncall@company.com"]
  }
}

Slack

Delivers formatted messages to a Slack channel using the Slack API. Supports interactive buttons for approvals directly within Slack. Best for: Real-time alerts, team-visible approval requests, operational notifications. Capabilities: Block Kit formatting, interactive Approve/Deny buttons, threaded replies, severity-coded emoji indicators. Configuration:
{
  "type": "slack",
  "name": "Engineering alerts",
  "config": {
    "bot_token": "xoxb-...",
    "channel_id": "C0123456789"
  }
}
For step-by-step instructions on creating a Slack App and obtaining the bot token and channel ID, see the Slack Integration guide. Interactive resolution: When an approval notification includes simple options (Approve/Deny), Slack renders inline buttons. Clicking a button resolves the pending request immediately via the Slack interactive webhook. For complex forms or sensitive fields, a “Complete in Dashboard” button links to the approval page.

Webhook

Delivers a signed JSON payload to any HTTP endpoint. Designed for integration with external systems — PagerDuty, Opsgenie, custom automation, ticketing systems. Best for: System-to-system integration, triggering external workflows, audit logging to external SIEM. Capabilities: JSON payload with full event data, HMAC-SHA256 signature for verification, callback_token for resolution, retry with exponential backoff (3 attempts: 1s, 5s, 30s). Configuration:
{
  "type": "webhook",
  "name": "PagerDuty",
  "config": {
    "url": "https://events.pagerduty.com/integration/...",
    "secret": "optional-hmac-secret"
  }
}
Outbound payload structure:
{
  "type": "approval_required | alert | operation_complete | informational",
  "message_id": "msg-abc123",
  "session_id": "session-456",
  "tenant_id": "acme",
  "callback_token": "base64url-token",
  "resolve_url": "https://gateway/messages/msg-abc123/resolve",
  "severity": "critical | warning | info",
  "timestamp": "2026-04-17T10:30:00Z",
  "event": { ... },
  "rule_name": "Agent unhealthy"
}
The callback_token allows the receiving system to resolve pending requests without Svantic credentials. POST the token back to the resolve_url with a resolution object.

SMS

Delivers short text messages via Twilio SMS. Best for: Urgent approval requests when approvers are away from their desk, critical alerts that need immediate attention. Capabilities: Short-form messages (160 chars for single segment), deep link to dashboard for resolution. Configuration:
{
  "type": "sms",
  "name": "On-call approver",
  "config": {
    "phone_numbers": ["+14155551234"],
    "twilio_account_sid": "AC...",
    "twilio_auth_token": "...",
    "twilio_from_number": "+14155550000"
  }
}

Phone

Delivers voice notifications via Twilio outbound calls. Uses text-to-speech (TTS) for the message and DTMF (keypad) input for resolution. Best for: Critical escalations when other channels haven’t been resolved, high-stakes approvals requiring verbal confirmation. Capabilities: TTS message delivery, DTMF input collection (press 1 to approve, 2 to deny), retry on no-answer, voicemail detection. Configuration:
{
  "type": "phone",
  "name": "VP Engineering escalation",
  "config": {
    "phone_numbers": ["+14155551234", "+14155555678"],
    "twilio_account_sid": "AC...",
    "twilio_auth_token": "...",
    "twilio_from_number": "+14155550000",
    "retry_on_no_answer": true,
    "max_retries": 2
  }
}
Resolution via DTMF: The TTS script reads the approval context and offers keypad options. Pressing a key immediately resolves the pending request via the Twilio status callback. Escalation: If the first phone number doesn’t answer, the system tries the next number in the list. If all numbers fail, the request remains pending (and may expire per the policy’s expiration setting).

In-App

Always enabled, not configurable. Every notification appears in the dashboard’s notification bell. Approval requests appear in the Approvals page.

Template System

Templates control how each notification is rendered for each channel. The system uses a master + tenant architecture.

Architecture

Template Master (built-in defaults) → seeded on first boot → Tenant Templates (per-tenant, in database) → runtime lookup → Template Registry → fallback chain → Rendered Notification

Template Master

The template master contains the default templates for every supported combination of event type and channel type. These are shipped with the platform and represent the recommended notification format. On first boot (database seed): The master templates are written to the root tenant’s notification_templates table. These serve as the source of truth for all future tenant creation. On tenant creation: The root tenant’s templates are copied to the new tenant. The new tenant immediately has a full set of working templates that can be customized independently.

Template Structure

Each template is identified by three keys:
FieldDescription
tenant_idWhich tenant this template belongs to
event_typeWhich event triggers this template (e.g., guard.approval_required)
channel_typeWhich channel this template is for (email, slack, webhook, sms, phone)
Template content varies by channel:
ChannelTemplate fields
Emailsubject (text with variables), html_body (HTML with variables)
Slackblocks (Block Kit JSON with variables), fallback_text
Webhookpayload_schema (JSON structure with variables)
SMSmessage (plain text with variables, max ~300 chars)
Phonetts_script (text-to-speech script with variables), dtmf_options (keypad mapping)

Template Variables

Templates can reference variables from the notification context:
VariableDescription
{{event_type}}The event type (e.g., guard.approval_required)
{{severity}}Severity level: info, warning, critical
{{agent_type}}The agent involved
{{session_id}}Session identifier
{{message_id}}Message/task identifier
{{tenant_id}}Tenant identifier
{{rule_name}}Policy or alert rule name that triggered the notification
{{title}}Human-readable notification title
{{description}}Contextual description
{{dashboard_url}}Link to the relevant dashboard page
{{resolve_url}}URL for resolving pending requests
{{callback_token}}Token for unauthenticated resolution
{{timestamp}}ISO timestamp of the event
{{fields.*}}Form field values (for user input requests)
{{plan.*}}Plan details (for plan approvals)
{{event.*}}Raw event data fields

Template Resolution

When a notification needs to be sent, the Template Registry resolves the template using a fallback chain:
  1. Exact match: (tenant_id, event_type, channel_type) — tenant has a custom template for this specific event and channel
  2. Category fallback: (tenant_id, event_category.*, channel_type) — tenant has a template for the event category (e.g., guard.* catches all guard events)
  3. Default fallback: (tenant_id, *, channel_type) — tenant’s catch-all template for the channel
  4. Master fallback: If no tenant template matches, use the root tenant’s template (the master)
This means a tenant can override just the email template for approvals while using defaults for everything else.

Editing Templates

Dashboard: Navigate to Settings → Channels → Templates. Select an event type and channel to view and edit the template. A preview pane shows the rendered output with sample data. API:
# List all templates for the tenant
POST /internal/templates/list

# Get a specific template
POST /internal/templates/get
{ "event_type": "guard.approval_required", "channel_type": "email" }

# Update a template (creates tenant override if editing a default)
POST /internal/templates/update
{
  "event_type": "guard.approval_required",
  "channel_type": "email",
  "subject": "{{severity}} — Approval needed: {{title}}",
  "html_body": "<div>... custom HTML ...</div>"
}

# Reset to default (deletes tenant override, reverts to master)
POST /internal/templates/reset
{ "event_type": "guard.approval_required", "channel_type": "email" }

Default Event-to-Channel Mappings

Every new tenant receives the following default notification mappings. These determine which channels are notified for which events:
EventIn-AppEmailSlackWebhookSMSPhone
guard.approval_requiredYesYesYesYesNoNo
policy.approval_requiredYesYesYesYesNoNo
agent.health_changed (unhealthy)YesYesYesYesNoNo
agent.deregisteredYesYesYesYesNoNo
dispatch.failed (threshold)YesYesYesYesNoNo
message.errorYesNoNoNoNoNo
message.completedNoNoNoYesNoNo
agent.registeredYesNoNoYesNoNo
session.startedNoNoNoYesNoNo
SMS and phone are never enabled by default — they are opt-in per policy because they are intrusive and incur per-message/per-minute costs. Mappings are managed through policies. Each policy can link to any combination of channels. The table above reflects the built-in policies that ship with every tenant.

Default Templates by Event Type

Approval Required

ChannelContent
EmailSubject: “Action Required: {{title}}”. HTML body with description, form fields (non-sensitive), and “Review in Dashboard” button. Sensitive fields show a warning and redirect to dashboard.
SlackHeader block with title. Description section. Approve/Deny buttons for simple approvals, or “Complete in Dashboard” button for complex forms.
WebhookJSON with type: "approval_required", A2UI spec, callback_token, resolve_url.
SMS”Svantic: Approval needed — {{title}}. Reply APPROVE {{ref}} or DENY {{ref}}. Details: {{dashboard_url}}“
PhoneTTS: “This is Svantic. {{agent_type}} needs approval for {{title}}. Press 1 to approve. Press 2 to deny.” DTMF: 1=approve, 2=deny.

Alert (Agent Unhealthy, Dispatch Failed, etc.)

ChannelContent
EmailSubject: “Alert: {{rule_name}}”. HTML body with severity indicator, event details table (key-value), and “View in Dashboard” button.
SlackSeverity emoji header (red=critical, yellow=warning, blue=info). Event summary fields. Rule name and severity context line.
WebhookJSON with type: "alert", full event data, severity, rule_name.
SMS”Svantic {{severity}}: {{rule_name}} — {{title}}. View: {{dashboard_url}}“
PhoneTTS: “This is Svantic. {{severity}} alert: {{rule_name}}. {{title}}.” (No DTMF — informational only.)

Operation Complete

ChannelContent
EmailSubject: “Completed: {{title}}”. HTML body with summary, duration, link to trace.
SlackCheckmark header. Operation summary. Link to trace in dashboard.
WebhookJSON with type: "operation_complete", result data, trace_id, duration_ms.
SMS”Svantic: {{title}} completed. View: {{dashboard_url}}“
PhoneNot used for operation complete (not time-sensitive).

Informational (Agent Registered, Session Started, etc.)

ChannelContent
WebhookJSON with type: "informational", event data.
Other channelsNot delivered by default (too noisy). Can be enabled per policy.

Creating Channels

Dashboard

Navigate to Settings → Channels and click New Channel. Select the channel type, provide a name and configuration, and save.

API

POST /internal/channels/new
{
  "type": "slack",
  "name": "Engineering alerts",
  "config": {
    "bot_token": "xoxb-...",
    "channel_id": "C0123456789"
  }
}

Default Channels

Every new tenant is provisioned with four default channels:
ChannelDefault StateReady to Use?
EmailEnabledYes — uses platform SMTP, sends to tenant admin email
SlackCreated, disabledNo — needs bot_token and channel_id
WebhookCreated, disabledNo — needs target URL
Phone/SMSCreated, disabledNo — needs Twilio credentials
The email channel works immediately — no configuration needed beyond the tenant’s admin email address. Other channels require provider credentials before they can deliver.

Linking Channels to Policies

Channels are linked to policies to control which notifications go where:
POST /internal/policies/update
{
  "policy_id": "policy-uuid",
  "channels": [
    { "channel_id": "slack-channel-uuid", "enabled": true },
    { "channel_id": "email-channel-uuid", "enabled": true },
    { "channel_id": "phone-channel-uuid", "enabled": false }
  ]
}
A single channel can be linked to multiple policies. Individual links can be enabled/disabled without removing the channel. This allows fine-grained control — for example, send all alerts to Slack, but only send critical approvals to the phone channel.

Delivery Tracking

Every notification delivery is tracked:
FieldDescription
channel_idWhich channel was used
status_codeHTTP status for webhook/Slack, delivery status for email/SMS
response_time_msDelivery latency
successWhether the delivery succeeded
errorError message if failed
delivered_atTimestamp
View delivery history in Settings → Channels → (select channel) → Delivery Log, or via the API:
POST /internal/channels/deliveries
{ "channel_id": "uuid", "page": 1, "per_page": 20 }

Testing Channels

Send a test notification through any configured channel:
POST /internal/policies/test
{ "policy_id": "policy-uuid" }
This sends a sample notification through all linked channels without triggering any real enforcement. Use this to verify delivery configuration before going live.

API Reference

EndpointDescription
POST /internal/channels/getList all channels for the tenant
POST /internal/channels/newCreate a new channel
POST /internal/channels/updateUpdate channel config or enabled state
POST /internal/channels/deleteDelete a channel (unlinks from all policies)
POST /internal/channels/deliveriesDelivery log for a channel
POST /internal/templates/listList all templates for the tenant
POST /internal/templates/getGet a specific template
POST /internal/templates/updateCreate or update a tenant template override
POST /internal/templates/resetReset a template to the master default

Further Reading