Create client plugins for Copilot in finance and operations apps

Client plugins, or client actions, are Microsoft Copilot plugins that invoke client code and are available for users in the context of client experiences for finance and operations apps. Developers can define plugins that convert the functionality, operations, and business logic of the X++ code base into actions that users can invoke and communicate with in natural language through the Copilot interface. For example, through client plugins, Copilot in finance and operations apps can be extended to let users enter natural language prompts in Copilot to perform application actions, fill in form values, or ask questions that require calculations and business logic from the application.

This article contains details about the components and options of client plugins. For a step-by-step tutorial that shows how to create a client plugin, see Tutorial: Create client plugins for Copilot in finance and operations apps.

Important

Architecture of client plugins

The development of client plugins has two key components:

  • The plugin must be created by using the Copilot in Finance and Operation chatbot in Copilot Studio. The plugin understands the user's natural language prompt, and the orchestration and execution of the plugin are managed based on the user's Copilot prompt. Upon execution, the plugin sends an event to the finance and operations client.
  • A method must be created in X++. This method is invoked by Copilot Studio and runs the defined client code. When Copilot Studio sends the event to finance and operations apps, the class is called, and the client operations are run.

For more information about the plugin architecture and execution, see Architecture of Copilot in finance and operations.

Defining the action in X++

In X++, you must create a class that's called and can run code when Copilot Studio invokes the method. The new class must be a subclass that extends the SysCopilotChatAction class.

Data contract

The method must be defined as a data contract. In this way, complex data types can be passed as input and output parameters of the method. As a result, serialization and deserialization of the parameters aren't required for communication with Copilot Studio. To define the method as a data contract, decorate it with the DataContract attribute. For more information about how to implement data contracts in X++, see Using Data Contracts in X++.

Provide the action definition

To define the action, decorate the class with the SysCopilotChatActionDefinition function.

Parameters

Parameter Type Description
IdentifierName string An identifier for the plugin action. It's the identifier that's defined for the event that's sent from Copilot Studio to finance and operations apps, and that returns output parameters from finance and operations apps to Copilot Studio. Use the identifierStr compile-time function to convert the identifier to a string.


The identifier name must begin with the prefix MS.PA

Name string A descriptive name for the action.
Description string A natural language description of the action. Although Copilot doesn't currently use this parameter, it should be provided in the definition. In a future release, this parameter will be used to enhance intelligent orchestration of plugins by linking the action to user intent.
MenuItemName string

The menu item that's associated with the action.

The permissions to this menu item determine the user permissions to invoke the client action. You can use an existing menu item, or you can create a new one to associate with the action.

MenuItemType securingMenuItemType The MenuItemType value for the menu item that's defined in the MenuItemName parameter.

Example

[SysCopilotChatActionDefinition(
    identifierStr(MS.PA.CopilotExample.ClientNavigate),
    'Navigate',
    'Navigates to or opens a defined form in the application client',
    menuItemActionStr(SysCopilotChatCustomNavigateAction), MenuItemType::Action)]

Define the action type

The action type is a mechanism for controlling the availability of the action to Copilot. It lets you define the context in which the action should be available for users to perform by using Copilot.

Global actions

Global actions have no specific application context and are available for users to perform in any form of the application, whenever the Copilot chat pane is open. To define a client action as global, decorate the method with the SysCopilotChatGlobalAction attribute.

Form actions

Form actions are applicable only in the context of a specific form. For example, the action might invoke a form action such as approving an invoice record or performing a calculation on data that's available in a specific form.

To define the form or forms where the action is available, decorate the method with one or more ExportMetadata attributes. The action is then considered in the Copilot plugin orchestration only if the user is in one of the forms that are defined for the action. If the user isn't in one of those forms, the orchestration ignores the action.

The following example defines the action as a form action that's available in the Batch and BatchGroup forms.

[ExportMetadata(formStr(BatchGroup), identifierStr(FormName))]
[ExportMetadata(formStr(Batch), identifierStr(FormName))]
[Export(identifierstr(Microsoft.Dynamics.AX.Application.SysCopilotChatAction))]

Runtime actions

Runtime actions are available wherever the developer defines them as available in code by adding them to a list of available actions.

To add a client action to the list of available actions, use SysCopilotChatAction::addToCopilotRuntimeActions.

Parameter Type Description
runtimeAction ClassName The class name of the runtime action to add to the list of runtime actions that are available to the user.
removeOnFormChange boolean If the value is true, the action is unregistered when the user goes to a different form. If it's false, the action remains registered.
context object (Optional) The context object instance to pass to the action when it runs.

To remove a runtime action from the list of actions that are available to Copilot for the user, use SysCopilotChatAction::removeFromCopilotRuntimeActions.

Parameter Type Description
runtimeAction ClassName The class name of the action to remove from the list of runtime actions that are available to Copilot for the user.

