Salesforce Developers Blog

Agentforce Metadata Types in Winter ’27: Dive into AiAgentDefinition

Avatar for Shreyas RameshShreyas Ramesh
Explore two new Agentforce metadata types in Winter ’27 that simplify managing, retrieving, and deploying agents across Salesforce orgs. Learn how these enhancements streamline agent versioning and development workflows.
Agentforce Metadata Types in Winter ’27: Dive into AiAgentDefinition
November 11, 2026

If you move Agentforce agents between orgs with Salesforce CLI or a continuous integration and continuous delivery (CI/CD) pipeline, the Winter ’27 release makes your work simpler. API version 68.0 introduces two new metadata types for agents: AiAgentDefinition and AiAgentDefinitionVersion. Each agent now has one definition and one folder per version, with readable names.

An earlier post, The New Agentforce Metadata and Development Lifecycle, showed how Agent Script agents map to the Bot, GenAiPlannerBundle, and AiAuthoringBundle metadata types. This post picks up from there. It covers why we simplified agent metadata and compares the old and new structures side by side, using a real agent. It also covers what to know before you retrieve and deploy with the new types.

Agent metadata before API version 68.0 (Winter ’27)

To see what changed, let’s start with a real agent. TestAgent is an Agentforce Service Agent built with Agent Script. It has one version, 10 subagents, and 26 actions. Here’s what you get when you retrieve it into a Salesforce DX project at API version 67.0.

1├── aiAuthoringBundles
2│   └── TestAgent
3│       ├── TestAgent.agent
4│       └── TestAgent.bundle-meta.xml
5├── bots
6│   └── TestAgent
7│       ├── TestAgent.bot-meta.xml
8│       └── v1.botVersion-meta.xml
9└── genAiPlannerBundles
10    └── TestAgent_v1
11        ├── TestAgent_v1.genAiPlannerBundle
12        ├── agentGraph
13        │   └── TestAgent_v1_graph.json
14        ├── agentScript
15        │   └── TestAgent_v1_definition.agent
16        └── localActions
17            ├── AccountManagement_1793afaabbea5e6
18            ├── CaseManagement_1797b79603146ff
19            ├── DeliveryIssues_1799f005010de87
20            │   ├── AnswerQuestionsWithKnowledge_17288a938fc0c53
21            │   │   ├── input
22            │   │   │   └── schema.json
23            │   │   └── output
24            │   │       └── schema.json
25            │   └── ... 5 more actions
26            ├── GeneralFAQ_17958732d5d84f7
27            ├── OrderInquiries_179524d7fde40be
28            ├── ReservationManagement_17932b500c2b88d
29            └── ServiceCustomerVerification_1796152b9540575
30                ├── SendEmailVerificationCode_1724f12735f68c6
31                └── VerifyCustomer_1726b9bee0044be

One agent with one version is spread across three metadata types (Bot, GenAiPlannerBundle, and AiAuthoringBundle). The agent’s settings live in TestAgent.bot-meta.xml (the bot), and the version’s settings and welcome message live in v1.botVersion-meta.xml (the version). The subagents and actions live in TestAgent_v1 (the planner bundle), and the Agent Script source sits in TestAgent.agent (the authoring bundle).

Here are the four biggest pain points we heard about from you regarding this structure:

One agent, many names. The same agent shows up as TestAgent.bot-meta.xml, v1.botVersion-meta.xml, TestAgent_v1, and TestAgent.agent. Deployment and retrieval operations can fail unless your tooling understands how these names correspond and strictly adheres to a complex naming structure. If you write your manifest by hand, every new version also adds a GenAiPlannerBundle member and an AiAuthoringBundle member to it.

Generated suffixes everywhere. Every subagent and action in a version gets a unique name with a generated suffix, such as ServiceCustomerVerification_1796152b9540575. In our one-version sample, the planner bundle contains 37 suffixed names, used 111 times, plus 33 suffixed folders. The suffixes mean nothing to you. Each version also gets its own suffixes, so comparing two versions shows changes that you never made.

Messages hidden in dialogs. To find your agent’s welcome message, you have to dig through a dialog, its steps, and its messages. Each one has its own generated identifier.

