Notifications

6 builtins for sending notifications from pipelines and scripts. Get pinged on Slack, Teams, Telegram, Discord, or email when your analysis finishes or fails. All config via environment variables — set once, use everywhere.

Smart Router

notify(message) String | Record → Nil

Sends a notification to whichever provider is configured in BIOLANG_NOTIFY. Accepts a plain string or a structured record. If no provider is set, prints to stderr.

# Simple string
notify("Alignment complete: 24 samples processed")

# Structured record — provider formats it natively
notify({
  title: "QC Pipeline Complete",
  status: "success",
  fields: {
    samples: 24,
    pass_rate: "96%",
    output: "/data/results/cohort.vcf.gz"
  }
})

Environment

BIOLANG_NOTIFY — provider name: slack, teams, telegram, discord, or email. Plus the provider-specific env vars below.

Slack

slack(message) String | Record → Nil

Sends a message to Slack via incoming webhook. String messages send as plain text. Record messages use Block Kit formatting with header, status, and fields.

# Using env var SLACK_WEBHOOK
slack("Variant calling finished: 1,234 SNPs, 456 indels")

# Explicit webhook URL
slack("https://hooks.slack.com/services/xxx/yyy/zzz",
      "Pipeline complete")

SLACK_WEBHOOK — Slack incoming webhook URL

Microsoft Teams

teams(message) String | Record → Nil

Sends a message to Microsoft Teams via incoming webhook. Record messages use Adaptive Card formatting with title, text, and facts.

# Using env var TEAMS_WEBHOOK
teams("RNA-seq pipeline complete: 12 samples normalized")

# Structured notification
teams({
  title: "Cohort Analysis",
  status: "success",
  fields: {
    samples: 48,
    variants: "2.3M",
    ti_tv: 2.1
  }
})

TEAMS_WEBHOOK — Teams incoming webhook URL

Telegram

telegram(message) String | Record → Nil

Sends a message via Telegram Bot API. Supports Markdown formatting. Three calling conventions depending on how much config is in env vars.

# All config from env vars
telegram("Alignment done: tumor.sorted.bam")

# Specify chat_id, token from env
telegram("-1001234567890", "Pipeline failed: low mapping rate")

# Fully explicit
telegram("123456:ABC-DEF", "-1001234567890", "Analysis complete")

TELEGRAM_BOT_TOKEN — Bot token from @BotFather

TELEGRAM_CHAT_ID — Target chat/group/channel ID

Discord

discord(message) String | Record → Nil

Sends a message to Discord via webhook. String messages send as plain content. Record messages use rich embed formatting with title, description, and inline fields.

# Using env var DISCORD_WEBHOOK
discord("FASTQ QC complete: 98% pass rate")

# Structured embed
discord({
  title: "Variant Calling Report",
  fields: {
    snps: 1234,
    indels: 456,
    ti_tv: 2.08
  }
})

DISCORD_WEBHOOK — Discord webhook URL

Email (SMTP)

email(to, subject, body) String, String, String → Nil

Sends an email via SMTP. Connects directly to your SMTP server with AUTH LOGIN. The body can be a string or a record (formatted as key-value pairs).

email("lab@example.com",
      "Pipeline Complete",
      "Variant calling finished. 1,234 SNPs and 456 indels in cohort.vcf.gz")

SMTP_HOST — SMTP server hostname

SMTP_PORT — Port (default: 587)

SMTP_USER — Username

SMTP_PASS — Password

SMTP_FROM — From address (defaults to SMTP_USER)

Pipeline Integration

Notifications pair naturally with pipelines. Add a final stage or use defer for guaranteed delivery even on failure.

# Variant calling pipeline with notifications
shell("bwa-mem2 mem -t 16 GRCh38.fa sample_R1.fq.gz sample_R2.fq.gz | samtools sort -@ 8 -o aligned.bam")

shell("gatk HaplotypeCaller -R GRCh38.fa -I aligned.bam -O raw.vcf.gz")
let variants = read_vcf("raw.vcf.gz") |> collect()
let snps = variants |> filter(|v| is_snp(v)) |> len()
let indels = variants |> filter(|v| is_indel(v)) |> len()

# Notify on completion
notify({
  title: "Variant Calling Complete",
  fields: {SNPs: snps, Indels: indels, output: "raw.vcf.gz"}
})

Setup

Set environment variables once in your shell profile. Then notify() works everywhere.

# ~/.bashrc or ~/.zshrc

# Pick your provider
export BIOLANG_NOTIFY=slack

# Slack
export SLACK_WEBHOOK=https://hooks.slack.com/services/T.../B.../xxx

# Teams
export TEAMS_WEBHOOK=https://outlook.office.com/webhook/...

# Telegram
export TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
export TELEGRAM_CHAT_ID=-1001234567890

# Discord
export DISCORD_WEBHOOK=https://discord.com/api/webhooks/...

# Email (for notify() with BIOLANG_NOTIFY=email)
export SMTP_HOST=smtp.gmail.com
export SMTP_USER=you@gmail.com
export SMTP_PASS=app-password-here
export NOTIFY_EMAIL_TO=lab@example.com

Summary

BuiltinProviderEnv Vars
notify(msg)Auto (reads BIOLANG_NOTIFY)BIOLANG_NOTIFY + provider vars
slack(msg)SlackSLACK_WEBHOOK
teams(msg)Microsoft TeamsTEAMS_WEBHOOK
telegram(msg)TelegramTELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID
discord(msg)DiscordDISCORD_WEBHOOK
email(to, subj, body)SMTPSMTP_HOST, SMTP_USER, SMTP_PASS