Skip to content

ProGuide Create an AI Assistant Function

UmaHarano edited this page May 12, 2025 · 1 revision
Language:      C#
Subject:       Framework
Contributor:   ArcGIS Pro SDK Team <[email protected]>
Organization:  Esri, http://www.esri.com
Date:          04/09/2025
ArcGIS Pro:    3.5
Visual Studio: 2022

This ProGuide explains the step by step process on how to create an AI Assistant Function to extend ArcGIS Pro's AI Assistant

In this topic

Prerequisites

Ensure you have the ArcGIS Pro AI Assistant Beta 3.5 installed along with the proapp-sdk-ai-assitant.vsix.

ProSDKAIAssistantVsix

Step 1

Create a new addin project. Call it CreateLayoutAIFunction. Store it in the folder of your choice.

Step 2

From the right-click visual studio project context menu, select "Add->New Item...". Click on the (newly installed) "ArcGIS Pro AI Assistant function (Beta)" item template to create a new AI Assistant Function. Call your AI Assistant Function "CreateDefaultLayout".

ProSDKAIAssistantTemplate

Step 3

The template will have generated a new AI Assistant extension class called CreateDefaultLayoutClass containing an AI assistant function called CreateDefaultLayout. We will inspect the code.

internal class CreateDefaultLayoutClass
{
   [AIAssistantFunction, Description("CreateDefaultLayout description")]
   public static AIFunctionResult CreateDefaultLayout(
       [Description("CreateDefaultLayout optionalTextString parameter description")] 
           string optionalTextString = "")
   {
      //TODO: CreateDefaultLayout implementation goes here
      System.Diagnostics.Debug.WriteLine(
$"Project Name: {Project.Current.Name}. Executing CreateDefaultLayout with parameter {optionalTextString}: {DateTime.Now}");
      return new AIFunctionResult("CreateDefaultLayout was executed");
   }
}

Some important points of interest: AI assistant functions are declared as public static. They return type of ArcGIS.Desktop.Internal.Core.Assistant.AIFunctionResult*. They are decorated with the [AIAssistantFunction, ...] attribute. This is what identifies a "generic" function as being an "AI Assistant Function". The "default" AI Assistant Function auto-generated by the template also includes an optional function parameter string optionalTextString. Note that it too has a [Description("...")] attribute, same as its parent function (whose description is included within the AIAssistantFunction attribute).

Step 4

We will inspect the Config.daml. Notice that the item template also added registration "code", or "xml", into the Config.daml:

<categories>
  <updateCategory refID="esri_core_ai_assistant_extension_category">
    <insertComponent id="CreateLayoutAIFunction_CreateLayout" className="CreateDefaultLayoutClass">
      <content searchDescription="CreateDefaultLayoutClass description">
        <aiAssistantFunction name="CreateDefaultLayout" searchDescription="CreateDefaultLayout description">
          <!--<dependencies>-->
          <!--Add a dependency AI Assistant Function to your function-->
          <!--<dependency refID="esri_mapping_assistant_extension|GetAllLayers"/>-->
          <!--</dependencies>-->
        </aiAssistantFunction>
      </content>
    </insertComponent>
  </updateCategory>
</categories>

Some important points of interest: AI assistant extension classes and their child AI assistant functions must be registered in the esri_core_ai_assistant_extension_category category. The registration includes an <insertComponent .../> element for the class and one <aiAssistantFunction .../> element per child AI assistant functions. In this case the template generates just a single function: "CreateDefaultLayout" so there is one <aiAssistantFunction .../> child element in this case. The class name attribute of the insertComponent element must match the class name of the extension function - "CreateDefaultLayoutClass" in this case. The name attribute on the aiAssistantFunction element must match the name of the AI assistant function - "CreateDefaultLayout" in this case. We will be changing the various "description" attributes in the following steps.

Step 5

We are going to add the code to our function to generate a default layout (via the AI Assistant). First, change the signature of the AI Assistant function as follows:

[AIAssistantFunction, Description("Create a default layout using the current map")]
public static async Task<AIFunctionResult> CreateDefaultLayout(
				[Description("The optional name of the layout")] 
      string layoutName = "Default Layout")
{

Note these changes:

  • The function description attribute has been changed to "Create a default layout using the current map". This is important. This description will be used by the LLM to determine the purpose of our function.
  • The parameter description has been changed to "The optional name of the layout" which will also be used by the LLM to determine the purpose of the parameter - i.e. to allow a user to specify the name of the layout. Note also that, if no name is provided, it defaults to "Default Layout".
  • We changed the return type from AIFunctionResult to Task<AIFunctionResult> reflecting that this particular method will be asynchronous. This is always usually going to be the case as most of the Pro SDK public api requires use of a QueuedTask.

Step 6

Add the layout generation code to the body of the method. This is "standard" layout creation code using LayoutFactory and ElementFactory same as would any other addin code needed for layout generation. Note also the use of QueuedTask.

[AIAssistantFunction, Description("Create a default layout using the current map")]
public static async Task<AIFunctionResult> CreateDefaultLayout(
   [Description("The optional name of the layout")] 
   string layoutName = "Default Layout")
{
   //Get the active map view.
   var map = MapView.Active.Map;

   var layout = await QueuedTask.Run(() =>
   {
      var layout = LayoutFactory.Instance.CreateLayout(8.5, 11, LinearUnit.Inches);
      layout.SetName(layoutName);

      //Add a map frame
      var mf_env = EnvelopeBuilderEx.CreateEnvelope(0.77, 1.3, 7.7, 9.7);

      var mf = ElementFactory.Instance.CreateMapFrameElement(
		layout, mf_env, map, "Default Map", false);

     //Add a title
     var title_sym = SymbolFactory.Instance.ConstructTextSymbol(
		ColorFactory.Instance.BlackRGB, 36, "AvenirNext LT Pro Medium", "Italic");
     var title_text = new Coordinate2D(0.77, 9.7);

     ElementFactory.Instance.CreateTextGraphicElement(
		layout, TextType.PointText, title_text.ToMapPoint(), title_sym,
		layoutName, "Title Text1", false);

      //Add a north arrow
      var na_frame = EnvelopeBuilderEx.CreateEnvelope(7.1, 1.3, 7.7, 1.9);

      var north_arrow_info = new NorthArrowInfo()
      {
          MapFrameName = mf.Name
      };

      ElementFactory.Instance.CreateMapSurroundElement(
          layout, na_frame, north_arrow_info, "", false,
          new ElementInfo() { Anchor = Anchor.BottomRightCorner});

      //Add a scale bar
      var sb_frame = EnvelopeBuilderEx.CreateEnvelope(3.09, 0.914, 5.4, 1.41);

      var sbar_info = new ScaleBarInfo()
      {
          MapFrameName = mf.Name
      };

      ElementFactory.Instance.CreateMapSurroundElement(
          layout, sb_frame, sbar_info, "", false,
          new ElementInfo() { Anchor = Anchor.BottomMidPoint});

      return layout;
   });

   //GUI thread
   await FrameworkApplication.Current.Dispatcher.InvokeAsync(async () =>
   {
      await ProApp.Panes.CreateLayoutPaneAsync(layout);
   });

   return new AIFunctionResult("Layout created and opened");
}

Step 7

We are going to update the <aiAssistantFunction .../> element. Change the searchDescription to "Create a default layout from the current map". This is the same description as was used for the function description in the code behind. Note that the searchDescription and Description don't always necessarily have to be the same (i.e. "identical") - even though they are in this case. The searchDescription in the Config.daml is used in a semantic search "upfront" by the AI Assistant to determine the purpose of your function whereas the Description in the code-behind is used by the LLM when it infers your method's usage and relevance in relation to a given user's chat entry. Next we will add the condition "esri_mapping_mapPane" to the <aiAssistantFunction .../> element to enable/disable it if there is/is not a map available. Here is the updated Config.daml.

<updateCategory refID="esri_core_ai_assistant_extension_category">
  <insertComponent ...>
    <content ...>
      <aiAssistantFunction name="CreateDefaultLayout" 
         searchDescription="Create a default layout from the current map"
         condition="esri_mapping_mapPane">
         ...
      </aiAssistantFunction>

Step 9

Compile and fix any errors.

Step 10

Run the addin in the debugger. Open any Pro project and make sure that it has an active map (otherwise your function method will be disabled). Open the AI Assistant dockpane. You will find it on the Help tab.

ProAIAssistantTab

Step 11.

Start a "Pro AI Assistant action session". This will switch the AI Assistant from executing Pro Help (the default) in response to your chat entries to executing Pro actions (as implemented by AI assistant functions). You can initiate an action session either via the burger button "AI-Assisted Pro Actions" option or by clicking the "Actions - Help me perform an action" button.

ProAIAssistantActionSession

Step 12

Type into the chat "Please create a default layout using the current map". Hit enter. You should see a new layout pane generated (via your ai assistant function). Feel free to experiment with different phrasing and specifying a title string, or not.

Developing with ArcGIS Pro

    Migration


Framework

    Add-ins

    Configurations

    Customization

    Styling


Arcade


Content


CoreHost


DataReviewer


Editing


Geodatabase

    3D Analyst Data

    Plugin Datasources

    Topology

    Linear Referencing

    Object Model Diagram


Geometry

    Relational Operations


Geoprocessing


Knowledge Graph


Layout

    Reports

    Presentations


Map Authoring

    3D Analyst

    CIM

    Graphics

    Scene

    Stream

    Voxel


Map Exploration

    Map Tools


Networks

    Network Diagrams


Parcel Fabric


Raster


Sharing


Tasks


Workflow Manager


Reference

Clone this wiki locally