all insights

Deploying an Agentforce agent from sandbox to production: the metadata map nobody hands you

You built the agent in a sandbox, it passed testing, and now you have to move it to production — and the change set is missing half of it. An Agentforce agent is not one object; it is a stack of Bot, planner, topic, and action metadata with a strict dependency order. Here is the whole deployment, the ordering that stops it failing, and the pieces that never travel in the metadata at all.

Deploying an Agentforce agent from sandbox to production: the metadata map nobody hands you — article illustration

You built the agent in a sandbox. It classifies topics correctly, the actions fire, testing passed, and a stakeholder signed off. Now you have to put it in production — and the moment you open a change set or a deployment, the tidy single “agent” you built in Agentforce Builder dissolves into a pile of unfamiliar metadata types with names like GenAiPlannerBundle and GenAiPlugin, half of which the change set didn’t pick up as dependencies. You deploy anyway, and production shows an agent that either isn’t visible, won’t respond, or answers with a topic that quietly points at an action that doesn’t exist yet.

This is the step Trailhead skips and the demo never shows. Building an agent is a designer’s job; deploying one is a release engineer’s job, and the two require completely different knowledge. An Agentforce agent is not an object — it’s a small graph of metadata components with a strict dependency order, wired to a handful of things (the running user, connections, permission sets) that don’t travel in the metadata at all. Get the graph and the order right and deployment is boring. Get them wrong and you spend a launch day debugging an agent that worked perfectly forty minutes ago in a different org.

This is the practitioner’s deployment map: what the metadata actually is, the order it has to move in, why change sets are the fragile option, and the out-of-band pieces that decide whether the agent works once it lands.

An agent is a stack, not an object

Open the agent you built and look underneath the Builder UI. What you designed as one thing is represented in metadata as several types, each a layer:

  • Bot and BotVersion — the foundation. Agentforce agents are built on the same Einstein Bot framework that powered the previous generation, so every agent has a Bot record and at least one BotVersion. If these don’t exist in the target org, nothing above them is visible, no matter what else you deploy.
  • GenAiPlannerBundle — the agent’s brain: the planner that ties the agent to its topics and defines how it reasons over them. On Summer ‘26 orgs (Metadata API v64) this is the current type. Its predecessor, GenAiPlanner, shipped in API v60 and is deprecated from v64 on — if you’re reading older guides that reference GenAiPlanner, check your API version before you copy their manifest.
  • GenAiPlugin — a topic. Each topic the agent can handle is a plugin: its scope, its instructions, and the list of actions it’s allowed to call.
  • GenAiFunction — an action. The custom things the agent can do — the ones you wired up in Apex or Flow — are functions, each pointing at the Apex class, Flow, or prompt template that actually runs.
  • GenAiPromptTemplate — any Prompt Builder template the agent or its actions use for grounded generation.

The mental model that saves you: the planner references topics, topics reference actions, actions reference the Apex and Flows that implement them. It’s a chain of references pointing downward, and a reference to something that isn’t there yet is a deployment failure. That single fact dictates everything about how you move it.

An Agentforce agent deploys like a dependency graph, not a file. The planner is useless without its topics, the topics without their actions, the actions without the Apex and Flows they call. Deploy bottom-up or don’t deploy at all.

To even see these types in a retrieve, you need Metadata API version 60 or higher. Point an older API version at the org and the GenAi* types simply won’t appear in your manifest, which is how teams end up “deploying the agent” and moving only the Bot shell.

The order that stops it failing

Because the references point downward, you deploy from the bottom of the chain up. The implementing components first, then the metadata that points at them, and the planner last. A reliable sequence:

  1. The plumbing the actions call. Apex classes, Flows, custom objects and fields, external services, custom metadata — everything an action’s implementation depends on. If a GenAiFunction invokes an Apex class that isn’t in the target, the function is dead on arrival.
  2. Bot and BotVersion. The foundation the planner attaches to. If the agent is new to the target org, these have to land before the planner or the planner won’t be visible.
  3. GenAiPromptTemplate. Any prompt templates the actions or the agent reference.
  4. GenAiFunction. The actions, now that the Apex, Flows, and prompt templates they point at all exist.
  5. GenAiPlugin. The topics, now that the actions they list all exist.
  6. GenAiPlannerBundle. The planner last, now that every topic it references is present.