Folder names that move. At API version 67.0 and earlier, the newest authoring bundle has no version number, while older ones do. For example, once TestAgent has four versions, its newest bundle is TestAgent, and the older ones are TestAgent_1, _2, and _3. When you create a version, a different folder becomes the unnumbered one. So the same bundle can have a different name from one retrieve to the next.

What’s new in API version 68.0

API version 68.0 gives each agent a simpler shape. One metadata type holds the agent, and one metadata type holds everything that belongs to a version.

Metadata type What it represents Member name
AiAgentDefinition The agent: its type, description, context variables, and other agent-level settings TestAgent
AiAgentDefinitionVersion One version of the agent: its settings, conversation variables, and messages, plus an inline <planner> element with its subagents and actions TestAgent#1
AiAuthoringBundle The Agent Script source that you edit (unchanged) TestAgent_1

In a Salesforce DX project, the files for these types live in the aiAgents, aiAgentDefinitionVersions, and aiAuthoringBundles folders.

At API version 68.0, Agentforce agents use the new types, and the Bot and BotVersion types are for classic Einstein Bots. If you retrieve or deploy an Agentforce agent as Bot or BotVersion at this API version, you get an error that tells you to use AiAgentDefinition and AiAgentDefinitionVersion instead. To keep using the old types, stay on API version 67.0.

Before and after: the folder structure

Here’s the same agent retrieved at API version 68.0.

1├── aiAgents
2│   └── TestAgent.aiAgentDefinition-meta.xml
3├── aiAgentDefinitionVersions
4│   └── TestAgent#1
5│       ├── TestAgent#1.aiAgentDefinitionVersion-meta.xml
6│       ├── agentGraph
7│       │   └── TestAgent_v1_graph.json
8│       ├── agentScript
9│       │   └── TestAgent_v1_definition.agent
10│       └── localActions
11│           ├── AccountManagement
12│           ├── CaseManagement
13│           ├── DeliveryIssues
14│           │   ├── AnswerQuestionsWithKnowledge
15│           │   │   ├── input
16│           │   │   │   └── schema.json
17│           │   │   └── output
18│           │   │       └── schema.json
19│           │   └── ... 5 more actions
20│           ├── GeneralFAQ
21│           ├── OrderInquiries
22│           ├── ReservationManagement
23│           └── ServiceCustomerVerification
24│               ├── SendEmailVerificationCode
25│               └── VerifyCustomer
26└── aiAuthoringBundles
27    └── TestAgent_1
28        ├── TestAgent_1.agent
29        └── TestAgent_1.bundle-meta.xml

If you know the old types, here’s how they map:

  • The agent-level part of Bot becomes AiAgentDefinition.
  • Each bot version and its GenAiPlannerBundle merge into one AiAgentDefinitionVersion.
  • The planner is no longer a separate component. Instead, it’s a <planner> element inside the version file.
  • AiAuthoringBundle remains largely unchanged, except that every AiAuthoringBundle file name also explicitly names its version as a suffix.

A key enhancement in API version 68.0 is support for selecting specific version members using the # delimiter. In your package.xml manifest or with the --metadata flag in Salesforce CLI, you can target an individual agent version, retrieve every version of a specific agent, or query across all versions for all agents, as shown in the table below.

Member What it selects
TestAgent#1 Version 1 of TestAgent
TestAgent#* All versions of TestAgent
* All versions of all agents

A few things stand out.

  • Everything that belongs to version 1, except its Agent Script source, lives in one folder, TestAgent#1.
  • Subagent and action folders use the names that you gave them, like DeliveryIssues/AnswerQuestionsWithKnowledge.
  • The authoring bundle folder always carries its version number. TestAgent_1 keeps its name when you add version 2.

The content itself didn’t change. When the two retrieves were compared, all 52 input and output schemas, the agent graph, and the .agent source file were identical. Only the names and the packaging changed.

Before and after: subagents and actions

The biggest difference is inside the files. Here’s the Service Customer Verification subagent and one of its actions in the API version 67.0 planner bundle. Some elements have been trimmed to save space.

