All skills
ccheney avatar

/teams-adaptive-cards

@00695ba

Build, validate, or repair Adaptive Card layouts, actions, forms, and delivery wrappers for Microsoft Teams. Use when Teams is the target host, including bot, webhook, Graph, and MessageCard migration tasks. Exclude Windows/custom card hosts and Teams text-only formatting.

Use this Skill: https://skilld.dev/gh/ccheney/robust-skills/teams-adaptive-cards

This session only. Nothing lands on disk.

referencesACTIONS.md

≈1.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Teams Adaptive Card Actions

Actions are the highest-risk part of Teams cards because support depends on transport and backend.

Action Selection

Need Use
Open a URL or deep link Action.OpenUrl
Submit form inputs to a bot Action.Submit
Cross-host Teams/Outlook invoke with refresh Action.Execute
Show/hide local details Action.ToggleVisibility
Reveal a small inline card Action.ShowCard

Transport Compatibility

Transport OpenUrl Submit Execute Notes
Bot Framework / Teams SDK Yes Yes Yes, with Universal Actions handling Best for interaction
Message extension Yes Depends on extension/action flow Yes for supported Universal Actions scenarios Match extension type
Workflows webhook Yes No — explicitly unsupported Docs list it as allowed, but no bot receives the invoke; treat as unusable Use notification-only cards
Graph chatMessage attachment Renders card attachment Do not assume bot invoke Do not assume bot invoke Graph sends a message, not a bot backend
Outgoing Webhook response OpenUrl only No No Teams outgoing webhooks restrict card actions

Action.OpenUrl

{
  "type": "Action.OpenUrl",
  "title": "View incident",
  "url": "https://example.com/incidents/123"
}

Best practices:

  • Use HTTPS URLs.
  • For Teams deep links, generate valid Teams deep-link URLs.
  • Keep titles short.
  • Do not use URL actions for destructive operations without confirmation on the destination page.

Action.Submit

Submits input values and optional hidden data to the bot.

{
  "type": "Action.Submit",
  "title": "Approve",
  "data": {
    "action": "approve",
    "requestId": "REQ-123"
  }
}

Teams behavior:

  • The bot does not receive input changes until the user selects a submit button.
  • The bot has a short response window for invoke handling.
  • Positive/destructive action styling is not supported in Teams.
  • isEnabled for Action.Submit is not supported in Teams.

Teams msteams Submit Behaviors

Teams supports Bot Framework action behavior through data.msteams.

messageBack
{
  "type": "Action.Submit",
  "title": "Comment",
  "data": {
    "msteams": {
      "type": "messageBack",
      "displayText": "Added a comment",
      "text": "comment",
      "value": "{\"requestId\":\"REQ-123\"}"
    }
  }
}

Use when the bot should receive structured action data and optionally show user-visible display text.

imBack
{
  "type": "Action.Submit",
  "title": "Run status",
  "data": {
    "msteams": {
      "type": "imBack",
      "value": "status REQ-123"
    }
  }
}

Use sparingly; it echoes text back into chat.

signin
{
  "type": "Action.Submit",
  "title": "Sign in",
  "data": {
    "msteams": {
      "type": "signin",
      "value": "https://example.com/auth/start"
    }
  }
}

Prefer Teams SSO/OAuth patterns when building production apps.

task/fetch or invoke
{
  "type": "Action.Submit",
  "title": "Open dialog",
  "data": {
    "msteams": {
      "type": "task/fetch",
      "data": { "requestId": "REQ-123" }
    }
  }
}

Use for dialog/task-module flows when the bot handles invoke activities.

Action.Execute

Universal Actions use Action.Execute and send an adaptiveCard/action invoke to the bot. They are intended for cross-host scenarios such as Teams and Outlook.

{
  "type": "Action.Execute",
  "title": "Approve",
  "verb": "approveRequest",
  "data": {
    "requestId": "REQ-123"
  }
}

Requirements:

  • Use schema version 1.4 or newer.
  • Implement bot invoke handling for adaptiveCard/action.
  • Return updated cards where appropriate.
  • Include fallback behavior if older clients may see the card.
  • For Outlook actionable messages, the card also needs the registered originator GUID; Teams-only bot cards do not.

The bot answers the invoke with a card or message response:

{
  "statusCode": 200,
  "type": "application/vnd.microsoft.card.adaptive",
  "value": { "type": "AdaptiveCard", "version": "1.4", "body": [] }
}

Refresh And User-Specific Views

Refresh lets a card update for specific users, so approvers can see buttons while other viewers see read-only state.

{
  "refresh": {
    "action": {
      "type": "Action.Execute",
      "verb": "refresh",
      "data": { "requestId": "REQ-123" }
    },
    "userIds": [
      "8:orgid:00000000-0000-0000-0000-000000000000"
    ]
  }
}

Rules (verified against Teams user-specific views docs):

  • userIds entries are Teams user MRIs (for example 8:orgid:<Entra object ID>).
  • Maximum 60 users can receive a user-specific view per card. For larger groups, rotate IDs in and out of userIds (for example, drop the earliest responder when the 61st responds) and rely on manual refresh for the rest.
  • If userIds is omitted, Teams auto-triggers refresh for everyone only when the conversation has 60 or fewer members; beyond that, users must pick "Refresh" from the message options menu.
  • Automatic refresh triggers only if the card from the last invoke is older than about a minute.
  • Teams caches up to 50 user-specific cards per user; older cards are evicted.
  • Refresh invokes the bot; no bot means no refresh.
  • Keep refreshed cards consistent with the action result to avoid stale decisions; update the base card with a message update when the shared state changes.

Action.ToggleVisibility

{
  "type": "Action.ToggleVisibility",
  "title": "Show details",
  "targetElements": ["details"]
}

Target elements need id values:

{
  "type": "Container",
  "id": "details",
  "isVisible": false,
  "items": [
    { "type": "TextBlock", "text": "More details", "wrap": true }
  ]
}

Do not hide required inputs behind toggle actions unless the validation behavior is clear and tested.

Action.ShowCard

Use for small inline secondary forms or details. Avoid deeply nested ShowCards. Inputs in ShowCards have parent/child submit behavior that can surprise users and backend code.

Confirmation And Destructive Actions

Teams has no built-in confirm prompt or destructive styling for card actions. For destructive actions:

  • Make the button text unambiguous ("Delete pipeline", not "OK").
  • Make the backend idempotent.
  • Include an operation ID in data.
  • Return an updated card that clearly shows final state.

Anti-Patterns

Anti-Pattern Problem Fix
Action.Submit in webhook card Explicitly unsupported; no bot receives it Use OpenUrl or a bot
Action.Execute without bot invoke handler Button fails Implement Universal Actions handling
Relying on style: "destructive" Teams does not support action styling Use clear text and idempotent backend
Missing hidden IDs in data Backend cannot correlate action Include stable IDs
Updating state only in chat text Card remains stale Update/replace card or use refresh
More than 60 userIds in refresh Extra IDs beyond the limit get no user-specific view Rotate the list; provide manual refresh

Source: SKILL.md on GitHub

No alerts18d3 checks · Risk SAFE
  • Gen Agent Trust Hub18d

    The skill is a comprehensive documentation and validation toolkit for Microsoft Teams Adaptive Cards. It includes reference guides for card elements, actions, and delivery surfaces, along with a local Node.js script for linting card payloads. No malicious patterns or security risks were identified.

  • Socket18d

    No alerts

  • Snyk18d

    Risk: LOW · No issues

Signed by skilld at 00695ba. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated 3 weeks ago

README badge

README badge for ccheney/robust-skills/teams-adaptive-cards