Adaptive Cards
What’s an Adaptive Card?
"Adaptive Cards are platform-agnostic snippets of UI, authored in JSON, that apps and services can openly exchange. When delivered to a specific app, the JSON is transformed into native UI that automatically adapts to its surroundings." — Microsoft
They help design and integrate light-weight UI for all major platforms and frameworks.
🔗 To learn more: https://adaptivecards.io
Adaptive Cards in Paracord
Within Paracord, Adaptive Cards are used to display structured messages and capture user input visually and interactively. Cards can include:
- Static or dynamic text
- Images
- Input fields (text, dropdowns, etc.)
- Buttons and actions
You’ll find Adaptive Cards rendered:
- In the Actor hub, as part of request skill / message content.
🔎 You can explore a working example here:
otonoma/getting-started/examples/adaptive-cards
display_out: Rendering Output with Adaptive Cards
Use the %display_out tag in your skill definition to render the output of a skill as an Adaptive Card. This allows users to view rich, formatted results from the event logic.
Example: Displaying a Random Value with Card Layout
%skill(subject=random_numberA, action=getA)
%display_out({
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.6",
"body": [
{
"type": "TextBlock",
"size": "medium",
"weight": "bolder",
"text": "${title}",
"style": "heading",
"wrap": true
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"style": "person",
"url": "${profileImage}",
"altText": "${companyName}",
"size": "small"
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"weight": "bolder",
"text": "${companyName}",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "none",
"text": "Created {{DATE(${string(createdUtc)}, SHORT)}}",
"isSubtle": true,
"wrap": true
}
]
}
]
},
{
"type": "TextBlock",
"text": "Random Value: ${value}"
}
]
})
event randomNumberA($conversation string) {
return {
value: Uuid(),
title: "Title here",
profileImage: "https://media.licdn.com/dms/image/D560BAQHuynegxP44Vw/company-logo_200_200/0/1716399649505/grokitdata_logo?e=1729123200&v=beta&t=NApIy-W7us7jQGOx5sDQho2xVpTRR7-yHKEHTZSpZRw",
companyName: "Grokit",
createdUtc: "2017-02-14T06:08:39Z"
};
}
The ${...} syntax allows referencing fields from the returned object in the card template.
form: Receiving Input with Adaptive Cards
To make Adaptive Cards interactive, you can use the %form tag inside a skill. This enables user input (e.g., text fields, dropdowns), which is then passed to the skill as parameters.
Example: Capturing User Information via Form
%skill(subject=input_card, action=input)
%form({
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": 2,
"items": [
{
"type": "Container",
"$data": "${properties}",
"items": [
{
"type": "Input.Text",
"label": "${label}",
"id": "${id}",
"regex": "${validation}",
"errorMessage": "${error}",
"isRequired": true
}
]
}
]
},
{
"type": "Column",
"width": 1,
"items": [
{
"type": "Image",
"url": "${thumbnailUrl}",
"altText": "${thumbnailAlt}",
"size": "auto"
}
]
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
})
event inputCard($conversation string) {
let $s = JsonString({
properties: [
{
id: "myName",
label: "Your name (Last, First)",
validation: "^[A-Z][a-z]+, [A-Z][a-z]+$",
error: "Please enter your name in the specified format"
},
{
id: "myEmail",
label: "Your email",
validation: "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+[.][A-Za-z0-9-]{2,4}$",
error: "Please enter a valid email address"
},
{
id: "myTel",
label: "Phone Number (xxx-xxx-xxxx)",
validation: "^[0-9]{3}-[0-9]{3}-[0-9]{4}$",
error: "Invalid phone number. Use the specified format"
}
]
});
return JsonParse($s);
}
Each field in the form supports:
validationvia regexerrorMessageon invalid inputisRequiredto enforce completion
Summary
| Tag | Purpose | Description |
|---|---|---|
%display_out | Render event output as a card | Formats skill results using an Adaptive Card template |
%form | Collect user input via a card | Gathers user-provided parameters to trigger skill logic |
For more examples and working code, visit:
otonoma/getting-started/examples/adaptive-cards