You don’t have to run six separate deployments — a single deployment that includes the whole set will resolve the graph internally — but when a deployment fails, this is the order you troubleshoot in, because the failure is almost always “a thing near the top referenced a thing near the bottom that didn’t make it.” A minimal manifest for the agent layer looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>Support_Agent</members>
    <name>Bot</name>
  </types>
  <types>
    <members>Support_Agent_v1</members>
    <name>BotVersion</name>
  </types>
  <types>
    <members>*</members>
    <name>GenAiPlugin</name>
  </types>
  <types>
    <members>*</members>
    <name>GenAiFunction</name>
  </types>
  <types>
    <members>Support_Agent_Planner</members>
    <name>GenAiPlannerBundle</name>
  </types>
  <version>64.0</version>
</Package>

With the Salesforce CLI, the deployment itself is one command:

sf project deploy start --manifest manifest/package.xml --target-org production

The trap in that manifest is the wildcards. <members>*</members> on GenAiPlugin and GenAiFunction pulls every topic and action in the org, which is convenient until it drags along a half-built topic from someone else’s agent. For a controlled release, name the specific plugins and functions your agent uses rather than wildcarding — the extra typing is how you keep an unrelated experiment out of production.

Agentforce DX: the CLI that knows what an agent is

Hand-maintaining that manifest is error-prone because you have to know every topic and function name your agent touches. Agentforce DX — the sf agent command set from the official plugin-agent — exists so you don’t have to. It treats the agent as a first-class unit instead of a scatter of metadata types, which is the same shift the Salesforce DX MCP Server makes for driving an org from an AI client.

The commands worth knowing:

  • sf agent generate template turns an existing agent’s Bot metadata into a reusable template you can version in your DX project.
  • sf agent generate test-spec produces the YAML test spec that drives Testing Center runs — the same artifact your CI pipeline should gate on.
  • sf agent activate / sf agent deactivate flip the agent’s live state in a target org by API name.

That last pair matters more than it looks, because of a fact that surprises every first-time deployer: an agent does not arrive active. You deploy the metadata, it lands, and the agent sits there inactive until something turns it on. That’s a feature — you don’t want a half-configured agent answering customers the instant its metadata lands — but it’s also the reason a “successful” deployment can be followed by an agent that does nothing. Activation is a deliberate, separate step:

sf agent activate --api-name Support_Agent --target-org production

Sequencing that activation after you’ve verified the topics, actions, and grounding is the difference between a controlled go-live and an agent that greets its first real customer while you’re still checking whether the deployment worked.

Why change sets are the fragile option

You can deploy an agent with a change set. Add the agent by its Bot component type, click View/Add Dependencies, and Salesforce pulls in the related components. For a simple agent in a simple org, that sometimes works. Treat it as the fragile path, for three reasons.

First, dependency detection is incomplete. The dependency finder catches much of the graph but not reliably all of it — an action’s Apex class, a referenced prompt template, or a Flow can be missed, and you won’t know until the agent misfires in production. Second, change sets don’t do ordering or dry runs. You can’t validate the dependency graph before committing, and you can’t easily stage the bottom-up sequence. Third, and most important for anything past a first pilot, change sets aren’t a release process. They’re not in source control, they’re not repeatable, and they leave no diff to review — the exact problems the maturity ladder from change sets to real CI/CD is about climbing out of.

For anything beyond a one-off, drive agent deployments through a source-tracked pipeline — Agentforce DX plus your existing DevOps tooling — so the agent is versioned, reviewable, and repeatable like any other metadata. An agent is production software the moment it can touch a customer; it deserves the same release discipline as the Apex behind it.

The pieces that don’t travel in the metadata

