> For the complete documentation index, see [llms.txt](https://docs.groundcover.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.groundcover.com/~/revisions/ETrLpNk6KtHjyaVUTLoE/use-groundcover/workflows/full-webhook-examples/slack-app-for-channel-routing.md).

# Slack App for Channel Routing

groundcover supports sending notifications to Slack using a **Slack App with bot tokens** instead of static webhooks. This method allows dynamic routing of alerts to any channel by including the channel ID in the payload. In addition to routing, messages can be enriched with formatting, blocks, and mentions — for example including <@user\_id> in the payload to directly notify specific team members. This provides a flexible and powerful alternative to fixed incoming webhooks for alerting.

Make sure you created a [webhook for a Slack App with Bot Tokens](https://docs.groundcover.com/~/revisions/ETrLpNk6KtHjyaVUTLoE/integrations/workflow-integrations/slack-app-with-bot-tokens).

Use the following workflow as an example. You can later enrich your workflow with additional functionality.

Here are a few tips for using the example workflow:

1. In the consts section, the `channels` attribute defines the mapping between Slack channels and their IDs. Use a clear, readable label to identify each channel (for example, the channel’s actual name in Slack), and map it to the corresponding channel ID.
2. To find a channel ID, open Slack in your browser, navigate to the channel, and copy the last part of the URL - that is the channel ID.\
   ![](/files/y5ELg7RhnvqrFZVzGf7h)
3. The channel name should be included in the monitor’s **Metadata Labels**, or you can fall back to a default. See the channel\_id attribute in the workflow example.\
   ![](/files/kPnV4lZsSaMtRhJZT2UB)
4. Finally, replace the integration name in `{{ providers.slack-routing-webhook }}` with the actual name of the Webhook integration you created.

```yaml
workflow:
  id: slack-channel-routing-workflow
  description: workflow for all channels with dynamic routing
  triggers:
  - type: alert
    filters:
    - key: annotations.slack-channel-routing-workflow
      value: enabled
  name: slack-channel-routing-workflow
  consts:
    channels: '{"devops":"C0111111111", "alerts":"C0222222222", "incidents":"C0333333333"}'
    channel_id: keep.dictget( '{{ consts.channels }}', '{{ alert.labels.channel_id }}', 'C09G9AFHLTB')
    env: keep.dictget({{ alert.labels }}, 'env', 'no-env')
    upper_env: "keep.uppercase({{consts.env}})"
    severity: keep.dictget({{ alert.annotations }}, '_gc_severity', 'unknown-severity')
    summary: keep.dictget({{ alert.labels }}, 'summary', 'no-summary')
    slack_message: "<https://app.groundcover.com/monitors/create-silence?keep.replace(keep.join(keep.dict_pop({{ alert.labels }}, \"_gc_monitor_id\", \"_gc_monitor_name\", \"_gc_severity\", \"backend_id\", \"grafana_folder\", \"_gc_issue_header\"), \"&\", \"matcher_\"), \" \", \"+\")|Silence> :no_bell: | \n<https://app.groundcover.com/monitors/issues?backendId={{ alert.labels.backend_id }}&selectedObjectId={{ alert.fingerprint }}|Investigate> :mag: | \n<https://app.groundcover.com/monitors?backendId={{ alert.labels.backend_id }}&selectedObjectId={{ alert.labels._gc_monitor_id }}|See Monitor> :chart_with_upwards_trend:\n\n*Labels:*  \n- keep.join(keep.dict_pop({{alert.labels}}, \"_gc_monitor_id\", \"_gc_monitor_name\", \"_gc_severity\", \"backend_id\", \"grafana_folder\", \"_gc_issue_header\"), \"\\n- \")\n"
    title_link: "https://app.groundcover.com/monitors/issues?backendId={{ alert.labels.backend_id }}&selectedObjectId={{ alert.fingerprint }}"
    red_color: "#FF0000"
    green_color: "#008000"
    footer_url: "groundcover.com"
    footer_icon: "https://app.groundcover.com/favicon.ico"
  actions:
  - if: "{{ alert.status }} == 'firing'"
    name: webhook-alert
    provider:
      type: webhook
      config: "{{ providers.slack-routing-webhook }}"
      with:
        body:
          channel: "{{ consts.channel_id }}"
          attachments:
          - color: "{{ consts.red_color }}"
            footer: "{{ consts.footer_url }}"
            footer_icon: "{{ consts.footer_icon }}"
            text: "{{ consts.slack_message }}"
            title: "\U0001F6A8 Firing: {{ alert.alertname }} [{{ consts.upper_env}}]"
            title_link: "{{ consts.title_link }}"
            type: plain_text
  - if: "{{ alert.status }} != 'firing'"
    name: webhook-alert-resolved
    provider:
      type: webhook
      config: "{{ providers.slack-routing-webhook }}"
      with:
        body:
          channel: "{{ consts.channel_id }}"
          text: "\u2705 [RESOLVED][{{ consts.upper_env}}] {{ consts.severity }} {{ alert.alertname }}"
          attachments:
          - color: "{{ consts.green_color }}"
            text: "*Summary:* {{ consts.summary }}"
            fields:
            - title: "Environment"
              value: "{{ consts.upper_env}}"
              short: true
            footer: "{{ consts.footer_url }}"
            footer_icon: "{{ consts.footer_icon }}"
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.groundcover.com/~/revisions/ETrLpNk6KtHjyaVUTLoE/use-groundcover/workflows/full-webhook-examples/slack-app-for-channel-routing.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
