docs/operator-manual/notifications/services/teams-workflows.md
The Teams Workflows notification service sends message notifications using Microsoft Teams Workflows (Power Automate). This is the recommended replacement for the legacy Office 365 Connectors service, which will be retired on March 31, 2026.
The Teams Workflows notification service requires specifying the following settings:
recipientUrls - the webhook url map, e.g. channelName: https://api.powerautomate.com/webhook/...The service supports the following Microsoft Teams Workflows webhook URL patterns:
https://api.powerautomate.com/...https://api.powerplatform.com/...https://flow.microsoft.com/.../powerautomate/ in the pathTeams and go to the channel you wish to set notifications forWorkflowsManageNew flowSend webhook alerts to a channel in the search bar or select it from the template listapi.powerautomate.com, api.powerplatform.com, or flow.microsoft.com)argocd-notifications-secret and define it in argocd-notifications-cmapiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
service.teams-workflows: |
recipientUrls:
channelName: $channel-workflows-url
apiVersion: v1
kind: Secret
metadata:
name: <secret-name>
stringData:
channel-workflows-url: https://api.powerautomate.com/webhook/your-webhook-id
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.teams-workflows: channelName
Teams Workflows provides enhanced channel support compared to Office 365 Connectors, allowing you to post to shared and private channels in addition to standard channels.
The Teams Workflows service uses Adaptive Cards exclusively, which is the modern, flexible card format for Microsoft Teams. All notifications are automatically converted to Adaptive Card format and wrapped in the required message envelope.
The service automatically converts template fields to Adaptive Card format. This is the simplest and most maintainable approach:
template.app-sync-succeeded: |
teams-workflows:
# ThemeColor supports Adaptive Card semantic colors: "Good", "Warning", "Attention", "Accent"
# or hex colors like "#000080"
themeColor: "Good"
title: Application {{.app.metadata.name}} has been successfully synced
text: Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}.
summary: "{{.app.metadata.name}} sync succeeded"
facts: |
[{
"name": "Sync Status",
"value": "{{.app.status.sync.status}}"
}, {
"name": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}]
sections: |
[{
"facts": [
{
"name": "Namespace",
"value": "{{.app.metadata.namespace}}"
},
{
"name": "Cluster",
"value": "{{.app.spec.destination.server}}"
}
]
}]
potentialAction: |-
[{
"@type": "OpenUri",
"name": "View in Argo CD",
"targets": [{
"os": "default",
"uri": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
}]
}]
How it works:
title → Converted to a large, bold TextBlocktext → Converted to a regular TextBlockfacts → Converted to a FactSet elementsections → Facts within sections are extracted and converted to FactSet elementspotentialAction → OpenUri actions are converted to Action.OpenUrlthemeColor → Applied to the title TextBlock (supports semantic colors like "Good", "Warning", "Attention", "Accent" or hex colors)For full control and advanced features, you can provide a complete Adaptive Card JSON template:
template.app-sync-succeeded: |
teams-workflows:
adaptiveCard: |
{
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Application {{.app.metadata.name}} synced successfully",
"size": "Large",
"weight": "Bolder",
"color": "Good"
},
{
"type": "TextBlock",
"text": "Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}.",
"wrap": true
},
{
"type": "FactSet",
"facts": [
{
"title": "Sync Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View in Argo CD",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
}
]
}
Note: When using adaptiveCard, you only need to provide the AdaptiveCard JSON structure (not the full message envelope). The service automatically wraps it in the required message + attachments format for Teams Workflows.
Important: If you provide adaptiveCard, it takes precedence over all other template fields (title, text, facts, etc.).
The Teams Workflows service supports the following template fields, which are automatically converted to Adaptive Card format:
title - Message title (converted to large, bold TextBlock)text - Message text content (converted to TextBlock)summary - Summary text (currently not used in Adaptive Cards, but preserved for compatibility)themeColor - Color for the title. Supports:
"Good" (green), "Warning" (yellow), "Attention" (red), "Accent" (blue)"#000080", "#FF0000", etc.facts - JSON array of fact key-value pairs (converted to FactSet)
facts: |
[{
"name": "Status",
"value": "{{.app.status.sync.status}}"
}]
sections - JSON array of sections containing facts (facts are extracted and converted to FactSet)
sections: |
[{
"facts": [{
"name": "Namespace",
"value": "{{.app.metadata.namespace}}"
}]
}]
potentialAction - JSON array of action buttons (OpenUri actions converted to Action.OpenUrl)
potentialAction: |-
[{
"@type": "OpenUri",
"name": "View Details",
"targets": [{
"os": "default",
"uri": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
}]
}]
adaptiveCard - Complete Adaptive Card JSON template (takes precedence over all other fields)
template - Raw JSON template (legacy, use adaptiveCard instead)
| Template Field | Adaptive Card Element | Notes |
|---|---|---|
title | TextBlock with size: "Large", weight: "Bolder" | ThemeColor applied to this element |
text | TextBlock with wrap: true | Uses n.Message if text is empty |
facts | FactSet | Each fact becomes a title/value pair |
sections[].facts | FactSet | Facts extracted from sections |
potentialAction[OpenUri] | Action.OpenUrl | Only OpenUri actions are converted |
themeColor | Applied to title TextBlock.color | Supports semantic and hex colors |
If you're currently using the teams service with Office 365 Connectors, follow these steps to migrate:
Create a new Workflows webhook using the configuration steps above
Update your service configuration:
service.teams to service.teams-workflowsUpdate your templates:
teams: to teams-workflows: in your templatestitle, text, facts, sections, potentialAction) will automatically be converted to Adaptive Card formatUpdate your subscriptions:
# Old
notifications.argoproj.io/subscribe.on-sync-succeeded.teams: channelName
# New
notifications.argoproj.io/subscribe.on-sync-succeeded.teams-workflows: channelName
Test and verify:
Note: Your existing templates will work without modification. The service automatically converts your template fields to Adaptive Card format, so you get the benefits of modern cards without changing your templates.
| Feature | Office 365 Connectors | Teams Workflows |
|---|---|---|
| Service Name | teams | teams-workflows |
| Standard Channels | ✅ | ✅ |
| Shared Channels | ❌ | ✅ (Dec 2025+) |
| Private Channels | ❌ | ✅ (Dec 2025+) |
| Card Format | messageCard (legacy) | Adaptive Cards (modern) |
| Template Conversion | N/A | Automatic conversion from template fields |
| Retirement Date | March 31, 2026 | Active |
The Teams Workflows service leverages Adaptive Cards, which provide:
For complex notifications, you can use the full Adaptive Card specification:
template.app-sync-succeeded-advanced: |
teams-workflows:
adaptiveCard: |
{
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "https://example.com/success-icon.png",
"size": "Small"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Application {{.app.metadata.name}}",
"weight": "Bolder",
"size": "Large"
},
{
"type": "TextBlock",
"text": "Successfully synced",
"spacing": "None",
"isSubtle": true
}
]
}
]
},
{
"type": "FactSet",
"facts": [
{
"title": "Status",
"value": "{{.app.status.sync.status}}"
},
{
"title": "Repository",
"value": "{{.app.spec.source.repoURL}}"
}
]
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View in Argo CD",
"url": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}"
}
]
}