1<localTopics>
2    <fullName>ServiceCustomerVerification_1796152b9540575</fullName>
3    <canEscalate>false</canEscalate>
4    <description>Verifies the customer's identity before granting access to sensitive data. ...</description>
5    <developerName>ServiceCustomerVerification_1796152b9540575</developerName>
6    <!-- instructions omitted -->
7    <language>en_US</language>
8    <localActionLinks>
9        <functionName>SendEmailVerificationCode_1724f12735f68c6</functionName>
10    </localActionLinks>
11    <localActionLinks>
12        <functionName>VerifyCustomer_1726b9bee0044be</functionName>
13    </localActionLinks>
14    <localActions>
15        <fullName>VerifyCustomer_1726b9bee0044be</fullName>
16        <description>Verifies whether the verification code entered by the user matches the code sent to the user's email address.</description>
17        <developerName>VerifyCustomer_1726b9bee0044be</developerName>
18        <invocationTarget>SvcCopilotTmpl__VerifyCode</invocationTarget>
19        <invocationTargetType>flow</invocationTargetType>
20        <isConfirmationRequired>false</isConfirmationRequired>
21        <isIncludeInProgressIndicator>true</isIncludeInProgressIndicator>
22        <localDeveloperName>VerifyCustomer</localDeveloperName>
23        <masterLabel>Verify Customer</masterLabel>
24        <source>SvcCopilotTmpl__VerifyCustomer</source>
25    </localActions>
26    <!-- SendEmailVerificationCode action omitted -->
27    <localDeveloperName>ServiceCustomerVerification</localDeveloperName>
28    <masterLabel>Service Customer Verification</masterLabel>
29    <pluginType>Topic</pluginType>
30</localTopics>

And here’s the same subagent in the API version 68.0 version file, inside the <planner> element.

1<localTopics>
2    <canEscalate>false</canEscalate>
3    <description>Verifies the customer's identity before granting access to sensitive data. ...</description>
4    <!-- instructions omitted -->
5    <language>en_US</language>
6    <localActionLinks>
7        <functionName>SendEmailVerificationCode</functionName>
8    </localActionLinks>
9    <localActionLinks>
10        <functionName>VerifyCustomer</functionName>
11    </localActionLinks>
12    <!-- SendEmailVerificationCode action omitted -->
13    <localActions>
14        <description>Verifies whether the verification code entered by the user matches the code sent to the user's email address.</description>
15        <invocationTarget>SvcCopilotTmpl__VerifyCode</invocationTarget>
16        <invocationTargetType>flow</invocationTargetType>
17        <isConfirmationRequired>false</isConfirmationRequired>
18        <isIncludeInProgressIndicator>true</isIncludeInProgressIndicator>
19        <localDeveloperName>VerifyCustomer</localDeveloperName>
20        <masterLabel>Verify Customer</masterLabel>
21        <source>SvcCopilotTmpl__VerifyCustomer</source>
22    </localActions>
23    <localDeveloperName>ServiceCustomerVerification</localDeveloperName>
24    <masterLabel>Service Customer Verification</masterLabel>
25    <pluginType>Topic</pluginType>
26</localTopics>

The suffixed fullName and developerName elements are gone. Now localDeveloperName is the name, and links between subagents and actions use it too. In this sample, all 37 suffixed subagent and action names disappeared. Because subagent and action names stay the same from one version to the next, diffs between versions get much smaller and easier to review.

Before and after: welcome and error messages

In API version 67.0, your welcome message sits inside a Welcome dialog in the bot version file.

1<botDialogs>
2    <botSteps>
3        <botMessages>
4            <message>Hi, I'm an AI service assistant. How can I help you?</message>
5            <messageIdentifier>7c57d39d-5d76-40d9-a8e8-181b1a20b657</messageIdentifier>
6        </botMessages>
7        <stepIdentifier>42386b78-770c-4911-8ad9-60f664fdeab0</stepIdentifier>
8        <type>Message</type>
9    </botSteps>
10    <botSteps>
11        <stepIdentifier>fdf3a8b3-f4b0-4329-a7f5-349f387b84db</stepIdentifier>
12        <type>Wait</type>
13    </botSteps>
14    <developerName>Welcome</developerName>
15    <isPlaceholderDialog>false</isPlaceholderDialog>
16    <label>Welcome</label>
17    <showInFooterMenu>false</showInFooterMenu>
18</botDialogs>
19<!-- ... -->
20<entryDialog>Welcome</entryDialog>

