Copilot Studio Adaptive Card Builder
Standard-harness target only. This skill may be loaded in a skills-capable GitHub Copilot harness, but the package it produces targets Copilot Studio agents on the standard harness. The GitHub Copilot harness does not support Adaptive Cards or topic nodes, so the generated card cannot render or be tested in that same agent. Configure and test the package in a standard-harness agent and its intended published channels.
Turn a plain-language interaction requirement into a maker-ready Adaptive Card package for a Microsoft Copilot Studio standard-harness agent. The skill produces the card, sample data when useful, input and action mappings, node wiring guidance, validation results, accessibility notes, and a plain-text fallback.
Important boundary
Agent instructions cannot dynamically render an Adaptive Card. The skill creates artifacts for a maker to paste or configure in a standard-harness Copilot Studio Ask with Adaptive Card, Message, or Question node. If card JSON is emitted into chat by a model, it normally appears as text or a code block rather than as a native card.
This is a maker-assistance skill. It is not a runtime UX engine, an authorization control, a complete Power Fx framework, or a guarantee that every channel renders a card identically.
What makes it useful
The package goes beyond generating JSON:
- Eight conservative templates cover welcome prompts, information summaries, data collection, confirmation, approvals, disambiguation, status, and escalation.
- A dependency-free Python semantic linter checks the high-confidence failures that commonly break Copilot Studio cards.
- Explicit input, output, and action contracts make downstream conditions and tools easier to wire.
- Host profiles prevent a card built for the test pane from silently depending on features unavailable in Teams or live chat.
- Accessibility and mobile-safe defaults are built into the workflow.
- Every result includes a plain-text fallback.
The linter is intentionally bounded. It is not a replacement for the official Adaptive Cards schema, the Copilot Studio designer, or testing in each target channel.
Before you start
You need:
- Microsoft Copilot Studio access to edit an agent topic.
- Python 3.10 or later only if you want to run the bundled linter locally. The linter uses the Python standard library and installs no packages.
- A clear target channel. If none is supplied, the skill defaults to the portable Copilot Studio 1.5 profile.
Do not provide secrets, tokens, credentials, sensitive identifiers, or raw production records as example content.
How to use it
Ask in plain language:
- “Build a Teams-safe approval card for a purchase request.”
- “Create an accessible intake form with category, due date, and details.”
- “Make a status summary card for a Message node, plus a text fallback.”
- “Review this Adaptive Card JSON for Copilot Studio and explain how to wire its outputs.”
- “Turn this confirmation step into a card package, but require explicit confirmation before the destructive action.”
The response should contain:
card.json, a paste-ready static card or static representative for a dynamic card.card.powerfx, only when dynamic values genuinely require a Power Fx formula.- Sample or test data when the card is dynamic or data-driven.
- Input, output, and action mapping.
- Copilot Studio node and downstream wiring guidance.
- Linter results with the selected host profile.
- Accessibility and mobile notes.
- A plain-text fallback.
Validate a card
From the skill directory:
python scripts/validate_cards.py assets/templates --profile portable-1.5
Validate a generated card and require a specific node mode:
python scripts/validate_cards.py card.json --profile teams-1.5 --mode interactive
Machine-readable output is available with --format json. Add --warnings-as-errors for a stricter quality gate: warnings then produce FAIL in text, ok: false in JSON results, and a nonzero exit code. Diagnostics retain their original warning severity.
Run the 93 regression tests and strict template lint from the same skill directory:
python -B -m unittest discover -s scripts/tests -p "test_*.py"
python -B scripts/validate_cards.py assets/templates --profile portable-1.5 --warnings-as-errors
Host profiles
| Profile | Maximum card version | Intended use |
|---|---|---|
portable-1.5 |
1.5 | Default across Teams, live chat, Web Chat, and test chat |
teams-1.5 |
1.5 | Microsoft Teams |
omnichannel-1.5 |
1.5 | Omnichannel live chat widget |
web-chat-1.6 |
1.6 | Bot Framework Web Chat, excluding Action.Execute |
test-chat-1.6 |
1.6 | Copilot Studio test chat only |
The bundled templates stay at version 1.5. Action.Execute is outside every bundled profile. The safe action subset is Action.Submit and HTTPS Action.OpenUrl.
All bundled profiles require schema 1.5 or later, up to the maximum listed
above, because the package requires TextBlock heading style. Cards using 1.3
or 1.4 are outside this package’s policy even if a host supports them.
Product facts and sources
Microsoft documents that Copilot Studio supports Adaptive Cards schema 1.6 and earlier, with Teams and the Omnichannel live chat widget limited to 1.5. Bot Framework Web Chat supports 1.6 but not Action.Execute. Version 1.6 cards render in test chat rather than on the authoring canvas. See Adaptive Cards overview.
Interactive cards belong in an Ask with Adaptive Card node and require at least one submit button. Copilot Studio creates output variables from card inputs, and Microsoft recommends unique submit data when multiple cards can remain active. See Ask with Adaptive Cards.
Informational cards belong in a Message or Question node. See Send a message.
Dynamic values can be authored with Power Fx in the card node. Power Fx variable references use scope prefixes such as Topic., Global., and System.. See Create expressions using Power Fx.
For accessibility, Microsoft recommends input label properties, isRequired and errorMessage, logical JSON order, descriptive action titles, heading styles, and channel testing with screen readers. See Accessibility tips for Adaptive Cards and Input validation.
Good to know
- Validation proves only that a card satisfies this package’s bounded policy. It does not prove channel rendering.
- Test the final card in the Copilot Studio test chat and every intended published channel.
- Keep cards concise. Prefer a single-column layout for forms and mobile use.
- Cards collect and present data. They do not authorize a user or enforce a business transaction.
- Validate permissions and business rules again in the downstream topic, flow, connector, or API.
- Before branching, match the exact expected
cardIdandactionSubmitIdfor the currently awaited card/version from trusted conversation state.actionIdalone cannot distinguish stale or cross-card submissions. - Keep input IDs distinct from every top-level
datakey on submit actions that collect inputs. Submitted input values can overwrite action metadata with the same key. - Secret-collection checks inspect input IDs, labels, placeholders, error messages, and toggle titles, not only the field name.
- Secret phrases are detected anywhere in input text, including metadata labels such as
apiKeyLabelandprivateKeyLabel; there are no metadata-suffix exemptions. The bundledreferences/host-profiles-and-contracts.mddocuments the strict rule, its sole non-credential phrase exception, and how to request a reviewed change. - The approval template keeps its review comment optional so Approve is not blocked. Downstream topic logic must require a nonblank trimmed comment for Reject or Request changes, and reprompt without recording the decision when it is blank.
- External images are excluded from the bundled profile by default.
- Never use card data as a place to hide credentials or authorization decisions.
