Skip to content
DevOps AI ToolKit
Newsletter
All prompts
AI for Grafana Difficulty: Intermediate ClaudeChatGPT

Grafana Alerting Notification Templates Prompt

Author custom Grafana alert notification message templates with Go templating for contact points (Slack, email, PagerDuty).

Target user
SREs and on-call engineers customizing alert payloads
Difficulty
Intermediate
Tools
Claude, ChatGPT

The prompt

You are a senior SRE who builds Grafana unified-alerting notification templates using Go text/template so on-call gets actionable, deduplicated messages.

I will provide:
- The contact point type (Slack, email, PagerDuty, webhook)
- The alert rules and label/annotation schema
- Current message (if any) and what is missing

Your job:

1. **Template scope**: define a named template with `{{ define "myorg.title" }}` and reference it from the contact point's Title/Message fields via `{{ template "myorg.title" . }}`.
2. **Iterate alerts**: loop `{{ range .Alerts }}` and split firing vs resolved with `.Alerts.Firing` and `.Alerts.Resolved`; show counts with `{{ len .Alerts.Firing }}`.
3. **Surface context**: print `{{ .Labels.alertname }}`, `{{ .Labels.severity }}`, `{{ .Annotations.summary }}`, `{{ .Annotations.description }}`, and the runbook via `{{ .Annotations.runbook_url }}`.
4. **Add links**: include `{{ .GeneratorURL }}`, `{{ .SilenceURL }}`, `{{ .DashboardURL }}`, and `{{ .PanelURL }}` for one-click triage.
5. **Group cleanly**: use `{{ .GroupLabels }}` and `{{ .CommonLabels }}` for the title; avoid dumping every label. Sort with `{{ .Labels.SortedPairs }}`.
6. **Format per channel**: Slack supports mrkdwn (`*bold*`, `<url|text>`); email supports HTML; keep PagerDuty summary under length limits.
7. **Guard emptiness**: wrap optional fields in `{{ if .Annotations.runbook_url }}...{{ end }}` so missing annotations do not render blank lines.
8. **Test**: preview under Alerting > Contact points > template preview, or fire a test notification before shipping.

Mark DESTRUCTIVE: editing a shared org-wide template used by many contact points, or removing a `define` block other contact points reference (silent broken notifications).

---

Contact point: [DESCRIBE]
Alert labels/annotations: [DESCRIBE]
Current message: [DESCRIBE]

Why this prompt works

Grafana’s unified alerting exposes a rich data model (.Alerts, .GroupLabels, .CommonLabels, annotation fields) to Go templates, but the docs scatter the field names across pages. This prompt forces a channel-aware template that separates firing from resolved, surfaces runbook and silence links, and guards against missing fields — the difference between an actionable page and a wall of labels.

How to use it

  1. Name the contact point type so formatting (mrkdwn vs HTML) is correct.
  2. Paste your label/annotation schema so templates reference real keys.
  3. Preview in the UI before saving to a live contact point.
  4. Version the template in provisioning YAML once validated.

Useful commands

# List contact points and templates via API
curl -s -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/v1/provisioning/templates | jq

# Create/update a notification template group
curl -X PUT -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  http://localhost:3000/api/v1/provisioning/templates/myorg-slack \
  -d '{"name":"myorg-slack","template":"{{ define \"myorg.slack.title\" }}...{{ end }}"}'

# Trigger a test notification for a contact point
curl -X POST -H "Authorization: Bearer $TOKEN" \
  http://localhost:3000/api/alertmanager/grafana/config/api/v1/receivers/test

Relevant grafana.ini keys:

[server]
root_url = https://grafana.example.com

[unified_alerting]
enabled = true

Example config

Provisioned template plus contact point reference:

apiVersion: 1
templates:
  - orgId: 1
    name: myorg-slack
    template: |
      {{ define "myorg.slack.title" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}{{ end }}
      {{ define "myorg.slack.body" }}
      {{ range .Alerts.Firing }}
      *{{ .Labels.severity | toUpper }}* {{ .Annotations.summary }}
      {{ if .Annotations.runbook_url }}<{{ .Annotations.runbook_url }}|Runbook> · {{ end }}<{{ .SilenceURL }}|Silence> · <{{ .DashboardURL }}|Dashboard>
      {{ end }}{{ end }}

contactPoints:
  - orgId: 1
    name: slack-critical
    receivers:
      - uid: slack-crit-1
        type: slack
        settings:
          recipient: "#alerts-critical"
          title: '{{ template "myorg.slack.title" . }}'
          text: '{{ template "myorg.slack.body" . }}'

Common findings this catches

  • Wall-of-labels messages → switch to SortedPairs and select fields.
  • Broken linksroot_url missing so SilenceURL/DashboardURL 404.
  • Blank lines → unguarded optional annotations.
  • Resolved spam → separate .Alerts.Resolved handling or suppress.
  • Truncated PagerDuty pages → summary too long.
  • HTML in Slack → wrong channel formatting.

When to escalate

  • Org-wide shared templates touched by many teams — coordinate changes.
  • Compliance review of what leaves via external channels — security.
  • Alert routing/grouping redesign — alerting platform owner.

Related prompts

Newsletter

Free: the DevOps AI Incident-Triage Cheat Sheet

Subscribe and we’ll send you the one-page cheat sheet — plus weekly AI prompts, automation ideas, and tool reviews for infrastructure engineers. One email a week. No spam, unsubscribe anytime.

  • AI Incident-Triage Cheat Sheet (PDF)
  • Access to 2,104 DevOps AI prompts
  • One practical workflow email per week