Here goes a quick hack to make your Copilot to interact with D365F&O client. For example: if you want to navigate to a form (customers, vendors) or show the top customers of a legal entity in a form, by directly asking Copilot.
Wondering how? Here are the steps.
Uh, oh, before that, here are the pre-requirements:
Pre-requirements
Following are the checkpoints you must consider, before proceeding:- You must have a unified developer environment. The development of AI plugins that use finance and operations business logic is available only in the unified developer experience. For information about how to create a unified developer environment from the unified admin experience for finance and operations apps, see Tutorial: Install the Finance and Operations Provisioning App. You can refer to my video blog that explains how to spin up an UAD instance from the scratch:
- You should be having your environment on version 10.0.40 proactive quality update 1 (PQU-1) with platform version 7.0.7279.80 or later.
- The following solutions must be installed in the Power Platform environment. If they aren't already installed, see Manage Dynamics 365 apps for information about how to install Dynamics 365 solution packages in Dataverse.
- The Copilot for finance and operations package, which includes the following solutions:
- Copilot for finance and operations apps
- Copilot for finance and operations generation solution
- Copilot for finance and operations anchor solution
- Finance and Operations Virtual Entity
Step 1: define classes for client operations
Begin by defining class to respond to Client events, by decorating the class with a signature SysCopilotChatGlobalAction:[DataContract]
[SysCopilotChatGlobalAction]
[SysCopilotChatActionDefinition(
identifierStr(MS.PA.CustTableNavigate.ClientNavigate),
'The menu item to navigate',
'Navigates to or opens a pre defined/destined form/menu item in the application client',
menuItemActionStr(SubhaNavigateCustTableForm), MenuItemType::Action)]
Let me explain, each.
- SysCopilotChatActionDefinition à Is what is needed to make this class respond to user inputs on Copilot side cars.
- SysCopilotChatActionDefinition à give a name to your navigation action, which is encapsulated within identifierStr(). Remember that the name must begin with MS.PA. in my case I have given a name like: MS.PA.CustTableNavigate.ClientNavigate.
- The next parameter is the prompt that, you would need, would show up while you trigger the Copilot chat.
- The next one is the description that shows up while you are interacting with the chat-car
- Last one indicates the Action menu item (created later), that is basically pointing to this Class.
[DataContract]
[SysCopilotChatGlobalAction]
[SysCopilotChatActionDefinition(
identifierStr(MS.PA.CustTableNavigate.ClientNavigate),
'The menu item to navigate',
'Navigates to or opens a pre defined/destined form/menu item in the application client',
menuItemActionStr(SubhaNavigateCustTableForm), MenuItemType::Action)]
internal final class SubhaNavigateCustTableForm extends SysCopilotChatAction
{
}
Step 2: define getter-setter methods for the user inputs
We are now going to create user inputs for the menu item to open and (optionally) if you want to show any response to other back:MenuItemName menuItemName;
str clientNavigationResponse;
[DataMember('menuItemName'),
SysCopilotChatActionInputParameter('The name of the menu for the form to launch', true)]
internal MenuItemName parmMenuItemName(MenuItemName _menuItemName = menuItemName)
{
menuItemName = _menuItemName;
return menuItemName;
}
[DataMember('clientNavigationResponse'),
SysCopilotChatActionOutputParameter('The response from the navigation, whether an error or successful navigation')]
public str parmclientNavigationResponse(str _clientNavigationResponse = clientNavigationResponse)
{
clientNavigationResponse = _clientNavigationResponse;
return clientNavigationResponse;
}
Please note the signatures of the methods.
Step 3: execute the class
To execute the class, one must extend the class SysCopilotChatActionDefinitionAttribute and then executing, using the context of the execution (like dataarea Id, etc):public void executeAction(SysCopilotChatActionDefinitionAttribute _actionDefinition, Object _context)
{
super(_actionDefinition, _context);
if (this.parmMenuItemName())
{
// Navigate to user provided destination page/form
MenuFunction::runClient(this.parmMenuItemName(), MenuItemType::Display, false, new Args());
this.parmclientNavigationResponse("Navigated to " + menuItemName + " list page.");
}
else
{
throw Error(Error::wrongUseOfFunction(funcName()));
this.parmclientNavigationResponse("There was an error navigating you to the " + menuItemName + " form. See the action menu for more information.");
}
}
Here it’s just accepting user keyed in navigation Menu item/form name and then navigating using “parmclientNavigationResponse(<name of the form>)”.
Save your class, and create an action menu item. Assign proper security and privileges to conclude the development. Build the Project area. Deploy your changes to your Online environment:
Step 4: create the topic in Copilot Studio
In Copilot Studio, let us create the Topic for client navigation mechanism which we just created:In response to which, I have created some quick replies like this:
Keep adding whichever forms you want to add here. And based on this, you need to add every form in your Copilot Studio, as a new Topic. Example for Customer navigation:
And then add an activity here:
That defines the client activity you have added in X++:
In the Value, we are passing the name of the form which we want to open.
Likewise, we are also creating the navigation for Vendor form:
Excepting that the value is = “VendTableListPage” now.
Repeat this for all the Menu Items you’ve created.
Further reads and exercises
We can create inputs from users to make users give some filtration data (ex: using top 10 customers/top 20 vendors) and for that you need to implement icustomAPI class:implements ICustomAPI
And then you can declaring your variables and create Custom API, requests parameters and AI operations based on that (vide my earlier blog: https://community.dynamics.com/blogs/post/?postid=bba91c98-6940-f011-b4cb-7c1e52199c3e) and then use them in conjunction with Copilot for deeper insights.
*This post is locked for comments