How to capture user questions asked to Copilot in Dynamics 365 CRM using Power Automate

As Microsoft’s Copilot becomes an integral part of the Dynamics 365 CRM ecosystem, understanding how users interact with it has become essential for businesses aiming to enhance their digital customer experience. Recently, a client approached us with a unique requirement – they wanted to capture the user details like username, Business Unit, Timestamp, and the exact question they typed when interacting with Copilot within their D365 CRM environment.

In this blog, we’ll walk you through how I approached this scenario and built a Power Automate flow with an Action & Plugin that captures these interactions effectively.

Step 1: Create or Open Your Solution

Begin by creating a solution in Power Apps, or open the solution you created earlier organized and easy to manage within the Dynamics 365 environment.

Step 2: Create an Automated Cloud Flow

  • Navigate to New > Automation > Cloud flow > Automated

Copilot in Dynamics 365 CRM using Power Automate

Step 3: Configure Trigger

  • Flow name: Copilot Interaction
  • Choose the trigger: When a row is added, modified, or deleted (Microsoft Dataverse).
  • Click Create

Copilot in Dynamics 365 CRM using Power Automate

Step 4: Trigger and Initialize

I used the “Copilot Interaction” table to trigger the flow and then fetched the related transcript data using the dataid.

1. Trigger:

  • Action: When a row is added
  • Table: Copilot Interactions
  • Scope: Organization

2. Initialize Variable: (Store the Question Ask By User)

  • Name: Questions
  • Type: Array
  • Value: [] (empty array)

Copilot in Dynamics 365 CRM using Power Automate

Step 5: Parse Interaction Context and Validate

After capturing the interaction, we parse the msdyn_interactioncontext using a Compose action to access the full JSON object. From this, we extract the Transcript.DataId to use later for fetching the related transcript.

Then, we use a Condition block to validate whether the interaction context is valid and contains data.

Expressions used:

1. To check if the interaction context is not empty:

outputs(‘Interaction_Context’) is not equal to json(‘{}’)

2. To extract the Transcript.DataId from the interaction context:

outputs(‘Interaction_Context’)?[‘Transcript’]?[‘DataId’]

These expressions make sure the context is valid and allow us to move forward only if the DataId exists, preventing flow failures or unnecessary steps.

Copilot in Dynamics 365 CRM using Power Automate

Step 6: Get User Details from Transcript Record

Once we have the Transcript.DataId, we use the Get a row by ID – Copilot Transcript Datas action to retrieve detailed information about the interaction from the Dataverse table.

Then, we extract and format the following fields using Compose actions:

1. Created By (User Name)
To get the formatted user name who initiated the Copilot interaction:

outputs(‘Get_a_row_by_ID_-_Copilot_Transcript_Datas’)?[‘body/_createdby_value@OData.Community.Display.V1.FormattedValue’]

2. Business Unit
To determine which business unit the user belongs to:

outputs(‘Get_a_row_by_ID_-_Copilot_Transcript_Datas’)?[‘body/_owningbusinessunit_value@OData.Community.Display.V1.FormattedValue’]

3. Timestamp (Last Modified)
This gives us the last modified time of the interaction record, representing the time of the chat:

outputs(‘Get_a_row_by_ID_-_Copilot_Transcript_Datas’)?[‘body/modifiedon@OData.Community.Display.V1.FormattedValue’]

These expressions help extract clean, readable values for display or reporting purposes

Copilot in Dynamics 365 CRM using Power Automate

Step 7: Decode and Convert Transcript Data to JSON

Once we have the Transcript Data (which is stored in Base64 UTF-16LE format), we need to decode it properly to extract readable JSON data.

 Steps:

1. Download a Transcript Data File

  • Use the action: Download a file or an image
  • Table Name: Copilot Transcript Datas
  • Row ID:outputs(‘DataId’)
  • Column Name: Transcript Data
    This downloads the actual transcript as a file in Base64 encoded format.

2. Convert to Base64 String

  • Add a Compose action:
    • base64(body(‘Download_a_Transcript_Data_File’))
  • This converts the binary file content into a base64 string (still in UTF-16LE format).

3. Why decoding directly doesn’t work
The data is in UTF-16 Little Endian (UTF-16LE) format. Standard base64ToString() or decodeUriComponent() methods don’t work properly here.
➤So we need to use a Dataverse plugin to handle the decoding correctly.

4. Perform Unbound Action (Call Action & Plugin)

  • Action: cop_ConvertBase64UTF16ToUTF8
  • Input:outputs(‘base64string’)
  • This plugin safely converts your Base64 UTF-16LE string into UTF-8 readable format.

Copilot in Dynamics 365 CRM using Power Automate

Copilot in Dynamics 365 CRM using Power Automate

Copilot in Dynamics 365 CRM using Power Automate

5. Develop a Plugin

    1. Code:
using System;
using Microsoft.Xrm.Sdk;

using System.Text;

 

namespace DecodeBase64String