Here’s the part that turns a “successful” deployment into a support ticket: several things an agent needs to function are not metadata components and will not move with any deployment, change set, or CLI push. You provision them in the target org by hand, and forgetting one produces an agent that deploys clean and then fails at runtime.

  • The agent (running) user and its permissions. Every agent acts as a user, and that user’s permission sets, sharing, and object access decide what the agent can actually see and do. The permission sets are metadata; the assignment to the right user, and the user’s own configuration, are org-specific. An agent with the wrong running-user access will refuse actions it demoed perfectly — a failure mode that’s really an identity problem, which is exactly why running-user identity sits at the center of governing an agent fleet.
  • Connections and named credentials. If any action calls an external system, the named credentials and external credentials that authenticate it are per-org. The action metadata deploys; the secret behind it does not, and shouldn’t.
  • Channel and Omni-Channel wiring. How the agent reaches customers — the messaging deployment, the Omni-Channel Flow that routes to it — is configured in the target org, not carried in the agent bundle.
  • Data Library and grounding sources. If the agent grounds on a Data Library or Data Cloud, the underlying search index and connected sources are provisioned in the target, not shipped with the planner.

Write these into your deployment runbook as explicit post-deploy steps. The metadata deployment is maybe half the actual go-live; the other half is the org configuration around it, and it’s the half that isn’t in your manifest to remind you.

A known trap and a testing seam

Two specifics worth carrying into your first real deployment.

There’s a known deployment bug where a GenAiPromptTemplate linked to a Flow that contains an Apex action fails to deploy in the same package. The workaround is exactly the bottom-up principle applied harder: deploy the Flow and Apex first, in their own deployment, then deploy the prompt template separately. If a prompt-template deployment fails inexplicably, this is the first thing to check.

And if you author with Agent Script — the deterministic, code-based authoring surface — deploy scripts as drafts first and commit them in the target org, rather than deploying an already-committed script, which can throw unexpected errors mid-deploy. The pattern is the same as everything else here: land the pieces in a controlled state, verify, then flip them live.

The runbook

Deploying an Agentforce agent well is mostly refusing to treat it as one thing. The sequence that holds:

  1. Retrieve at API v64+ so the GenAi* types actually appear.
  2. Deploy bottom-up — Apex and Flows, then Bot/BotVersion, then prompt templates, then functions, then plugins, then the GenAiPlannerBundle — naming components rather than wildcarding.
  3. Provision the out-of-band pieces — running user and permission sets, connections and named credentials, channels, grounding sources.
  4. Verify before activating — topics, instructions, variables, filters, and permissions all present and correct, per the pre-launch testing sequence.
  5. Activate deliberately with sf agent activate, as the last step, once the agent is proven in the target.

Do it through a source-tracked pipeline and the whole thing becomes repeatable — which is the point, because you won’t deploy an agent once. You’ll deploy it every time you tune a topic, add an action, or fix a misclassification, and each of those is the same graph moving through the same order. The teams that ship agents calmly are the ones who wrote the graph down before the first launch, not the ones who rediscover it under pressure on the second.

Understanding the basics

What metadata makes up an Agentforce agent?

An agent is a stack of metadata types, not a single object. At the base are Bot and BotVersion (the Einstein Bot framework the agent is built on). Above them sits the GenAiPlannerBundle (the planner, called GenAiPlanner before API v64), which references GenAiPlugin components (topics), which reference GenAiFunction components (actions), which point at the Apex classes, Flows, and GenAiPromptTemplate records that actually run. You retrieve all of these at Metadata API version 60 or higher.

Why does my agent deploy successfully but not work?

Almost always because something outside the metadata is missing. The agent’s running user, its permission-set assignments, the named credentials behind external actions, the Omni-Channel routing, and the grounding sources are all provisioned per-org and don’t travel in a deployment. A clean deployment plus an unconfigured running user produces an agent that refuses actions it demoed perfectly. The second common cause: the agent deployed inactive and was never activated with sf agent activate.

Can I deploy an Agentforce agent with a change set?

Technically yes — add the agent by its Bot component type and use View/Add Dependencies. But change-set dependency detection is incomplete (it can miss an action’s Apex class or a prompt template), there’s no dry-run or ordering control, and nothing is in source control or reviewable. For anything past a first pilot, use Agentforce DX (sf agent commands) and a source-tracked pipeline so the agent is versioned and repeatable like any other metadata.


Trying to get an Agentforce agent out of a sandbox and into production without a launch-day fire drill — or to put agent deployments on a real release pipeline instead of change sets? Talk to us — building and governing production Agentforce agents is the work we do.

Keep reading

All insights