agentleFS
MicrosoftKnown publishermicrosoft/cat-agent-skills/submissions/copilot-studio-adaptive-card-builder/SKILL.md

copilot-studio-adaptive-card-builder

Skill95 starsChanged 6 days agoMITView on GitHub

Use this skill whenever a user asks to create, generate, design, review, validate, lint, troubleshoot, or improve an Adaptive Card for Microsoft Copilot Studio standard-harness agents, including forms, confirmations, approvals, welcome prompts, status cards, handoff cards, input mappings, Action.Submit payloads, Power Fx card formulas, accessibility, host compatibility, or paste-ready card JSON. The skill may run in a skills-capable GitHub Copilot harness, but its generated package cannot render or be tested there because that harness does not support Adaptive Cards or topic nodes. Use it before claiming that Adaptive Card JSON is ready for a Copilot Studio node. Do not use it to claim that generative instructions dynamically render native cards.

We split this skill into the rules it gives an agent

48 rules. About 0 are common, 31 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈31

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Create a complete maker-assistance package, not an isolated JSON block.

    line 19
  2. Distinctive:

    Read references/host-profiles-and-contracts.md when selecting a profile, template, output contract, or wiring pattern.

    line 42
  3. Distinctive:

    Read references/evals.md when evaluating this skill or checking an edge case.

    line 44
  4. Very specific:

    Use the cards under assets/templates/ as known-good starting points.

    line 46
  5. Very specific:

    Use scripts/validate_cards.py for deterministic checks when Python execution is available.

    line 48
  6. Very specific:

    If the user does not specify a channel, select portable-1.5.

    line 74
  7. Distinctive:

    Do not request production secrets or records.

    line 76
  8. Distinctive:

    Keep the template's safe structure unless the requirement needs a justified change.

    line 91
  9. Distinctive:

    Every input must have:

    line 95
  10. Very specific:

    Every Action.Submit must have a descriptive title and a data object containing:

    line 104
  11. Very specific:

    Keep each actionSubmitId unique to its button and card version.

    line 116
  12. Very specific:

    Only after that gate may actionId select the already-validated branch.

    line 122
  13. Very specific:

    Keep input IDs distinct from every top-level data key on submit actions that collect inputs.

    line 125
  14. Very specific:

    add a clearly worded Input.Toggle confirmation.

    line 143
  15. Very specific:

    keep associatedInputs on auto so the confirmation is validated.

    line 149
  16. Distinctive:

    never present the card itself as the authorization boundary.

    line 151
  17. Very specific:

    Use Adaptive Cards schema 1.5 unless the requirement specifically needs a verified 1.6 feature and the target is web-chat-1.6 or …

    line 155
  18. Very specific:

    Start with a wrapped TextBlock using style: "heading".

    line 163
  19. Very specific:

    Use input label rather than a nearby TextBlock as the only label.

    line 165
  20. Distinctive:

    Keep JSON order aligned with intended keyboard and screen-reader order.

    line 166
  21. Distinctive:

    Use descriptive action titles.

    line 167
  22. Very specific:

    Use Action.Submit for interactive outcomes and HTTPS Action.OpenUrl only when a link is genuinely required.

    line 168
  23. Very specific:

    Do not use Action.Execute, external images, hidden validated inputs, Action.ShowCard, or Action.ToggleVisibility in the bounded profile.

    line 169
  24. Very specific:

    Do not use ${variable} placeholders in paste-ready JSON.

    line 170
  25. Very specific:

    When the bundled script can run, execute it from the skill root (the directory containing SKILL.md).

    line 183
  26. Very specific:

    When using --warnings-as-errors, warnings must also be resolved before the run passes.

    line 191
  27. Distinctive:

    Do not call the result "official schema validation." Do not claim the script ran if execution was unavailable.

    line 209
  28. Distinctive:

    Add an Ask with Adaptive Card node.

    line 215
  29. Distinctive:

    Call the tool, flow, or handoff only after those checks.

    line 222
  30. Distinctive:

    Add a Message or Question node.

    line 227
  31. Distinctive:

    Add an Adaptive Card and paste the JSON.

    line 228
  32. Distinctive:

    Do not use an Ask with Adaptive Card node without a submit action.

    line 229
  33. Distinctive:

    Do not claim accessibility conformance from static inspection alone.

    line 249
  34. Distinctive:

    Test in Copilot Studio test chat.

    line 285
  35. Distinctive:

    Test every published target channel separately.

    line 286
  36. Distinctive:

    Verify keyboard order and screen-reader announcements.

    line 288
  37. Distinctive:

    Verify downstream authorization and business rules.

    line 289
  38. Distinctive:

    Verify the text fallback.

    line 290
  39. Distinctive:

    Never describe a static preview, designer preview, or successful lint as proof of host rendering.

    line 292
  40. Distinctive:

    Never embed secrets, tokens, credentials, sensitive identifiers, or raw production data.

    line 296
  41. Distinctive:

    Never use a card as an authorization or transaction control.

    line 297
  42. Distinctive:

    Never invent host support, variable mappings, schema behavior, or Power Fx syntax.

    line 298
  43. Distinctive:

    Never imply that instructions alone render a card.

    line 299
  44. Distinctive:

    Never call the bounded linter a complete schema validator.

    line 300
  45. Distinctive:

    Never claim cross-channel parity without channel-specific testing.

    line 301
  46. Distinctive:

    Never make color the only signal.

    line 302
  47. Distinctive:

    Never add destructive actions without explicit confirmation and downstream enforcement.

    line 303
  48. Distinctive:

    Never upload a sensitive card to a public preview service.

    line 304

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Copilot Studio Adaptive Card Builder