In API version 68.0, it’s one line.

1<welcomeMessage>Hi, I'm an AI service assistant. How can I help you?</welcomeMessage>

The version file has three simple message elements: welcomeMessage, errorMessage, and escalationMessage. They hold the first message of the Welcome, Error_Handling, and Transfer_To_Agent dialogs. When you deploy, Salesforce builds the dialogs from these messages for you.

Before and after: package.xml

Now suppose that TestAgent has four versions. It also uses a global subagent and two global actions, which call an Apex class and a prompt template. Here’s a hand-written API version 67.0 manifest for it.

1<?xml version="1.0" encoding="UTF-8"?>
2<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3    <types>
4        <members>TestAgent</members>
5        <name>Bot</name>
6    </types>
7    <types>
8        <members>TestAgent_v1</members>
9        <members>TestAgent_v2</members>
10        <members>TestAgent_v3</members>
11        <members>TestAgent_v4</members>
12        <name>GenAiPlannerBundle</name>
13    </types>
14    <types>
15        <members>TestAgent_1</members>
16        <members>TestAgent_2</members>
17        <members>TestAgent_3</members>
18        <members>TestAgent</members>
19        <name>AiAuthoringBundle</name>
20    </types>
21    <types>
22        <members>Custom_Subagent</members>
23        <name>GenAiPlugin</name>
24    </types>
25    <types>
26        <members>SayHello</members>
27        <name>ApexClass</name>
28    </types>
29    <types>
30        <members>Custom_PromptTemplate</members>
31        <name>GenAiPromptTemplate</name>
32    </types>
33    <types>
34        <members>Say_Hello</members>
35        <members>Custom_PromptTemplate</members>
36        <name>GenAiFunction</name>
37    </types>
38    <version>67.0</version>
39</Package>

That’s 7 types and 14 members. At API version 68.0, you name the agent and its versions.

1<?xml version="1.0" encoding="UTF-8"?>
2<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3    <types>
4        <members>TestAgent</members>
5        <name>AiAgentDefinition</name>
6    </types>
7    <types>
8        <members>TestAgent#*</members>
9        <name>AiAgentDefinitionVersion</name>
10    </types>
11    <version>68.0</version>
12</Package>

The #* wildcard picks up every version, so you don’t need to edit the manifest when you add one.

How to retrieve Agentforce metadata dependencies with the Salesforce CLI

What about the Apex class, the prompt template, and the global subagent and actions? Each agent version knows what it uses, so you can ask the Metadata API to bring those along. With Salesforce CLI, add the --root-type-with-dependencies flag and set it to AiAgentDefinitionVersion. You can use it with a manifest or with the --metadata flag. Using the # delimiter syntax and the new flag requires Salesforce CLI version 2.149.9 or later, so be sure to execute sf update prior to running these commands.

1# With the manifest above
2sf project retrieve start --manifest manifest/package.xml --root-type-with-dependencies AiAgentDefinitionVersion --target-org my-sandbox
3
4# Without a manifest, for version 1 of TestAgent
5sf project retrieve start --metadata "AiAgentDefinitionVersion:TestAgent#1" --root-type-with-dependencies AiAgentDefinitionVersion --target-org my-sandbox

In both cases, the retrieve then adds what each version depends on. That includes its parent AiAgentDefinition and its AiAuthoringBundle, which holds the Agent Script source that you edit. It also includes the flows, Apex classes, and prompt templates that its actions call, and any global subagents and actions that it uses. The compiled Agent Script file in the version’s agentScript folder isn’t a dependency. It’s part of the version, so you get it with or without the flag.

Without the flag, you get only what you name. For example, --metadata AiAgentDefinitionVersion on its own retrieves every version of every agent. It doesn’t bring each version’s parent AiAgentDefinition, its AiAuthoringBundle, or anything else that it uses, so name the ones that you need too. If you name versions with --metadata, put the value in double quotes so that your shell doesn’t treat # or * as special characters. Without a manifest, Salesforce CLI uses the sourceApiVersion in your sfdx-project.json file, so set it to 68.0.