{

public class DecodeBase64 : IPlugin

{

public void Execute(IServiceProvider serviceProvider)

{

// Declare variables outside the try block

IPluginExecutionContext context = null;

IOrganizationServiceFactory serviceFactory = null;

IOrganizationService service = null;

ITracingService tracingService = null;

 

string inputParameterName = "Base64Input";

string outputParameterName = "ConvertedUTF8";

string base64String = string.Empty;

byte[] utf16Bytes = null;

byte[] utf8Bytes = null;

string utf8String = string.Empty;

Encoding utf16Encoding = Encoding.Unicode; // UTF-16LE

Encoding utf8Encoding = Encoding.UTF8;


try

{

// Get services

context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

service = serviceFactory.CreateOrganizationService(context.UserId);

tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


// Check input parameter

if (!context.InputParameters.ContainsKey(inputParameterName) || context.InputParameters[inputParameterName] == null)

{

throw new InvalidPluginExecutionException($"Input parameter '{inputParameterName}' not found or is null.");

}
 

// Get Base64 string

base64String = context.InputParameters[inputParameterName] as string;
 

if (string.IsNullOrEmpty(base64String))

{

tracingService.Trace("Base64 string is empty.");

context.OutputParameters[outputParameterName] = string.Empty;

return;

}

tracingService.Trace($"Base64 String: {base64String}");

// Decode from Base64 to UTF-16LE bytes

utf16Bytes = Convert.FromBase64String(base64String);

// Convert UTF-16LE bytes to UTF-8 bytes

utf8Bytes = Encoding.Convert(utf16Encoding, utf8Encoding, utf16Bytes); 

// Convert bytes to UTF-8 string

utf8String = utf8Encoding.GetString(utf8Bytes);

tracingService.Trace($"UTF-8 String: {utf8String}");

// Set output

context.OutputParameters[outputParameterName] = utf8String;

tracingService.Trace($"Output parameter '{outputParameterName}' set with UTF-8 string.");

}

catch (Exception ex)

{

if (tracingService != null)

{

tracingService.Trace($"Error: {ex.Message}");

}
 
throw new InvalidPluginExecutionException($"An error occurred in DecodeBase64 plugin: {ex.Message}", ex);

}

}

}

}

 

  1. Parse into JSON

1. Add another Compose action:

json(outputs(‘Perform_an_unbound_action’)?[‘body/DecodedData’])

2. Now your data is clean, structured, and ready to be used as JSON in your Power Automate flow.

Copilot in Dynamics 365 CRM using Power Automate

Note:
You could use third-party websites available online, but most are either paid or less secure. This plugin-based method is 100% free, secure, and directly integrated with Dataverse

Understanding the Data Flow

Each interaction with Copilot is stored in the Copilot Transcript Datas table.

  • It contains a Transcript Data column (file type).
  • This file holds the full JSON (questions, other info, etc.).
  • If the user refreshes the chat window, a new record is created.
  • If the user stays in the same session, questions keep appending to the same record.

Step 8: Parse the JSON to Extract User Messages

After decoding the base64 content, we now parse the JSON structure to access individual messages.

Action: Parse JSON

  • Content:
    outputs(‘Convert_DecodedData_into_Json’)
  • Schema:
{

"type": "object",

"properties": {

"messages": {

"type": "array",

"items": {

"type": "object",

"properties": {

"user": {

"type": "string"

},

"message": {

"type": "string"

}

},

"required": ["user", "message"]

}

}

}

}

Apply to Each: Loop Through Messages

  • Input:
    body(‘Parse_JSON’)?[‘messages’]

This iterates over every message within the parsed JSON array.

Condition: Check if the Message Was Typed by the User

  • Expression:
    items(‘Apply_to_each’)?[‘user’] is equal to → “user”

This ensures you’re only extracting the questions typed by the user (not by Copilot or bot).

Copilot in Dynamics 365 CRM using Power Automate

Step 9: Store and Display the User Questions

Once we’ve confirmed the message is from the user, we now want to store these questions and make them available for further processing or display.

 Append Question to Array Variable

  • Action: Append to array variable
  • Name: Questions
  • Value:
    message (this holds the actual question typed by the user)

Action: Compose (to get all questions as a single string)

This combines all user questions with line breaks:

join(variables(‘Questions’), decodeUriComponent(‘%0A’))

Action: Compose (to get the latest question and timestamp)

To show only the most recent question along with its timestamp:

last(variables(‘Questions’)) – @{outputs(‘Timestamp’)}

This is especially helpful if you’re showing real-time Q&A or logging the latest query.

Copilot in Dynamics 365 CRM using Power Automate

Step 10: Chat with Copilot ( To Check the Flow Output )

Ask your question in Copilot (e.g., “Can u give details of mobile heating issue?”).
Go to Power Automate → My Flows → Check the latest run to see the question with the timestamp in the output.

Copilot in Dynamics 365 CRM using Power Automate

Copilot in Dynamics 365 CRM using Power Automate

Conclusion

In this blog, we used Power Automate to build a flow that captures user questions via Copilot and stores them with a timestamp. We used actions like Compose to handle and display the data clearly. This setup helps automate data collection for further processing or integration with other systems.

The post How to capture user questions asked to Copilot in Dynamics 365 CRM using Power Automate first appeared on Microsoft Dynamics 365 CRM Tips and Tricks.

Original Post https://www.inogic.com/blog/2025/04/how-to-capture-user-questions-asked-to-copilot-in-dynamics-365-crm-using-power-automate/

Leave a reply

Join Us
  • X Network2.1K
  • LinkedIn3.8k
  • Bluesky0.5K
Support The Site
Events
April 2025
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30     
« Mar   May »
Follow
Sign In/Sign Up Sidebar Search
Popular Now
Loading

Signing-in 3 seconds...

Signing-up 3 seconds...