Harnessing Power FX to Enhance Adaptive Cards in Power Virtual Agents

Brendon Colburn
3 min readJun 5, 2023

--

Introduction

Power Virtual Agents (PVA) provides an intuitive, no-code interface for building chatbots. One of its features, Adaptive Cards, allows you to present rich, interactive content within your bot conversations. But what happens when you run into a roadblock that the existing documentation doesn’t cover? This was the challenge my colleague Paul and I faced while trying to iterate through dynamic content using the new Adaptive Cards experience in PVA.

The Challenge

The issue was with handling dynamic content in Adaptive Cards. The existing documentation provides examples of using static content, but it didn’t guide us on how to work with dynamic content. In the provided examples, the content of the card (like text in a TextBlock) was hardcoded. However, in our use case, we needed to fetch and display dynamic data based on the user’s conversation with the bot.

Here’s the JSON of a typical Adaptive Card as provided in the documentation:

{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"text": "Tell us about yourself",
"weight": "Bolder",
"size": "Medium",
"wrap": true,
"style": "heading"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
]
}

This example uses static content. The text in the “TextBlock” is fixed, and it doesn’t change based on the bot’s conversation with the user.

The Troubleshooting

To handle dynamic content, we had to use variables in place of hardcoded text. The documentation provided examples of using Power Fx, a low-code programming language, to handle variables. Here’s an example of using Power Fx with Adaptive Cards:

{
'$schema': "http://adaptivecards.io/schemas/adaptive-card.json",
type: "AdaptiveCard",
version: "1.5",
body: [
{
type: "TextBlock",
text: Topic.Title,
weight: "Bolder",
size: "Medium",
wrap: true,
style: "heading"
}
],
actions: [
{
type: "Action.Submit",
title: "Submit"
}
]
}

In this example, instead of hardcoded text, we used Topic.Title to dynamically fetch the title of the topic in the conversation.

But we were still faced with a challenge when we needed to iterate over an array of data and display it in the form of a FactSet. The earlier way of doing this didn’t seem to work any longer:

{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.3",
"body": [
{
"type": "TextBlock",
"text": "${description}",
"size": "Medium",
"weight": "Bolder",
"wrap": true,
"separator": true
},
{
"type": "FactSet",
"facts": [
{
"$data": "${imagetags}",
"title": "${id}",
"

"value": "${tag}"
}
],
"separator": true,
"$data": "${$root['imagetags[0]']}",
"id": "id"
}
]
}

The Solution

After several rounds of trial and error, we came up with a solution. The key was to leverage the power of Power Fx to handle the iteration. Here’s the JSON of the Adaptive Card that we ended up with:

{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.3",
"body": [
{
"type": "TextBlock",
"text": Topic.ResultObject.description, // "Note that you always need to specify Topic as the root object"
"size": "Medium",
"weight": "Bolder",
"wrap": true,
"separator": true
},
{
"type": "FactSet",
"facts":
ForAll(Topic.ResultObject.imagetags, // So this is what was different, we used Power FX to return the facts for the factset
{
"title": ThisRecord.id,
"value": ThisRecord.tag
}),
"separator": true,
"id": "id"
}
]
}

In this version, we used the ForAll function from PowerFx to iterate over imagetags and create a set of facts. For each item in imagetags, ThisRecord.id and ThisRecord.tag fetched the id and tag respectively.

Conclusion

Our journey of troubleshooting this issue was a testament to the flexibility and power of Power Virtual Agents and PowerFx. Even when the existing documentation didn’t cover our specific use case, we were able to find a solution by leveraging the capabilities of the tools at our disposal. I hope that sharing our experience can help others who might be facing similar challenges.

In the ever-evolving world of technology, sometimes you have to create your own path. This experience reminded us that when you’re armed with a powerful toolset and a mindset for problem-solving, you can find your way through any challenge.

--

--

Responses (1)