The GenAiFunction metadata type represents an Agentforce Agent Action—the bridge between the Agentforce reasoning engine and executable Salesforce platform logic. Introduced in API version 60.0, a GenAiFunction wraps an underlying Flow, @InvocableMethod ApexClass, GenAiPromptTemplate, or Model Context Protocol (mcpTool) endpoint with natural-language instructions and JSON Schema definitions.

SFDX Bundle Directory Structure

Unlike flat XML metadata types, each GenAiFunction is stored as a bundle directory under force-app/main/default/genAiFunctions/<Action_Name>/:

Text
force-app/main/default/genAiFunctions/
└── Verify_Order_Return_Eligibility/
    ├── Verify_Order_Return_Eligibility.genAiFunction-meta.xml
    ├── input/
    │   └── schema.json
    └── output/
        └── schema.json
GenAiPlugin(Agent Topic) GenAiFunction(.genAiFunction-meta.xml) input/schema.json(copilotAction:isUserInput) invocationTarget(Apex / Flow / Prompt / MCP Tool) output/schema.json(copilotAction:isDisplayable)

Key Metadata Fields

Field Type Required Description
masterLabel string Yes Action name shown in Agentforce Builder
description string No Natural-language instructions telling the LLM when and how to invoke this action
invocationTarget string No API name of the target ApexClass, Flow, or GenAiPromptTemplate
invocationTargetType GenAiFunctionTargetType No Target type: apex, flow, generatePromptResponse, mcpTool (v65.0+), retriever
isConfirmationRequired / requiresConfirmation boolean No Requires explicit user confirmation in the UI before executing destructive actions
isIncludeInProgressIndicator boolean No Shows a live status message in the chat UI while the action runs (v62.0+)
progressIndicatorMessage string No Message shown during execution (for example, Verifying warranty status...)

Production-Grade Bundle Example

1. Metadata XML (Verify_Order_Return_Eligibility.genAiFunction-meta.xml)

XML
<?xml version="1.0" encoding="UTF-8"?>
<GenAiFunction xmlns="http://soap.sforce.com/2006/04/metadata">
    <description>Checks whether a customer order is eligible for return based on the Order Number and purchase date. Always call this action before initiating a return.</description>
    <invocationTarget>OrderReturnEligibilityService</invocationTarget>
    <invocationTargetType>apex</invocationTargetType>
    <isConfirmationRequired>false</isConfirmationRequired>
    <isIncludeInProgressIndicator>true</isIncludeInProgressIndicator>
    <masterLabel>Verify Order Return Eligibility</masterLabel>
    <progressIndicatorMessage>Checking order return eligibility...</progressIndicatorMessage>
</GenAiFunction>

2. Input Schema (input/schema.json)

JSON
{
  "unevaluatedProperties": false,
  "properties": {
    "orderNumber": {
      "title": "Order Number",
      "description": "The 8-digit alphanumeric Order Number provided by the customer (for example, ORD-94821).",
      "lightning:type": "lightning__textType",
      "lightning:isPII": false,
      "copilotAction:isUserInput": true
    }
  },
  "required": ["orderNumber"],
  "lightning:type": "lightning__objectType"
}

3. Output Schema (output/schema.json)

JSON
{
  "unevaluatedProperties": false,
  "properties": {
    "isEligible": {
      "title": "Is Eligible",
      "description": "Indicates whether the order is within the 30-day return window.",
      "lightning:type": "lightning__booleanType",
      "copilotAction:isDisplayable": false,
      "copilotAction:isUsedByPlanner": true
    },
    "eligibilityReason": {
      "title": "Eligibility Reason",
      "description": "Explanation of why the order is eligible or ineligible for return.",
      "lightning:type": "lightning__textType",
      "copilotAction:isDisplayable": true,
      "copilotAction:isUsedByPlanner": true
    }
  },
  "lightning:type": "lightning__objectType"
}

Tip

copilotAction:isUsedByPlanner vs copilotAction:isDisplayable: Set copilotAction:isUsedByPlanner to true on output fields that the reasoning engine needs to decide its next step (such as boolean flags or status codes), and set copilotAction:isDisplayable to false on internal IDs or raw JSON payloads you do not want rendered directly in the chat widget.

Frequently asked questions

What is the SFDX directory structure for a GenAiFunction?

Each GenAiFunction lives in its own subfolder under genAiFunctions/ActionName/ containing ActionName.genAiFunction-meta.xml, an input/schema.json file defining expected inputs, and an output/schema.json file defining returned outputs.

Which invocationTargetType values are supported by GenAiFunction?

GenAiFunction supports apex, flow, generatePromptResponse (Prompt Builder templates), mcpTool (Model Context Protocol tools in API v65.0+), standardFunction,retriever, and datacloud.

What does requiresConfirmation do on a GenAiFunction?

When requiresConfirmation is true (API version 63.0+), the Agentforce UI prompts the human user to explicitly confirm the action before the underlying Flow or Apex method executes.

How does the LLM know what parameters to pass into a GenAiFunction?

The LLM inspects the GenAiFunction description and the property descriptions inside input/schema.json, where copilotAction:isUserInput marks parameters that the agent can extract from the conversation.

What is the purpose of progressIndicatorMessage on a GenAiFunction?

When isIncludeInProgressIndicator is true, the progressIndicatorMessage text (for example, Checking order eligibility...) is displayed in the chat window while the action is executing.

Comments

Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.