[Copilot Studio] Tried Displaying KPIs as Graphs in Chat: Two Routes Using Adaptive Cards and Code Interpreter

[Copilot Studio] Tried Displaying KPIs as Graphs in Chat: Two Routes Using Adaptive Cards and Code Interpreter

I will introduce two methods for displaying KPI graphs within Copilot Studio chat, based on hands-on verification. I have summarized the characteristics and appropriate use cases of Adaptive Cards, which do not require premium features, and the Code Interpreter, which offers greater flexibility.
2026.06.22

This page has been translated by machine translation. View original

Introduction

Hello, I'm Keema.

When creating KPI reports, there is often a request to show not only numerical tables but also bar charts and line graphs.
There are mainly two ways to display charts in a chat using Copilot Studio.

This article covers two routes for displaying KPI charts in a chat, with hands-on verification conducted as of June 2026.
One method uses the chart elements of Adaptive Cards, and the other generates images using Python/matplotlib via the code interpreter.
I hope this serves as a reference for those who want to show charts within a chat.

This article is the 7th installment in a series on building agents with Copilot Studio.
The series as a whole aims to create an agent that handles "collection → aggregation → charting → insights → documentation" end-to-end, and this article covers the "charting" part.

Target audience: Those who want to display KPI charts in a chat using Copilot Studio

Series Article List

# Theme Article
Part 1 First Agent Creating Your First Agent
Part 2 Knowledge Trying File-Based Answers with Knowledge
Part 3 Topics, Tools, Flows Building "Actions" with Topics, Tools, and Agent Flows
Part 4 Templates, Autonomous Triggers, Multi-Agent Expanding the Configuration with Templates, Autonomous Triggers, and Multi-Agent
Part 5 Collection (How to Pass Data) Comparing Methods for Providing KPI Data to an Agent for Aggregation
Part 6 Aggregation Performing KPI Aggregation Deterministically Without Relying on LLMs
Part 7 Charting (This article)

1. What We'll Do This Time

We will try two routes for displaying charts in a chat.

  • Route A: Display a bar chart using Adaptive Cards chart elements (Chart.VerticalBar)
  • Route B: Generate a bar chart image using the code interpreter (Python/matplotlib)
  • Organize how to choose between the two routes and the constraints of the display destination (channel)

For verification, we use the ARR (fictional values) of the same three fictional SaaS companies (CloudNova / StreamForge / Datapeak) as in previous installments.

2. Two Routes for Displaying Charts

There are two main options for displaying charts in a chat with Copilot Studio.

Aspect Route A: Adaptive Card Chart Elements Route B: Code Interpreter
Mechanism The host renders the card's Chart.* elements Generates an image with Python/matplotlib
Cost Does not use premium features Premium (consumes Copilot Credits)
Flexibility Limited to chart types provided by the card Free to use Python (axes, colors, annotations, etc.)
Output Card (rendered within the chat) PNG image (displayed in chat / downloadable)
Setup effort Write a JSON card payload and embed it in the topic's message node Just ask in natural language. CI auto-generates and runs the Python code
Channel constraints Depends on the host's supported card version Not displayed in Teams or Microsoft 365 Copilot channels

Route A has the advantage of being usable without premium features, but requires the effort of handwriting a JSON card payload and embedding it in a topic.
Route B requires a premium subscription, but since you simply ask "turn this into a chart" and CI generates and runs the Python code, the actual operation is intuitive.

Let's start with Route A, which does not use premium features.

3. Route A: Displaying with Adaptive Card Chart Elements

3.1 Preparing the Bar Chart Card

We prepare an Adaptive Card JSON to display the ARR of three companies in a vertical bar chart.
For Chart.VerticalBar's data, pass an array of { "x": label, "y": value }.
A fallback with a FactSet (tabular format) is included so that information is preserved even on hosts that don't support chart elements.
Here, the ARR for fiscal year 2025 Q2 is written directly as sample data to demonstrate how the card works.

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.6",
  "body": [
    {
      "type": "TextBlock",
      "text": "ARR Comparison for 3 SaaS Companies (2025 Q2, in millions JPY)",
      "weight": "Bolder",
      "size": "Medium",
      "wrap": true
    },
    {
      "type": "Chart.VerticalBar",
      "title": "ARR (millions JPY)",
      "xAxisTitle": "Company",
      "yAxisTitle": "ARR (millions JPY)",
      "colorSet": "categorical",
      "data": [
        { "x": "CloudNova", "y": 1800 },
        { "x": "StreamForge", "y": 1150 },
        { "x": "Datapeak", "y": 2600 }
      ],
      "fallback": {
        "type": "FactSet",
        "facts": [
          { "title": "CloudNova", "value": "ARR 1,800 million JPY" },
          { "title": "StreamForge", "value": "ARR 1,150 million JPY" },
          { "title": "Datapeak", "value": "ARR 2,600 million JPY" }
        ]
      }
    }
  ]
}

