---
title: "Route alerts to team channels | Grafana Cloud documentation"
description: "Send each new alert group to the Slack channel of the team that owns it, based on its team label, with a fallback channel for everything else."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Route alerts to team channels

> Note
> 
> Grafana Workflows is currently in [public preview](https://grafana.com/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.

Send each new alert group to the Slack channel of the team that owns it, based on its team label, with a fallback channel for everything else.

This Grafana Workflows blueprint is in the **Alerts** category of the Blueprints library.

## Before you begin

To use this blueprint, you need:

- Grafana IRM set up on your stack.
- Slack connected to Grafana IRM. For details, refer to [Configure Slack for Grafana IRM](https://grafana.com/docs/grafana-cloud/alerting-and-irm/irm/integrations/chat-and-collaboration/slack/).

## Steps

Steps run in order from first to last. A step inside a switch branch runs only when Workflows chooses that branch.

Expand table

| Step                                                             | ID              | Type                 | Description                                                                                                                  |
|------------------------------------------------------------------|-----------------|----------------------|------------------------------------------------------------------------------------------------------------------------------|
| Route by team label                                              | `route-by-team` | `switch`             | Picks the channel from the team label. Replace payments and platform with your team label values, and add a branch per team. |
| Post to the payments channel (branch 1 of `route-by-team`)       | `post-payments` | `slack.message.post` | Posts payments alerts. Set `channelID` to the payments team channel.                                                         |
| Post to the platform channel (branch 2 of `route-by-team`)       | `post-platform` | `slack.message.post` | Posts platform alerts. Set `channelID` to the platform team channel.                                                         |
| Post to the fallback channel (default branch of `route-by-team`) | `post-fallback` | `slack.message.post` | Posts alerts with no matching team label so nothing is missed. Set `channelID` to a shared triage channel.                   |

For the inputs and outputs of each step type, refer to [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types).

Before you turn on the workflow, customize any steps that need input from you, such as a channel ID or a schedule name. Each step’s description says what to set.

## Workflow definition

Save this definition as a YAML file to create the workflow with gcx, the Workflows API, or Terraform, or give it to a coding agent as an example. Replace *FOLDER\_UID* with the UID of the folder for the workflow. Blueprints start disabled, so finish customizing the steps before you set `enabled` to `true`. For details, refer to [Manage workflows as code](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code).

YAML ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```yaml
apiVersion: workflows.ext.grafana.app/v1alpha1
kind: Definition
metadata:
  name: route-alerts-to-team-channels
  annotations:
    grafana.app/folder: <FOLDER_UID>
spec:
  name: Route alerts to team channels
  enabled: false
  startWhen:
    matchingRules:
      - eventNameRegex: 'grafana_irm_app\.alertgroup\.updated'
        filter: "inputs.data.eventKind == 'created'"
    schedules: []
  steps:
    - id: route-by-team
      type: switch
      name: Route by team label
      description: Picks the channel from the team label. Replace payments and platform with your team label values, and add a branch per team.
      branches:
        - condition: "resources.alertgroup.event.labels.exists(l, l.key.name == 'team' && l.value.name == 'payments')"
          steps:
            - id: post-payments
              type: slack.message.post
              name: Post to the payments channel
              description: Posts payments alerts. Set channelID to the payments team channel.
              inputs:
                channelID: ''
                messageText: ':bell: <${resources.alertgroup.event.permalinks.web}|${resources.alertgroup.event.title}> (${resources.alertgroup.event.alerts_count} alerts)'
        - condition: "resources.alertgroup.event.labels.exists(l, l.key.name == 'team' && l.value.name == 'platform')"
          steps:
            - id: post-platform
              type: slack.message.post
              name: Post to the platform channel
              description: Posts platform alerts. Set channelID to the platform team channel.
              inputs:
                channelID: ''
                messageText: ':bell: <${resources.alertgroup.event.permalinks.web}|${resources.alertgroup.event.title}> (${resources.alertgroup.event.alerts_count} alerts)'
        - steps:
            - id: post-fallback
              type: slack.message.post
              name: Post to the fallback channel
              description: Posts alerts with no matching team label so nothing is missed. Set channelID to a shared triage channel.
              inputs:
                channelID: ''
                messageText: ':grey_question: Unrouted alert: <${resources.alertgroup.event.permalinks.web}|${resources.alertgroup.event.title}>. Add a team label to route it next time.'
```

## How it works

This section explains when the workflow runs and how its steps work together.

### When it runs

This blueprint starts on the `grafana_irm_app.alertgroup.updated` event.

Its trigger filter starts a run only when this CEL expression is true:

text ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```text
inputs.data.eventKind == 'created'
```

### How the steps fit together

These notes cover how the steps connect and which Workflows behaviors the blueprint relies on.

- Triggers on `grafana_irm_app.alertgroup.updated` with `eventKind` created.
- A switch checks the auto-loaded alert group’s labels (`resources.alertgroup.event.labels`) with the CEL `exists()` macro, where each label is {key: {name}, value: {name}}.
- It routes to the first branch whose team label matches, and the default branch catches unlabeled alerts.
- Each branch needs its own step IDs, because step IDs are unique across the whole workflow.
- This is the pattern to copy for any one-of-many routing, for example by service, environment, or cluster.
- Customize the team values in each condition, add or remove branches, and set each channel.

## Next steps

- [Blueprints](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/blueprints)
- [Start from a blueprint](https://grafana.com/docs/grafana-cloud/platform/workflows/build/use-blueprints)
- [Manage workflows as code](https://grafana.com/docs/grafana-cloud/platform/workflows/as-code)
- [Step and trigger types reference](https://grafana.com/docs/grafana-cloud/platform/workflows/reference/step-trigger-types)