Create a complete maker-assistance package, not an isolated JSON block.

Non-negotiable platform boundary

The generated package is for Copilot Studio agents on the standard harness only. This skill may be invoked from a skills-capable GitHub Copilot harness, but Adaptive Cards and topic nodes are not supported there. Do not attempt to render or test the generated card in that same GitHub Copilot harness agent. Hand the package to a maker to configure and test in a standard-harness agent and its intended published channels.

Generative instructions do not dynamically render an Adaptive Card. Produce artifacts that a maker can paste or configure in a standard-harness Copilot Studio card node. Never tell the user that adding JSON to agent instructions makes a native card appear. Model-emitted JSON is normally displayed as text.

Use:

  • Ask with Adaptive Card for interactive cards that collect input or submit an action.
  • Message or Question for informational cards that do not submit.
  • A Power Fx formula in the card node when the card must include dynamic topic, global, environment, or system values.

This skill does not publish an agent, edit a live Copilot Studio topic, guarantee rendering parity, replace authorization, or provide a complete Power Fx authoring framework.

Load supporting material only when needed

Read references/host-profiles-and-contracts.md when selecting a profile, template, output contract, or wiring pattern.

Read references/evals.md when evaluating this skill or checking an edge case.

Use the cards under assets/templates/ as known-good starting points. Adapt the smallest suitable template rather than drafting from scratch.

Use scripts/validate_cards.py for deterministic checks when Python execution is available. The script is a bounded semantic linter, not full official schema validation.

Workflow

1. Classify the request

Choose one task:

  • Build a new card package from a requirement.
  • Review supplied card JSON and wiring.
  • Repair a card that fails validation or channel testing.
  • Adapt a bundled template.

Capture or infer:

InputRequired decision
Interaction goalWhat decision, information, or data collection the card supports
Node modeInteractive or informational
Target channelTeams, Omnichannel live chat, Web Chat, test chat, or portable
Data behaviorStatic JSON or dynamic Power Fx
Fields and actionsInputs, defaults, validation, submit actions, links
Downstream useConditions, variables, flow, connector, API, or handoff
RiskSensitive data, destructive actions, authorization, external content
LocaleUser-facing language and date, time, or number expectations

If the user does not specify a channel, select portable-1.5. If node mode is unclear, infer it from whether the user must submit data and state the inference.

Do not request production secrets or records. Use synthetic sample values.

2. Select the narrowest template

Choose one of:

  1. welcome-starter-prompts.json
  2. information-summary.json
  3. data-collection-form.json
  4. confirmation.json
  5. approval-decision.json
  6. choice-disambiguation.json
  7. status-progress.json
  8. escalation-handoff.json