Adaptive Cards chart elements include vertical bar, horizontal bar, line, pie, donut, and more.

Teams supports the following types of charts:

  • Donut chart
  • Gauge chart
  • Grouped vertical bar chart
  • Horizontal bar chart
  • Line chart
  • Pie chart
  • Stacked horizontal bar chart
  • Vertical bar chart

Source: Charts in Adaptive Cards | Microsoft Learn

3.2 Adding the Card to the Topic's Message Node

Cards that only display information (those that do not receive user input) are placed in a message node.

  1. From the agent's "Topics", create an empty topic via "Add a topic" → "From blank"
  2. In the trigger description, write when this topic should be used (e.g., when you want to show the ARR of 3 companies as a bar chart)
  3. Add a message node via "Add a node" → "Send a message"
  4. In the message node toolbar, select "Add" → "Adaptive Card"
  5. Open the designer via "Edit Adaptive Card", and paste the above JSON into the card payload editor

If a bar chart appears in the designer's preview, the card is valid.

Adaptive Card designer. The preview shows a bar chart of ARR for 3 companies, and Chart.VerticalBar is recognized in the card structure
Adaptive Card designer. A bar chart is rendered in the preview (upper left), and Chart.VerticalBar appears in the card structure

Save the JSON, close the designer, and save the topic.

3.3 Verifying Operation in the Test Chat

In the test chat, send an utterance matching the trigger description (e.g., "Show me the ARR of CloudNova / StreamForge / Datapeak as a bar chart").
The card from the message node was returned, and the bar chart was actually rendered.

The test chat showing a bar chart of ARR for 3 companies rendered
Chart.VerticalBar was rendered in the test chat. The X-axis shows companies (CloudNova / StreamForge / Datapeak), the Y-axis shows ARR (millions JPY), and bars for the 3 companies are displayed

With generative orchestration turned on, in addition to displaying the card, the agent sometimes added a text summary with rankings or comments of its own.
The chart (card) and insights (text) appeared together in the same response.

In this verification, the following text was returned following the chart attachment.

Here is the ARR comparison bar chart for 2025 Q2. The figures are summarized below.

Company ARR
1st Datapeak 2,600 million JPY
2nd CloudNova 1,800 million JPY
3rd StreamForge 1,150 million JPY

Key Points

  • Datapeak is at the top, accounting for approximately 47% of the combined total for the 3 companies (5,550 million JPY).
  • CloudNova is in the middle, with an 800 million JPY gap from Datapeak.
  • StreamForge is the smallest, at approximately 44% of Datapeak's level.

Comparing NRR (net revenue retention) and operating profit margin alongside ARR would make differences in growth efficiency and profitability even clearer. Feel free to request comparisons of other KPIs or report creation!

The Adaptive Card itself was rendered in the test chat without using premium tools like the code interpreter.

3.4 Note: Channels That Can Render Chart Elements Are Limited

The chart was rendered in the test chat in this verification.
The Adaptive Card JSON specifies a schema version such as "version": "1.6".
This is not the Copilot Studio version, but the Adaptive Cards specification version itself (the value of "version" written near the beginning of the JSON we created).
Chart elements (such as Chart.VerticalBar) are features added in version 1.6, and they will not be rendered if the destination channel (host) does not support that version.

Copilot Studio supports the Adaptive Cards schema versions 1.6 and earlier. However, the appropriate schema version depends on the targeted host app:

  1. The Bot Framework Web Chat component (that is, the default website integration pattern) supports version 1.6 but doesn't support Action.Execute
  2. The live chat widget (used for Omnichannel for Customer Service) is limited to version 1.5
  3. Teams is also limited to version 1.5

In addition, Copilot Studio only renders version-1.6 cards in the test chat, not on the canvas.

Source: Using Adaptive Cards in Copilot Studio | Microsoft Learn

