Skip to content
CloudOps
Newsletter
All guides
AI for Microsoft Teams By James Joyner IV · · 8 min read

Teams Workflows: Routing CI/CD Events Into Channels Cleanly

The Workflows app replaced incoming webhooks. Here's how to route Jenkins, GitHub, and Prometheus events into Teams channels with cards people actually read.

  • #microsoft-teams
  • #workflows
  • #ci-cd
  • #devops
  • #adaptive-cards
  • #automation

Most teams have a #builds channel that nobody reads, and it’s their own fault. They wired every CI/CD event — every build start, every test, every deploy, green and red alike — into one firehose, and within a week everyone muted it. The channel became noise, and the one red build that mattered scrolled past unseen. Routing events into Teams is easy. Routing them so humans actually act on the important ones is the real skill.

With incoming webhooks deprecated in favor of the Workflows app (built on Power Automate), there’s a good moment to rethink not just how you post events but which events and how they look. Here’s the approach that keeps a CI/CD channel useful.

The Workflows-app entry point

The modern way to get an external event into a channel is a workflow triggered by a webhook. You create one from the channel’s Workflows option, pick the “post to a channel when a webhook request is received” template, and Teams hands you a unique HTTPS URL. Your CI system POSTs JSON to that URL; the workflow posts an Adaptive Card to the channel.

The trigger is dumb on purpose — it accepts whatever JSON you send and exposes it to the workflow, where you shape the card. So the intelligence lives in two places: what your CI system chooses to send, and how the workflow renders it.

Filter at the source, not in the channel

The single highest-leverage decision is not sending events nobody needs. Before a single event reaches Teams, decide what’s channel-worthy:

  • Post: deploy succeeded to prod, deploy failed (any env), build failed on main, a release tagged.
  • Don’t post: every PR build, every green build on a feature branch, every individual test pass.

Your CI pipeline should only call the workflow URL for the events on the first list. A curl guarded by a condition in your pipeline is the cheapest filter there is:

# only notify Teams on failure or prod success
if [ "$STATUS" = "failed" ] || { [ "$ENV" = "production" ] && [ "$STATUS" = "succeeded" ]; }; then
  curl -X POST "$TEAMS_WORKFLOW_URL" \
    -H "Content-Type: application/json" \
    -d "{\"service\":\"$SERVICE\",\"status\":\"$STATUS\",\"env\":\"$ENV\",\"version\":\"$VERSION\",\"url\":\"$BUILD_URL\"}"
fi

A channel that only ever shows things that matter is a channel people keep unmuted. That’s the whole game.

Make the card scannable in one second

The default “dump the JSON” card is a wall of text. Design the card so status is legible at a glance — color, a clear title, the few facts that matter, and a button to the build. In the workflow, render an Adaptive Card with the incoming fields bound in:

{
  "type": "AdaptiveCard",
  "version": "1.5",
  "body": [
    {
      "type": "TextBlock",
      "text": "@{triggerBody()?['status']} — @{triggerBody()?['service']}",
      "weight": "Bolder",
      "size": "Large",
      "color": "@{if(equals(triggerBody()?['status'],'succeeded'),'good','attention')}"
    },
    {
      "type": "FactSet",
      "facts": [
        { "title": "Env", "value": "@{triggerBody()?['env']}" },
        { "title": "Version", "value": "@{triggerBody()?['version']}" }
      ]
    }
  ],
  "actions": [
    { "type": "Action.OpenUrl", "title": "View build", "url": "@{triggerBody()?['url']}" }
  ]
}

Red for failure, green for success, a title you read without thinking, and a one-click jump to the logs. That’s the difference between a card someone glances at and acts on versus one they scroll past.

Route by severity to the right channel

Not every event belongs in the same place. The pattern that’s worked for me:

  • #deploys — successful prod deploys, release tags. Calm, informational, the audit trail.
  • #build-failures — red builds on main and failed deploys. This is the actionable channel; keep it sacred and only put genuinely actionable failures here.
  • A targeted activity notification — for a prod deploy failure, also notify the release owner personally so it doesn’t depend on someone watching the channel.

Multiple workflow URLs, one per channel, and your pipeline picks the destination by severity. The failure channel stays low-volume and therefore high-signal.

Operational hygiene

  • Treat the workflow URL as a secret. Anyone with it can post to your channel. Store it in your CI secret manager, rotate it if it leaks, and never commit it.
  • Migrate off legacy incoming webhooks. If you still have old office.com/webhook connector URLs, move them to Workflows now — the legacy connectors are on a deprecation path and will stop delivering.
  • Add a heartbeat. A silent channel is ambiguous: is everything green, or did the integration break? A daily “pipeline integration healthy” post tells you the pipe still works.
  • Coalesce flapping. If a deploy retries five times, don’t post five failure cards. Debounce in the pipeline and post once with a retry count.

The deprecation of incoming webhooks is annoying, but it’s a chance to fix the thing that was always broken — the unread firehose channel. Filter at the source, render cards that are legible in a second, route by severity, and your CI/CD channel becomes something engineers actually trust to tell them when something’s wrong.

For more on event routing in Teams, see the Microsoft Teams category, and the prompt library has prompts for designing CI/CD notification cards.

The Workflows app, trigger templates, and connector deprecation timelines change over time. Verify current Power Automate trigger options and migration deadlines before relying on them.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.