Keep the template's safe structure unless the requirement needs a justified change. Prefer one column. Keep no more than three primary actions. Do not add external images by default.

3. Design the explicit contract

Every input must have:

  • a unique, stable id;
  • a visible and accessible label;
  • a declared output type;
  • a downstream variable name;
  • required-state behavior and an errorMessage when required;
  • synthetic sample data when useful.

Every Action.Submit must have a descriptive title and a data object containing:

{
  "cardId": "stable_card_identifier",
  "actionId": "stable_action_identifier",
  "actionSubmitId": "card_and_action_specific_identifier",
  "intent": "stable.machine.intent",
  "riskLevel": "none | consequential | destructive"
}

Keep each actionSubmitId unique to its button and card version. Before branching, require the exact expected cardId and actionSubmitId for the currently awaited card/version, using trusted conversation state rather than values supplied by the client. The version is part of the package's versioned card identity, not the Adaptive Cards schema version. Reject missing, unknown, cross-card, expired, or already-consumed submissions without invoking work. Only after that gate may actionId select the already-validated branch; never accept it alone. Identity matching does not replace downstream authorization.

Keep input IDs distinct from every top-level data key on submit actions that collect inputs. Associated input values can overwrite same-named action data, including branch identity and risk metadata. Explicit escape actions using associatedInputs: "none" collect no inputs and have no such merge collision.

Adaptive Card validation cannot make one input required only for selected submit actions. Keep conditionally required inputs optional in the card, then enforce the rule downstream after branching on the trusted expected action identity. For the approval template, allow reviewComment to be blank for Approve. For Reject or Request changes, trim reviewComment; if it is blank, reprompt and do not record or invoke the decision.

For destructive or irreversible operations:

Require riskLevel: "destructive" when the action title or any string value anywhere in submit data names a listed destructive operation, treating identifier separators and camel case like spaces, with no exceptions.

  • add a clearly worded Input.Toggle confirmation;
  • set it as required with an error message;
  • set value explicitly to the distinct valueOff value; do not assume a custom valueOff changes the schema's omitted-value default of "false";
  • bind its exact ID with confirmationInputId; the ID need not contain confirm;
  • include riskLevel: "destructive" and requiresExplicitConfirmation: true in submit data;
  • keep associatedInputs on auto so the confirmation is validated;
  • recheck permissions and business rules downstream;
  • never present the card itself as the authorization boundary.

4. Author the card

Use Adaptive Cards schema 1.5 unless the requirement specifically needs a verified 1.6 feature and the target is web-chat-1.6 or test-chat-1.6.

Schema 1.5 is the package minimum because heading style is required. Do not target 1.3 or 1.4 or remove the heading to accommodate an older schema.

Apply these defaults:

  • Include $schema, type, version, body, and meaningful fallbackText.
  • Start with a wrapped TextBlock using style: "heading".
  • Set wrap: true on every TextBlock.
  • Use input label rather than a nearby TextBlock as the only label.
  • Keep JSON order aligned with intended keyboard and screen-reader order.
  • Use descriptive action titles. Never use vague titles such as "Click here."
  • Use Action.Submit for interactive outcomes and HTTPS Action.OpenUrl only when a link is genuinely required.
  • Do not use Action.Execute, external images, hidden validated inputs, Action.ShowCard, or Action.ToggleVisibility in the bounded profile.
  • Do not use ${variable} placeholders in paste-ready JSON. They are not Copilot Studio variable binding.
  • Set associatedInputs: "none" only on explicit escape actions that must bypass form validation. Such actions must use riskLevel: "none" and isEscapeAction: true.

For a dynamic card:

  1. Produce a valid static representative as card.json.
  2. Produce a separate card.powerfx formula using verified Copilot Studio Power Fx syntax.
  3. Reference variables with explicit scope such as Topic.Title.
  4. Provide synthetic sample-data.json that corresponds to the representative.
  5. Validate the static representative and clearly state that the linter does not parse Power Fx.

5. Validate

When the bundled script can run, execute it from the skill root (the directory containing SKILL.md). Replace the card path, profile, and mode as needed:

python scripts/validate_cards.py card.json --profile portable-1.5 --mode interactive

