2025-08-05
Build Interactive Microsoft Teams Adaptive Cards

Adaptive Cards That Do Things: Input, Actions, Bots, and Real-Time Teams Workflows
Episode Overview
Tired of static notifications? We turn Adaptive Cards into interactive experiences: collect feedback, kick off flows, branch conversations with bots, and personalize content on the fly. You’ll get copy-paste JSON, deployment tips, and patterns that keep users in Teams while your processes run in the background.
Who This Is For
-
Teams admins, makers, and bot builders
-
Power Automate/Power Platform pros
-
Developers wiring Microsoft 365 workflows via Graph/Bot Framework
-
Comms/HR/IT leads who want higher engagement (and fewer ignored posts)
Core Concepts (Fast)
-
Schema building blocks:
type→ card/element,body→ what users see,actions→ what users do -
Interactivity:
Action.Submit(send data to flow/bot),Action.Execute(context-aware bot actions),Action.OpenUrl(last resort) -
Inputs:
Input.Text,Input.Number,Input.ChoiceSet,Input.Date -
Dynamic UX: Templating (
${...}), data binding,isVisibleconditions
Copy-Paste Starters
1) Collect feedback inside Teams
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{ "type": "TextBlock", "text": "Policy Update: Quick Feedback", "weight": "Bolder", "size": "Large" },
{ "type": "Input.Text", "id": "policyFeedback", "placeholder": "Share your thoughts..." },
{ "type": "Input.ChoiceSet", "id": "sentiment", "style": "expanded",
"choices": [
{ "title": "👍 Helpful", "value": "positive" },
{ "title": "😐 Neutral", "value": "neutral" },
{ "title": "👎 Needs work", "value": "negative" }
] }
],
"actions": [
{ "type": "Action.Submit", "title": "Send", "data": { "kind": "policy-feedback" } }
]
}
What happens: On Send, Teams posts policyFeedback, sentiment, and data.kind to your bot/flow.
2) Kick off a Power Automate flow (HTTP trigger)
-
Configure a When an HTTP request is received trigger.
-
In the card’s
Action.Submit, pass the flow URL via your bot (or use an incoming webhook from the bot). The flow body will include all input IDs anddata.
Expected payload excerpt:
{
"kind": "policy-feedback",
"policyFeedback": "Please clarify WFH days.",
"sentiment": "neutral",
"from": { "aadObjectId": "user-guid", "name": "Adele V." }
}
3) Branch with a bot using Action.Execute
{
"type": "Action.Execute",
"title": "Approve",
"verb": "approveRequest",
"data": { "requestId": "${request.id}" }
}
Bot handler idea: On approveRequest, validate ACLs, write to Dataverse/SharePoint, then respond with an updated card (e.g., mark status Approved and hide buttons).
4) Conditional visibility & personalization
{
"type": "Container",
"items": [
{ "type": "TextBlock", "text": "Hello, ${user.displayName}!" },
{ "type": "TextBlock", "text": "Task: ${task.title}" }
],
"isVisible": "${task.status != 'completed'}"
}
5) Safer choices (prevent fat-fingered writes)
{
"type": "Input.ChoiceSet",
"id": "priority",
"value": "normal",
"choices": [
{ "title": "Low", "value": "low" },
{ "title": "Normal", "value": "normal" },
{ "title": "High (requires reason)", "value": "high" }
],
"wrap": true
}
In your handler, require a justification if priority == "high" before proceeding.
Design Patterns That Work
-
Micro-approvals: Approve/Reject with required comment; update the card inline on completion.
-
Triage cards: ChoiceSet to route tickets; bot posts follow-up questions based on route.
-
Targeted nudges: Card shows “Remind assignees” only if
${overdueCount} > 0. -
Checklists: Render remaining tasks; hide completed items with
isVisible.
Testing & Tooling
-
Use the Adaptive Card Designer to preview for Teams Host + mobile.
-
Validate schema version (use
1.4+ forisVisible,1.5for advanced features). -
Log the raw submit payloads during dev to verify input IDs and data shapes.
Wiring Options (Choose Your Backend)
-
Power Automate: Fastest start; map inputs → SharePoint/Dataverse/Email/Approvals.
-
Bots (Bot Framework / Teams Toolkit): Maximum control; use
Action.Executefor responsive, multi-step flows. -
Azure Functions / Logic Apps: Great for lightweight webhooks and custom APIs.
Guardrails & Gotchas
-
Every input needs an
id. Noid, no data. -
Don’t overuse OpenUrl. Keep users in Teams when possible.
-
Access control: Validate who clicked—never trust client-side visibility alone.
-
State updates: Post a refreshed card after actions to avoid duplicate submissions.
-
Mobile first: Test long text, ChoiceSet behavior, and button wrapping on phones.
-
Versioning: Pin schema/version in templates to avoid host regressions.
Rollout Checklist (30–60 minutes)
-
Pick one message that should collect input (feedback, RSVP, triage).
-
Build the card in Designer; add Input + Action.Submit.
-
Wire to a Power Automate HTTP flow (log to SharePoint/Dataverse).
-
Add conditional visibility for role-specific actions.
-
Pilot in a small Team; iterate on copy/layout; then templatize.
FAQ
-
Can cards update after submission? Yes—post a replacement card or use bot responses.
-
Do I need a bot to collect input? No—Power Automate HTTP trigger works; bots add richer branching.
-
How do I limit who can approve? Validate AAD group/role server-side before processing
Action.*. -
Can I localize text? Yes—bind text from your payload or generate locale-specific templates.
Host: Mirko Peters