Skip to main content

Notifications and Bots

Akritas sends notifications after a successful alert investigation. Telegram and Mattermost can also use the normal Chat investigation loop as bidirectional bot interfaces. Prepare Change and Apply are not available through bots.

Three receiver types are supported:

  • webhook receives the complete versioned JSON envelope;
  • telegram sends compact text through the Telegram Bot API sendMessage;
  • mattermost creates a post through the Mattermost REST API using a bot account.

Quick start​

Copy the example and connect it through a service option:

cp configs/akritas/notifications.example.json \
configs/akritas/notifications.local.json

export AKRITAS_NOTIFICATIONS_CONFIG=configs/akritas/notifications.local.json

The same path can be supplied through notifications_config in the main JSON configuration or with -notifications-config. The normal CLI, environment, service configuration, and default precedence applies. An empty path disables notifications and bot ingress.

The notification configuration is a separate strict version 1 JSON file. It accepts 1 to 16 receivers and an optional timeout up to 1m, with a default of 10s. Unknown fields, duplicate names, and missing environment variables stop startup. The example also contains bounded queue and history settings for bot chat.

Generic webhook​

{
"version": 1,
"receivers": [{
"name": "automation",
"type": "webhook",
"url_env": "AKRITAS_INCIDENT_WEBHOOK_URL",
"bearer_token_env": "AKRITAS_INCIDENT_WEBHOOK_TOKEN",
"hmac_secret_env": "AKRITAS_INCIDENT_WEBHOOK_HMAC_SECRET"
}]
}

Either url or url_env is required. Bearer and HMAC authentication are optional and can be enabled together. X-Akritas-Signature has the form sha256=<hex> and covers the exact JSON body. Akritas also sends X-Akritas-Event, X-Akritas-Delivery, and, when available, X-Akritas-Run-ID.

The envelope contains event: incident.investigated, a unique delivery ID, a UTC timestamp, and an incident object with the model, canonical alert, answer, selected skills, tool activity, capability gaps, validated investigation, and Run budget. The maximum payload is 512 KiB. A receiver must treat model text as untrusted data, not instructions.

Telegram​

Create a bot, keep its token in a secret-backed environment variable, and add the bot to the group. In a direct chat, the user must message the bot first because a bot cannot initiate the conversation.

{
"name": "telegram-ops",
"type": "telegram",
"bot_token_env": "AKRITAS_TELEGRAM_BOT_TOKEN",
"chat_id_env": "AKRITAS_TELEGRAM_CHAT_ID",
"message_thread_id_env": "AKRITAS_TELEGRAM_THREAD_ID",
"inbound_mode": "polling"
}

chat_id can be stored directly in the configuration or resolved through chat_id_env. Optional message_thread_id or message_thread_id_env selects a topic. base_url defaults to https://api.telegram.org; change it only for a self-hosted Bot API server.

In polling mode, Akritas calls getUpdates with a 30-second long-poll timeout. It needs no public endpoint or webhook secret. Without an explicit allowlist, only messages from the configured chat_id are accepted. For more complex access, configure allowed_conversation_ids, allowed_conversation_ids_env, allowed_user_ids, or allowed_user_ids_env.

Telegram polling and webhook modes are mutually exclusive. Akritas does not automatically delete a previously registered provider webhook; call deleteWebhook when necessary. The poller uses bounded backoff during temporary network failures and advances its offset only after a message enters the local queue.

For webhook mode, replace inbound_mode and add a secret and allowlist:

{
"inbound_mode": "webhook",
"inbound_secret_env": "AKRITAS_TELEGRAM_WEBHOOK_SECRET",
"allowed_conversation_ids_env": "AKRITAS_TELEGRAM_ALLOWED_CHAT_IDS"
}

Register the provider webhook separately:

curl --fail-with-body \
-X POST "https://api.telegram.org/bot${AKRITAS_TELEGRAM_BOT_TOKEN}/setWebhook" \
--data-urlencode "url=https://akritas.example/api/v1/bots/telegram/telegram-ops/webhook" \
--data-urlencode "secret_token=${AKRITAS_TELEGRAM_WEBHOOK_SECRET}" \
--data-urlencode 'allowed_updates=["message"]'

Akritas verifies the official X-Telegram-Bot-Api-Secret-Token, chat and user allowlists, and is_bot. History is isolated by chat and topic.

Mattermost​

Create a Mattermost bot account, add it to the required team and channel, and grant permission to create posts. Akritas requires the bot access token:

{
"name": "mattermost-ops",
"type": "mattermost",
"base_url_env": "AKRITAS_MATTERMOST_URL",
"bot_token_env": "AKRITAS_MATTERMOST_BOT_TOKEN",
"channel_id_env": "AKRITAS_MATTERMOST_CHANNEL_ID",
"inbound_secret_env": "AKRITAS_MATTERMOST_OUTGOING_WEBHOOK_TOKEN",
"allowed_conversation_ids_env": "AKRITAS_MATTERMOST_ALLOWED_CHANNEL_IDS",
"allowed_user_ids_env": "AKRITAS_MATTERMOST_ALLOWED_USER_IDS"
}

Create an outgoing webhook or slash command with this callback:

https://akritas.example/api/v1/bots/mattermost/mattermost-ops/webhook

The integration token must match inbound_secret_env. An outgoing webhook works in public channels; use a slash command for a private channel or direct message. The bot account sends replies through the REST API. An explicit user allowlist is required and must not contain the bot's own ID, which would permit a feedback loop.

Chat lifecycle​

Bot ingress does not use the common AKRITAS_API_KEY. Telegram polling uses the bot token over TLS and applies allowlists; webhook adapters verify a separate provider secret and the same allowlists. After verification, Akritas places the update in a bounded memory queue. One worker invokes the normal RAG, skills, planning, and read-only tool loop and sends the response through the provider.

Conversation history lives only in process memory. Defaults are 20 messages and 64 KiB per session, a 24-hour TTL, at most 256 sessions, and a queue of 64 updates. Configure these limits with bot_history_messages, bot_history_bytes, bot_session_ttl, bot_max_sessions, and bot_queue_size. A restart clears history and the in-memory duplicate cache.

Commands are /help, /new, /reset, /status, and /ask <question>. Ordinary text is treated as a question. Long answers are split into multiple messages. Successful Runs use source telegram_bot or mattermost_bot, and delivery creates the bot_reply audit event. Prompts and answers are not stored in audit.

Failure semantics​

Receivers run in parallel and best effort. One failure does not block other receivers. Akritas makes one attempt and has no persistent queue or automatic retry. Each receiver status is recorded in the notification_delivery audit event.

A delivery failure does not change an already successful investigation into a failed job, so a provider retry does not rerun the model merely because Telegram or Mattermost was unavailable. For guaranteed delivery, point the generic webhook at an external durable queue or outbox.

Chat adapters do not send raw tool results. They use a fixed compact message, neutralize @, collapse line breaks inside fields, and escape Mattermost Markdown. Telegram messages are limited to 4,000 Unicode characters and Mattermost messages to 16,000; truncated messages contain an explicit marker.