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:
| Field | Description |
|---|
tenant_id | Which tenant this template belongs to |
event_type | Which event triggers this template (e.g., guard.approval_required) |
channel_type | Which channel this template is for (email, slack, webhook, sms, phone) |
Template content varies by channel:
| Channel | Template fields |
|---|
| Email | subject (text with variables), html_body (HTML with variables) |
| Slack | blocks (Block Kit JSON with variables), fallback_text |
| Webhook | payload_schema (JSON structure with variables) |
| SMS | message (plain text with variables, max ~300 chars) |
| Phone | tts_script (text-to-speech script with variables), dtmf_options (keypad mapping) |
Template Variables
Templates can reference variables from the notification context:
| Variable | Description |
|---|
{{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:
- Exact match:
(tenant_id, event_type, channel_type) — tenant has a custom template for this specific event and channel
- Category fallback:
(tenant_id, event_category.*, channel_type) — tenant has a template for the event category (e.g., guard.* catches all guard events)
- Default fallback:
(tenant_id, *, channel_type) — tenant’s catch-all template for the channel
- 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:
| Event | In-App | Email | Slack | Webhook | SMS | Phone |
|---|
| guard.approval_required | Yes | Yes | Yes | Yes | No | No |
| policy.approval_required | Yes | Yes | Yes | Yes | No | No |
| agent.health_changed (unhealthy) | Yes | Yes | Yes | Yes | No | No |
| agent.deregistered | Yes | Yes | Yes | Yes | No | No |
| dispatch.failed (threshold) | Yes | Yes | Yes | Yes | No | No |
| message.error | Yes | No | No | No | No | No |
| message.completed | No | No | No | Yes | No | No |
| agent.registered | Yes | No | No | Yes | No | No |
| session.started | No | No | No | Yes | No | No |
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
| Channel | Content |
|---|
| Email | Subject: “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. |
| Slack | Header block with title. Description section. Approve/Deny buttons for simple approvals, or “Complete in Dashboard” button for complex forms. |
| Webhook | JSON with type: "approval_required", A2UI spec, callback_token, resolve_url. |
| SMS | ”Svantic: Approval needed — {{title}}. Reply APPROVE {{ref}} or DENY {{ref}}. Details: {{dashboard_url}}“ |
| Phone | TTS: “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.)
| Channel | Content |
|---|
| Email | Subject: “Alert: {{rule_name}}”. HTML body with severity indicator, event details table (key-value), and “View in Dashboard” button. |
| Slack | Severity emoji header (red=critical, yellow=warning, blue=info). Event summary fields. Rule name and severity context line. |
| Webhook | JSON with type: "alert", full event data, severity, rule_name. |
| SMS | ”Svantic {{severity}}: {{rule_name}} — {{title}}. View: {{dashboard_url}}“ |
| Phone | TTS: “This is Svantic. {{severity}} alert: {{rule_name}}. {{title}}.” (No DTMF — informational only.) |
Operation Complete
| Channel | Content |
|---|
| Email | Subject: “Completed: {{title}}”. HTML body with summary, duration, link to trace. |
| Slack | Checkmark header. Operation summary. Link to trace in dashboard. |
| Webhook | JSON with type: "operation_complete", result data, trace_id, duration_ms. |
| SMS | ”Svantic: {{title}} completed. View: {{dashboard_url}}“ |
| Phone | Not used for operation complete (not time-sensitive). |
| Channel | Content |
|---|
| Webhook | JSON with type: "informational", event data. |
| Other channels | Not 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:
| Channel | Default State | Ready to Use? |
|---|
| Email | Enabled | Yes — uses platform SMTP, sends to tenant admin email |
| Slack | Created, disabled | No — needs bot_token and channel_id |
| Webhook | Created, disabled | No — needs target URL |
| Phone/SMS | Created, disabled | No — 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:
| Field | Description |
|---|
channel_id | Which channel was used |
status_code | HTTP status for webhook/Slack, delivery status for email/SMS |
response_time_ms | Delivery latency |
success | Whether the delivery succeeded |
error | Error message if failed |
delivered_at | Timestamp |
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
| Endpoint | Description |
|---|
POST /internal/channels/get | List all channels for the tenant |
POST /internal/channels/new | Create a new channel |
POST /internal/channels/update | Update channel config or enabled state |
POST /internal/channels/delete | Delete a channel (unlinks from all policies) |
POST /internal/channels/deliveries | Delivery log for a channel |
POST /internal/templates/list | List all templates for the tenant |
POST /internal/templates/get | Get a specific template |
POST /internal/templates/update | Create or update a tenant template override |
POST /internal/templates/reset | Reset a template to the master default |
Further Reading