Define input parameters

Input and output parameters are used to pass values between the Copilot orchestration and the finance and operations client.

Input parameters that are defined for the action are received with the event payload that's sent from Copilot Studio to finance and operations apps to invoke the action. They're defined as data members of the data contract.

To define the properties of an input parameter, use the SysCopilotChatActionInputParameter function.

Parameter Type Description
description string A natural language description of the parameter. Although Copilot doesn't currently use this parameter, it should be provided in the definition. In a future release, this parameter will be used to enhance intelligent orchestration of plugins by linking the parameter to the user's natural language prompt.
isRequired boolean A value that determines whether a value must be defined for the parameter.

For each parameter, you must also define an accessor method to get and set the variables. The following example shows the definition of a menuItemName input parameter for a navigation action that has the client go to the form that's defined for this parameter.

[DataMember('menuItemName'),
SysCopilotChatActionInputParameter('The name of the menu for the form to launch', true)]
internal MenuItemName parmMenuItemName(MenuItemName _menuItemName = menuItemName)
{
    menuItemName = _menuItemName;
    return menuItemName;
}

Define output parameters

Output parameters that are defined for the action are sent with the event payload from finance and operations apps to Copilot Studio as a response. Like input parameters, output parameters are defined as data members of the data contract. For example, if your client action performs a calculation that's based on the form data, your output parameter can be the result of the calculation. That result can then be sent to Copilot as a response.

To define the properties of an output parameter, use the SysCopilotChatActionOutputParameter function.

Parameter Type Description
description string A natural language description of the parameter. Although Copilot doesn't currently use this parameter, it should be provided in the definition. In a future release, this parameter will be used to enhance intelligent orchestration of plugins by linking the parameter to the user's natural language prompt.

For each output parameter, you must define an accessor method. The following example shows the definition of a navResponse output parameter for a client action. This parameter is the action response that's sent back to Copilot and can be shown to the user in the chat session.

[DataMember('navResponse'),
SysCopilotChatActionOutputParameter('The response from the navigation, whether an error or successful navigation')]
public str parmNavResponse(str _navResponse = navResponse)
{
    navResponse = _navResponse;
    return navResponse;
}

Define the execution of the client action

To define business logic that should run for the action and set any output parameter values, create an instance of the SysCopilotChatActionDefinitionAttribute class. When you call executeAction, the output parameters are reserialized and returned to Copilot Studio in the event payload.

For example, if your Copilot action is used to go to a form in the client, you can use the following code to perform the navigation and define a message that's set as the output parameter that's sent to Copilot.

public void executeAction(SysCopilotChatActionDefinitionAttribute _actionDefinition, Object _context)
{
    super(_actionDefinition, _context);

    if (this.parmMenuItemName())
    {
        // Navigate
        MenuFunction::runClient(this.parmMenuItemName(), MenuItemType::Display, false, new Args());
        this.parmNavResponse("You were successfully navigated to the " + menuItemName + " form.");
    }
    else
    {
        throw Error(Error::wrongUseOfFunction(funcName()));
        this.parmNavResponse("There was an error navigating you to the " + menuItemName + " form. See the action menu for more information.");
    }
}

Creating topics in Copilot Studio

Invoke the client action

When the user enters a prompt in the Copilot chat pane with the intent to invoke a client action, the prompt is sent to Copilot Studio so that it can manage the orchestration and invocation of the action, based on the user intent. Copilot Studio determines which plugin to invoke for the prompt. For client actions, the plugin must define which X++ action should be invoked. Copilot Studio then sends an event to finance and operations apps to invoke the action. The event payload defines the values of the input parameters for the X++ class as a JavaScript Object Notation (JSON) object.

In your topic or plugin in Copilot Studio, create an Event activity node that defines the event to send to X++ and the event payload to include as input parameters for the client action. The value of the Name property of the event activity is the value of the IdentifierName parameter that's defined in the SysCopilotChatActionDefinition attribute of your X++ class. The value of the Value property of the event activity is a JSON string that defines the values for the input parameters that should be sent to the X++ class.

Receive output parameters of the client action

Your client action might have output parameters that you want to return either as a natural language response to the user in Copilot or to continue with another action. When the client action is run in X++, the output parameters are sent to Copilot Studio as an event.

In Copilot Studio, you must create a separate topic to receive the response from the X++ class. Create a topic that has an Event received trigger. The value of the Event name property of the trigger must be the value of the IdentifierName parameter that's defined in the SysCopilotChatActionDefinition attribute of your X++ class. The System.Activity.Text variable is set to the event payload as a JSON string. You can add a Parse value node to the topic to parse the System.Activity.Text value for the values of the output parameters of the client action.

Note

In a coming release, client plugins will be invoked by generative AI, removing the requirement to create topics to invoke the actions and receive the output parameters.