Edictum
Edictum Control PlaneNotifications

Notification Channels

Get notified when agents request approval. Four channel types, with Telegram as the only interactive channel today.

AI Assistance

Right page if: you need to choose between notification channels, configure routing filters, or understand which channel supports interactive approve/deny buttons. Wrong page if: you need setup steps for a specific channel -- see https://docs.edictum.ai/docs/control-plane/notifications/telegram, https://docs.edictum.ai/docs/control-plane/notifications/slack, https://docs.edictum.ai/docs/control-plane/notifications/discord, or https://docs.edictum.ai/docs/control-plane/notifications/webhook. Gotcha: routing filters use AND logic across dimensions but OR logic within a dimension. An empty filter means "receive everything" for that dimension, not "receive nothing."

Get notified when agents request approval. Four channel types, with Telegram as the only interactive approve/deny channel today.

Channel Types

ChannelInteractiveNotes
TelegramYesBot token + chat_id. Inline keyboard buttons.
SlackNoIncoming webhook URL. One-way notification with an app link.
DiscordNoBot token + channel_id. One-way notification with an app link.
WebhookNoGeneric HTTPS POST. One-way notification payload.

Interactive currently means Telegram only. Other channels send a notification with a link back to the app where you can decide.

Adding a Channel

App > Settings > Notifications > Add Channel.

Notification channel configuration in settings

Select the channel type, fill in the configuration fields, and click Test to verify.

Routing Filters

Each channel can have routing filters that control which approval requests it receives:

FilterFormatExample
environmentsList of exact environment names["production", "staging"]
agent_patternsGlob patterns matched against agent_id["prod-*", "ops-agent"]
ruleset_namesGlob patterns matched against the ruleset name["block-*", "require-approval-*"]

How Filters Are Evaluated

Filters are evaluated at notification send time, not when the channel is created. This means you can update filters on a channel and the new filters apply immediately to future approval requests.

AND logic across dimensions. All non-empty filter dimensions must match. If you set both environments: ["production"] and agent_patterns: ["prod-*"], the channel only receives approvals from agents matching prod-* in the production environment.

OR logic within a dimension. Each filter field is a list. A match against any item in the list satisfies that dimension. Setting environments: ["production", "staging"] matches approvals from either environment.

Empty filter = receive everything for that dimension. A channel with no filters receives all approval requests. A channel with only environments set receives all agents and all rulesets in those environments.

Pattern Syntax

agent_patterns and ruleset_names use Python's fnmatch module for pattern matching. The patterns are case-sensitive (fnmatchcase).

PatternMatchesDoes not match
prod-*prod-api, prod-billing-v2staging-api, PROD-api
*-deployci-deploy, prod-deploydeploy, deploy-v2
agent-?agent-1, agent-aagent-12, agent-
[!t]*agent-1, prod-apitest-agent
require-*-approvalrequire-deploy-approvalrequire-approval

Supported wildcards:

WildcardMeaning
*Matches everything
?Matches any single character
[seq]Matches any character in seq
[!seq]Matches any character not in seq

Examples

GoalFilters
Production alerts onlyenvironments: ["production"]
Prod and staging (OR)environments: ["production", "staging"]
One team's agentsagent_patterns: ["platform-*"]
Specific rule alertsruleset_names: ["require-human-approval"]
Deploy rulesets onlyruleset_names: ["*-deploy", "*-deploy-*"]
EverythingLeave all filters empty

Routing Scenarios

Slack for production, Discord for staging:

Create two channels with environment filters:

ChannelTypeenvironments
prod-alertsSlack["production"]
staging-alertsDiscord["staging"]

Both channels can have empty agent_patterns and ruleset_names to receive all approvals in their respective environments.

Telegram for one team's agents, webhook for everything else:

ChannelTypeagent_patterns
ml-team-telegramTelegram["ml-*", "data-*"]
catch-all-webhookWebhook(empty -- receives everything)

The Telegram channel receives approvals from ml-* and data-* agents. The webhook receives all approvals, including those same agents. Filters do not create exclusive routing -- a single approval can match multiple channels and be sent to all of them.

Production deploys by a specific team (AND logic):

ChannelTypeenvironmentsagent_patternsruleset_names
infra-prod-deploysSlack["production"]["infra-*"]["*-deploy"]

All three dimensions must match: the environment is production, the agent ID starts with infra-, and the ruleset name ends with -deploy.

Security

Secrets Encrypted at Rest

Channel configuration secrets are encrypted at rest using NaCl SecretBox. In API responses, sensitive values are masked.

HTTPS Requirement

Telegram requires EDICTUM_BASE_URL to be set to a public HTTPS URL. The control plane must be reachable from the internet for button callbacks to work.

Sending notifications works without HTTPS. Receiving button clicks does not.

Test Button

Every channel has a test button:

POST /v1/notifications/channels/{id}/test

Or click Test in the app. A test message is sent to verify the configuration is correct.

Channel Lifecycle

  1. Add a channel in Settings > Notifications
  2. Test to verify configuration
  3. Enable/disable with the toggle -- disabled channels don't send notifications
  4. Edit to update configuration or filters
  5. Delete to remove permanently

Next Steps

Last updated on

On this page