Since Teams and live chat only support up to version 1.5, chart elements like Chart.VerticalBar will not be rendered.
If you plan to use this in a published channel, be sure to verify that it actually renders in the target channel (this article only confirms behavior in the test chat).

4. Route B: Generating a Chart Image with the Code Interpreter

Route A can render charts without premium features, but the output is limited to the chart types provided by the card.
If you need full freedom over axis formatting and annotations, or if you want to paste the generated image into a document, the code interpreter is the better choice.

4.1 Turning Aggregated Values into a Bar Chart

Route B uses the code interpreter. This is a premium feature that consumes Copilot Credits.
In the agent's "Settings" → "Generative AI", turn on "Code interpreter" under "File processing capabilities".

In the test chat, ask to turn the aggregated ARR averages for the three companies into a bar chart. The first prompt sent was as follows.

Please generate a bar chart comparing the 2025 ARR averages for the 3 companies (CloudNova 1950, StreamForge 1300, Datapeak 2810) as a PNG image using matplotlib. Add value labels to each bar, set the Y-axis to "ARR (millions JPY)", and use different colors for each company.

The code interpreter generated a bar chart PNG with matplotlib, but the Y-axis label ("ARR (millions JPY)") was garbled.
The flow from sending the request message, to code execution, to the returned image is displayed sequentially within the chat.

The test chat showing a request message sent, the code interpreter generating a bar chart PNG image, and the response returned
The utterance, code execution, and bar chart image were displayed as a sequence in the chat. The Y-axis label is garbled

So we tried adding plt.rcParams['font.family'] = 'Yu Gothic' at the beginning of the prompt.

Please generate a bar chart comparing the 2025 ARR averages for the 3 companies (CloudNova 1950, StreamForge 1300, Datapeak 2810) using matplotlib. Set the Y-axis to "ARR (millions JPY)", use different colors for each company, and add value labels to each bar. Please include plt.rcParams['font.family'] = 'Yu Gothic' at the beginning.

This time, the Y-axis label was correctly displayed in Japanese.

Bar chart with the Y-axis label correctly displayed in Japanese
After specifying plt.rcParams['font.family'] = 'Yu Gothic'. The Y-axis label "ARR (millions JPY)" is displayed correctly

The bar values (1,950 / 1,300 / 2,810) are the 2025 ARR averages that the code interpreter aggregated previously.
Following the aggregation, you can proceed directly to charting within the same code interpreter session.

4.2 Note: Images Generated by the Code Interpreter Are Not Displayed in Some Channels

Images generated by the code interpreter are not rendered in the Teams and Microsoft 365 Copilot channels.

Images created with code interpreter are not rendered in the Teams and Microsoft 365 Copilot channel

Source: FAQ for code interpreter | Microsoft Learn

Both Route A (Adaptive Card) and Route B (code interpreter-generated images) were displayable in the test chat in my environment, but display is restricted in some channels such as Teams.
Whether the output actually displays in the target channel must be verified before publishing.

5. How to Choose Between the Two Routes

After running both hands-on, the choice can be summarized as follows.

  • If you want to avoid premium charges, use Route A (Adaptive Card). It can render charts without premium tools like the code interpreter. However, there is the overhead of writing a JSON card payload and embedding it in a topic, and chart types are limited to those provided by the card.
  • If you prioritize flexibility in presentation, or want to paste the generated image into a document, use Route B (code interpreter). Premium charges (Copilot Credits) are required, but since you simply ask in natural language and CI generates and runs the Python code, the operational overhead is minimal. You have full freedom over axes, colors, and annotations.

For charts to be placed in the final deliverable documents (PowerPoint / Excel), there is also a method of embedding editable charts directly into the document rather than pasting images.
This will be covered in a future installment.

6. Summary

There are two ways to display KPI charts in a chat: Adaptive Card, which does not use premium features, and the code interpreter, which offers greater flexibility.
If you want to avoid premium charges, use Adaptive Card (though it requires handwriting JSON and some setup effort). If premium charges are acceptable and you prioritize intuitive operation, flexibility in presentation, and image reusability, use the code interpreter.

Both methods rendered in the test chat, but display is restricted in some channels such as Teams.
It is advisable to choose based on your purpose—whether it is a quick in-chat display or a chart to be embedded in a document—while also accounting for the constraints of the target channel.

References

Share this article