Skip to content
AI & Agents
Skill

/add-adaptive-card

Generate and insert an Adaptive Card into a Copilot Studio topic using AdaptiveCardPrompt. Use when the user asks to add an adaptive card, rich card, form card, info card, confirmation card, or interactive card to a topic.

BOOST
From plugin
copilot-studio
46931 skills4 agents1 hook
Install
$ npx -y skills add microsoft/skills-for-copilot-studio --skill add-adaptive-card --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/add-adaptive-card

Context preview

The summary Claude sees to decide when to auto-load this skill.

Generate and insert an Adaptive Card into a Copilot Studio topic using AdaptiveCardPrompt. Use when the user asks to add an adaptive card, rich card, form card, info card, confirmation card, or interactive card to a topic.

SKILL.md

add-adaptive-card.SKILL.md
user-invocable: false
description: Generate and insert an Adaptive Card into a Copilot Studio topic using AdaptiveCardPrompt. Use when the user asks to add an adaptive card, rich card, form card, info card, confirmation card, or interactive card to a topic.
argument-hint: <card-type> in <topic-name>
allowed-tools: Bash(node *schema-lookup.bundle.js *), Read, Write, Edit, Glob
context: fork
agent: copilot-studio-author

Add Adaptive Card

Add an `AdaptiveCardPrompt` node to an existing Copilot Studio topic. Use this for all Adaptive Card scenarios — display-only cards, input forms, and confirmation flows.

Instructions

1. **Auto-discover the agent directory**:

   Glob: agents/**/agent.mcs.yml

NEVER hardcode an agent name.

2. **Clarify requirements** from the user if not specified:

  • Which topic should the card be added to?
  • Which card type (form, info, confirmation)?
  • What fields, labels, and placeholders are needed?
  • Which topic variables should receive the submitted values?

3. **Read the target topic file** to understand its structure and find the correct insertion point.

4. **Verify the schema** if needed:

   # Copilot Studio node schema
   node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js summary AdaptiveCardPrompt

   # Adaptive Cards element schema (v1.6 — the version supported by Copilot Studio)
   node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js ac-summary TextBlock
   node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js ac-summary Input.Text
   node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js ac-search Action

5. **Select and adapt the template** from [card-templates.md](card-templates.md) matching the requested type.

6. **Generate unique IDs** for all new nodes (format: `<nodeType>_<6-8 random alphanumeric>`).

7. **Insert the node(s)** at the correct position in the `actions` array using Edit.

8. **Validate** the updated topic file:

   node ${CLAUDE_SKILL_DIR}/../../scripts/schema-lookup.bundle.js validate <topic-file.yml>

9. **Inform the user** that they must push (VS Code Extension) and publish (Copilot Studio UI) before testing with `/chat-with-agent` or `/run-tests`.

AdaptiveCardPrompt Structure

`AdaptiveCardPrompt` is the correct node kind for all Adaptive Cards in Copilot Studio. The card JSON is embedded as a **multiline YAML literal string** under `card: |`.

- kind: AdaptiveCardPrompt
  id: adaptiveCardPrompt_m9Kp2x
  card: |
    {
      "type": "AdaptiveCard",
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "version": "1.5",
      "body": [...],
      "actions": [...]
    }
  output:
    binding:
      fieldId: Topic.MyVariable
  outputType:
    properties:
      fieldId:
        type: String

**Rules**:

  • `card: |` — the literal block scalar is mandatory. Do not use `card: >` or inline the JSON without it.
  • `$schema` and `version` are required inside the card JSON.
  • The `output.binding` maps each card input `id` to a topic variable (`Topic.VarName`, no `=` prefix).
  • `outputType.properties` must declare a type for every bound field.
  • Use plain `binding:` — no `kind:` property inside it.
  • **Every `AdaptiveCardPrompt` must have `output`, `outputType`, and an `Action.Submit` button** — including display-only info cards. Omitting any of these causes VS Code extension errors (`MissingRequiredProperty`, `AdaptiveCardMissingActionSubmit`).
  • For info cards with no meaningful inputs, add an `Action.Submit` (e.g. "OK") and bind a dummy acknowledgement variable (`Topic.CardAcknowledged`, type `String`).

Node Comparison

| Node | Use When | |------|----------| | `AdaptiveCardPrompt` | Any Adaptive Card — with or without input fields | | `SendActivity` | Plain text messages with optional `{}` variable interpolation |

Do NOT use `SendActivity` with an `attachments` array for Adaptive Cards.

Field Validation

Do NOT use `style: "Email"` or `style: "Tel"` for validation — these only change the mobile keyboard and do not validate on submit. Always use `regex`:

{
  "type": "Input.Text",
  "id": "email",
  "label": "Email address",
  "placeholder": "Enter your email address",
  "isRequired": true,
  "regex": "^[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}$",
  "errorMessage": "Enter a valid email address"
}
{
  "type": "Input.Text",
  "id": "mobile",
  "label": "Mobile number",
  "placeholder": "Enter your mobile number",
  "isRequired": true,
  "regex": "^[+]?[0-9][\\s\\-\\(\\)0-9]{6,14}$",
  "errorMessage": "Enter a valid mobile number"
}

| Approach | Validates on submit? | Notes | |----------|---------------------|-------| | `regex` | Yes — blocks submit if pattern fails | Use for email, phone, any format | | `isRequired: true` | Yes — blocks submit if empty | Mandatory fields | | `style: "Email"` | No | Keyboard hint only — never use for validation | | `style: "Tel"` | No | Keyboard hint only — never use for validation |

> **Rule**: Every `Input.ChoiceSet` (and any required input) must have a `label` property, or the VS Code extension raises `AdaptiveCardInputIsRequiredMissingLabel`.

Output Binding

  • Card input `id` values must exactly match the keys in `output.binding`.
  • Topic variable references: `Topic.VariableName` (no `=` prefix).
  • Declare every bound field in `outputType.properties` with its type.
output:
  binding:
    userName: Topic.UserName
    userEmail: Topic.UserEmail
    category: Topic.Category
outputType:
  properties:
    userName:
      type: String
    userEmail:
      type: String
    category:
      type: String

Dynamic Text Around Cards

Card JSON is static — Power Fx expressions and `{}` interpolation do not work inside the card body. Use `SendActivity` before or after `AdaptiveCardPrompt` for dynamic content:

- kind: SendActivity
  id: sendMessage_Rz4Wq1
  activity: "Hello {Topic.UserName}, please
Read more
Ships withcopilot-studio

A plugin for Claude Code, GitHub Copilot CLI, and VS Code that enables authoring, testing, and troubleshooting Microsoft Copilot Studio STANDARD agents through YAML files — directly from your terminal or editor.

Get the whole plugin

Other skills on copilot-studio.