Repair every error. Review every warning. Run again until the card has no errors. When using --warnings-as-errors, warnings must also be resolved before the run passes. Text status, JSON result ok, and exit code reflect that strictness.

The linter checks:

  • JSON syntax and required root structure;
  • selected host profile and maximum version;
  • the bounded element and action allowlists;
  • required child arrays and high-confidence property types;
  • duplicate or missing input IDs;
  • labels, required-field errors, and heading or wrapping defaults;
  • Action.Submit identity data and collisions with associated input IDs;
  • HTTPS links;
  • unsupported template expressions;
  • secret-like input IDs and visible prompts (labels, placeholders, error messages, and toggle titles), plus embedded credential patterns;
  • destructive-action confirmation patterns;
  • interactive versus informational node requirements.

Do not call the result "official schema validation." Do not claim the script ran if execution was unavailable. In that case, report "mechanical validation not run" and perform the same checks manually.

6. Produce Copilot Studio wiring

For an interactive card:

  1. Add an Ask with Adaptive Card node.
  2. Paste the JSON literal, or switch the node to Formula and insert the Power Fx version.
  3. Save the designer so Copilot Studio creates output variables from input IDs.
  4. Review the generated output schema and correct types with Edit Schema when needed.
  5. Require the exact expected cardId and actionSubmitId for the currently awaited card/version from trusted conversation state before branching; reject stale, unknown, or mismatched identities without invoking work.
  6. Map each input ID to the named downstream topic variable.
  7. Revalidate required data, authorization, stale submissions, and business rules.
  8. Call the tool, flow, or handoff only after those checks.
  9. Configure retry and interruption behavior intentionally.

For an informational card:

  1. Add a Message or Question node.
  2. Add an Adaptive Card and paste the JSON.
  3. Do not use an Ask with Adaptive Card node without a submit action.

For consecutive or retried interactive cards, track which card instance is currently awaited and consume a successful submission only once. Distinguish reissued instances with fresh submit identities or a downstream freshness check; matching the static template's identifiers alone cannot detect replays.

7. Apply accessibility and mobile checks

Report:

  • whether every input has a meaningful label;
  • whether required fields have useful errors;
  • whether JSON order produces a logical focus order;
  • whether headings and wrapped text are present;
  • whether color is reinforced by text;
  • whether action titles make sense when announced alone;
  • whether columns, density, and action count are mobile-safe;
  • which screen-reader and channel tests remain for the maker.

Do not claim accessibility conformance from static inspection alone.

8. Return the complete package

Use this order:

## Boundary and assumptions
## Card JSON
## Power Fx card formula
## Sample or test data
## Input and output mapping
## Action mapping
## Copilot Studio wiring
## Validation result
## Accessibility and mobile notes
## Plain-text fallback
## Channel test checklist

Omit the Power Fx section only for a static card. Omit sample data only when it adds no value.

The mapping must include:

Card field or actionCard typeCopilot Studio output or payloadDownstream variable or branchValidation or control

The validation result must name the profile, mode, linter version, error count, warning count, and command used. If validation was manual, say so.

The plain-text fallback must preserve the decision or collection goal without depending on card rendering. For interactive cards, provide a numbered or clearly delimited response format the topic can parse or route to a human.

9. Require real host testing

End with a short checklist:

  • Paste or configure the card in the intended Copilot Studio node.
  • Test in Copilot Studio test chat.
  • Test every published target channel separately.
  • Exercise required fields, invalid values, every action, retries, interruptions, stale clicks, and duplicate submits.
  • Verify keyboard order and screen-reader announcements.
  • Verify downstream authorization and business rules.
  • Verify the text fallback.

Never describe a static preview, designer preview, or successful lint as proof of host rendering.

Guardrails

  • Never embed secrets, tokens, credentials, sensitive identifiers, or raw production data.
  • Never use a card as an authorization or transaction control.
  • Never invent host support, variable mappings, schema behavior, or Power Fx syntax.
  • Never imply that instructions alone render a card.
  • Never call the bounded linter a complete schema validator.
  • Never claim cross-channel parity without channel-specific testing.
  • Never make color the only signal.
  • Never add destructive actions without explicit confirmation and downstream enforcement.
  • Never upload a sensitive card to a public preview service.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.