Senders are outbound notification adapters. Channels and providers use them to push alerts to email, log files, consoles, or complex routing pipelines — all without touching core code.
Senders are fire-and-forget output adapters that sit alongside the channel and provider subsystems. Any channel or provider calls senders.send(id, configName, message) and the sender subsystem takes care of delivery.
Each sender can hold multiple named configurations, so a single email-smtp sender can deliver to several different inboxes simultaneously, each identified by a config name. Senders are installed and configured from the Manage Senders dialog in the Kwirth UI without writing any code.
Leaf senders — deliver to an external destination
Writes colorized, formatted lines to stdout / stderr. Includes optional ISO timestamps, level tags, and a configurable prefix.
Appends formatted log lines to a file. Supports line-count-based rotation — when the limit is reached, the file is archived and a new one starts.
Sends transactional email via the Resend API. Requires a Resend account and API key. No SMTP configuration needed.
Sends email via any SMTP server. Supports TLS (port 465), STARTTLS (port 587), and plain (unauthenticated relay). Compatible with Gmail, Outlook, Postfix, and others.
Posts colour-coded message cards to a Teams channel via an incoming webhook. Card colour follows the message severity level (red = error, orange = warning, blue = info, gray = debug).
Routing senders — intercept, filter, and dispatch
Fans a single message out to multiple target senders simultaneously. All targets receive the same unmodified message in parallel. If one target fails the rest are unaffected.
Evaluates an ordered list of regex rules against each message. First match wins — the rule can drop the message or forward it to a specific sender. Messages that match no rule follow the default action.
A visual pipeline designer in the Kwirth UI. Combine tee and regex nodes into a tree-based routing graph. No JSON editing needed — the designer generates the config.
Gates messages by time-of-day and day-of-week. Define windows (e.g. Mon–Fri 09:00–18:00) that forward to a specific sender, and silence everything outside. Timezone-aware.
Throttles delivery to a maximum rate per interval so an alert storm can't flood a destination. Messages over the limit are queued and delivered in the next window rather than dropped.
Because senders receive the full ISenderAccess facade at startup, a sender can delegate to other senders. This is how tee, regex, composite, timed, and ratelimit work: they each intercept a message and decide which downstream sender (if any) should receive it.
You can chain them: a timed sender can forward to a regex sender, which can forward to a tee sender, which fans out to email-smtp and file.
Open the menu drawer and choose Manage Senders (requires cluster-scope access key). From there you can:
.tgz uploadSenders with a custom UI (composite, timed) open a dedicated editor instead of the generic config form when you expand their card.
import { ISender, ISenderAccess, ISenderConfig, ISenderFieldDef, ISenderMessage }
from '@kwirthmagnify/kwirth-common-back'
export class SlackSender implements ISender {
readonly id = 'slack'
private configs = new Map<string, { name: string; webhookUrl: string }>()
getConfigSchema(): ISenderFieldDef[] {
return [
{ name: 'name', label: 'Name', required: true },
{ name: 'webhookUrl', label: 'Webhook URL', required: true },
]
}
async send(configName: string, message: ISenderMessage): Promise {
const cfg = this.configs.get(configName)
if (!cfg) throw new Error(`config '${configName}' not found`)
await fetch(cfg.webhookUrl, {
method: 'POST',
body: JSON.stringify({ text: message.body }),
headers: { 'Content-Type': 'application/json' }
})
}
addConfig(c: ISenderConfig) { this.configs.set(c.name, c as any) }
removeConfig(n: string) { this.configs.delete(n) }
hasConfig(n: string) { return this.configs.has(n) }
getConfigNames() { return [...this.configs.keys()] }
async startSender(_: ISenderAccess): Promise {}
async stopSender(): Promise {}
}
export default SlackSender Full ISender interface reference, config schema docs, and packaging guide in the Kwirth docs.
Sender docs → Browse sender sourcesInbound HTTP integration — the Integration extension family that lets external systems call into Kwirth. Where Senders push data out, webhooks bring data in.
A webhook is an installable extension that exposes an HTTP endpoint inside Kwirth. An external service (GitHub, an Alertmanager, a CI job, a business app…) POSTs a payload to that endpoint, the webhook parses it, and routes it to a target channel or plugin — so the rest of Kwirth can observe and react to it in real time.
The inbound URL embeds a secret token, so only callers holding that URL can post — and you can rotate the token at any time to revoke a leaked URL. Inbound endpoints are part of Kwirth's access-key model; treat the URL as a credential.
Open ☰ → Manage extensions → Webhooks. Like every family, you can install from the catalog, from a URL, or by uploading a .tgz; versions are supported. Per webhook you manage its named configs, view/rotate each config's URL + token, choose the target, and export/import configs as JSON.
External systems initiate the call. The counterpart to outbound Senders.
Each config exposes a unique URL with an embedded, rotatable token.
Delivers the received payload to a chosen channel or plugin.
Catalog / URL / upload install, schema-driven config, export & import.