M365Con 2027 – free online conference · 11–22 Jan 2027 · 120 sessions→ m365con.net

2025-08-05

Build Interactive Microsoft Teams Adaptive Cards

Build Interactive Microsoft Teams Adaptive Cards
Stop posting pretty-but-pointless Teams cards. Adaptive Cards can capture input, fire approvals, update themselves, and even drive bots—without users ever leaving Teams. In this episode, you’ll learn the JSON essentials (body, actions, data binding), how to wire Action.Submit/Execute to Power…

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, isVisible conditions

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 and data.

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+ for isVisible, 1.5 for 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.Execute for responsive, multi-step flows.

  • Azure Functions / Logic Apps: Great for lightweight webhooks and custom APIs.

Guardrails & Gotchas

  • Every input needs an id. No id, 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)

  1. Pick one message that should collect input (feedback, RSVP, triage).

  2. Build the card in Designer; add Input + Action.Submit.

  3. Wire to a Power Automate HTTP flow (log to SharePoint/Dataverse).

  4. Add conditional visibility for role-specific actions.

  5. 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.

YouTube

Host: Mirko Peters

Related articles

← Automate Microsoft 365 with the Cross-Platform CLIFix OneDrive Files On-Demand Sync Issues →