Skip to main content

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:

  • validation via regex
  • errorMessage on invalid input
  • isRequired to enforce completion

Summary

TagPurposeDescription
%display_outRender event output as a cardFormats skill results using an Adaptive Card template
%formCollect user input via a cardGathers user-provided parameters to trigger skill logic

For more examples and working code, visit:
otonoma/getting-started/examples/adaptive-cards