Retrieving with dependencies isn’t new. From API version 64.0 (Summer ’25) through 67.0, you could do it only for a whole Bot, so you always got every version of the agent. Now you can do it for a single version, so you can move exactly the version that you want, plus what it needs.

A few limits apply. You can make up to 25 retrieve requests with dependencies per day, and each request can cover up to 100 components. The retrieve also goes only one level deep. It adds what each version uses directly, but not what those dependencies use in turn. For example, if an action calls an Apex class that uses another Apex class, you get only the first class. Add other metadata that your agent needs, such as custom objects or Data 360 dependencies, to your manifest or --metadata list.

Deployment validations in API version 68.0

The new types come with a few deployment validation rules. Most of them protect you from half-deployed agents. Deployment of agents on API 68.0 will fail if:

You mix the old and new formats. Pick either API 67.0 or API 68.0 format. Don’t try to deploy Bot or BotVersion and the new types for the same agent in the same deployment.

You deploy the definition without at least one version. A version can’t deploy unless its AiAgentDefinition already exists in the target org or is in the same deployment. A new definition also needs at least one version. The first time you deploy an agent to an org, include the definition, not just a version.

Your Agent Script source is not included. For agents built with Agent Script, you must deploy the version’s AiAuthoringBundle along with the AiAgentDefinitionVersion. Note the agentScript folder inside the version is a compiled copy, not the source that you edit. Storing the compiled copy in your source control is not recommended.

You don’t set the agent user correctly. Your retrieved metadata includes the agent username from the source org. For a draft agent, use string replacement to swap in a username from the target org. Committed agents can’t be edited, so to give one a new user, create a new version and add the user there. Either way, the agent needs a user before it can run in the new org.

Migration tips for switching to API 68.0

  • Retrieve instead of converting by hand. Run sf update to get the latest Salesforce CLI, set your manifest version and the sourceApiVersion in your sfdx-project.json file to 68.0, and retrieve. Salesforce writes the new structure for you.
  • Make the switch in its own commit. Every agent folder and file name changes, so keep the switch separate from other work. Real changes won’t get lost in the rename during code review.
  • Update scripts that read agent XML. If your pipeline parses GenAiPlannerBundle files or relies on suffixed names, point it at the <planner> element in the version file and use localDeveloperName.

Conclusion

API version 68.0 gives every Agentforce agent a simpler, more predictable metadata shape. You get one definition per agent, one folder per version, names without generated suffixes, and messages that you can read at a glance. Your manifests get shorter, your diffs get smaller, and you can retrieve a single version with everything it depends on. Try it in a Winter ’27 org: retrieve one of your agents at API version 68.0 and compare it with what’s in your source control today.

Resources

About the author

Shreyas Ramesh serves as a Lead Software Engineer with Salesforce AI in San Francisco. He is also a Fellow of the Institute of Analytics (FIoA) alongside BCS, The Chartered Institute for IT. Within the Agentforce Core Platform group, Shreyas directs the architecture for Agentforce Metadata, Agentforce Versioning, and additional design-time functionality aimed at providing enterprise-grade application lifecycle management (ALM) for Agentforce. Connect with Shreyas via LinkedIn.

More Blog Posts

The New Agentforce Metadata and Development Lifecycle

The New Agentforce Metadata and Development Lifecycle

Streamline your CI/CD pipelines by leveraging the new versioned metadata model and human-readable Agent Scripts. Learn how bundleized assets eliminate "global ripples" and simplify peer reviews for more reliable agent deployments.May 14, 2026

新しいAgentforceメタデータと開発ライフサイクル

新しいAgentforceメタデータと開発ライフサイクル

新しいバージョン管理付きメタデータモデルと、人間が読みやすいAgent Scriptを活用して、CI/CDパイプラインを効率化しましょう。バンドル化されたアセットが「グローバルな波及効果」を排除し、ピアレビューを簡素化することで、より信頼性の高いエージェントのデプロイを実現する方法を学びましょう。August 25, 2026

The Salesforce Developer’s Guide to the Summer ’26 Release

The Salesforce Developer’s Guide to the Summer ’26 Release

Summer ’26 developer highlights: Hosted MCP Servers, LWC State Managers, Apex user-mode defaults, Agentforce Mobile SDK, and CLI updates with code examples.June 08, 2026