home Home build Tools bug_report Errors menu_book Guides lightbulb Tips smart_toy Prompts extension Extensions folder_open Resources info About
search

Agentforce is Salesforce's platform for building and deploying autonomous AI agents that can reason, plan, and take actions inside your org — without a human in the loop for every step. Unlike a chatbot that only answers questions, an Agentforce agent can retrieve data, update records, call external APIs, and trigger flows, all driven by natural language instructions.

What Is Agentforce?

Agentforce sits on top of the Einstein 1 Platform and uses a large language model (the Einstein Reasoning Engine) as its brain. You define the agent's role, the topics it can handle, and the actions it can take. At runtime, the LLM decides which topic and action to invoke based on the user's message, executes it, and returns a grounded response.

Agentforce Runtime Architecture
User Layer
person End User
chat Messaging Channel
smart_toy Agentforce Agent
Reasoning Layer
psychology Einstein Reasoning Engine (LLM)
category Topic Classification
bolt Action Selection
Action Layer
code Apex Action
account_tree Flow Action
integration_instructions API Action
search Data Cloud Query
Data Layer
database Salesforce CRM
hub Data Cloud
article Knowledge Base
cloud External Systems
lightbulb

Key mental model: You don't code the agent's decision-making — you configure what the agent can do (Topics + Actions) and the LLM decides when and how to use those tools based on the conversation context.

Core Concepts

Agentforce has four building blocks. Understanding how they compose is the foundation of everything else.

smart_toy

Agent

The top-level entity. Defines the agent's name, persona, role description, and which topics it has access to. An agent can serve one channel (e.g., a service portal) or multiple.

category

Topic

A domain of responsibility. Each topic has a natural language description that the LLM uses to classify incoming requests. A topic contains one or more actions. Example: "Order Management".

bolt

Action

A specific capability the agent can invoke — an Apex method, a Flow, a prompt template, or an external API call. Each action has inputs/outputs the LLM maps to and from the conversation.

psychology

Reasoning Engine

The LLM layer that reads the conversation, selects the right topic and action, maps user intent to action inputs, executes it, and generates a natural language response from the output.

Configuring Topics

Topics are configured in Setup → Agents → [Your Agent] → Topics. The topic description is critical — it's the text the LLM reads to decide whether an incoming user message belongs to this topic. Write it like a job description for the topic.

edit_note

Write better topic descriptions: Be specific about what the topic handles AND what it doesn't. Overlapping descriptions cause the LLM to pick the wrong topic. Include example triggers like "Use this topic when the user asks about order status, cancellations, or shipment tracking."

Example: Well-Written Topic
Topic Name
Order Management
Scope / Description
Handle all customer requests related to orders. Use this topic when the user asks about: checking order status or delivery dates, cancelling or modifying an existing order, reporting a missing or damaged item, requesting a return label, or tracking a shipment. Do not use this topic for product recommendations, account billing questions, or technical support issues.
Actions in this Topic
Get Order Status Cancel Order Create Return Case Send Tracking Link

Building Apex Actions

Apex actions are the most powerful and flexible way to extend Agentforce. An invocable Apex method becomes an action the agent can call with inputs drawn from the conversation and CRM context.

info

Requirements: The Apex class must be global, the method must be @InvocableMethod, and all parameters must use an inner @InvocableVariable wrapper class. The method must be bulkified (accept and return List).

Apex — Invocable Action for Agentforce
global class GetOrderStatusAction {

    // Input wrapper — each @InvocableVariable is a field the LLM can populate
    global class ActionInput {
        @InvocableVariable(
            label='Order Number'
            description='The customer-facing order number, e.g. ORD-12345'
            required=true
        )
        global String orderNumber;

        @InvocableVariable(
            label='Customer Account ID'
            description='Salesforce Account ID of the requesting customer'
            required=false
        )
        global String accountId;
    }

    // Output wrapper — the LLM reads these to formulate its response
    global class ActionOutput {
        @InvocableVariable(label='Order Status')
        global String status;

        @InvocableVariable(label='Estimated Delivery Date')
        global String estimatedDelivery;

        @InvocableVariable(label='Tracking URL')
        global String trackingUrl;

        @InvocableVariable(label='Error Message')
        global String errorMessage;
    }

    @InvocableMethod(
        label='Get Order Status'
        description='Retrieves the current status and delivery information for a given order number. Use when the customer asks where their order is or when it will arrive.'
        category='Order Management'
    )
    global static List<ActionOutput> execute(List<ActionInput> inputs) {
        List<ActionOutput> outputs = new List<ActionOutput>();

        for (ActionInput inp : inputs) {
            ActionOutput out = new ActionOutput();

            try {
                List<Order__c> orders = [
                    SELECT Id, Status__c, Estimated_Delivery__c, Tracking_URL__c
                    FROM Order__c
                    WHERE Order_Number__c = :inp.orderNumber
                    LIMIT 1
                ];

                if (orders.isEmpty()) {
                    out.errorMessage = 'No order found with number ' + inp.orderNumber;
                } else {
                    Order__c order = orders[0];
                    out.status = order.Status__c;
                    out.estimatedDelivery = order.Estimated_Delivery__c != null
                        ? order.Estimated_Delivery__c.format()
                        : 'Not yet available';
                    out.trackingUrl = order.Tracking_URL__c;
                }

            } catch (Exception e) {
                out.errorMessage = 'Unable to retrieve order: ' + e.getMessage();
                System.debug(LoggingLevel.ERROR, 'GetOrderStatus error: ' + e.getMessage());
            }

            outputs.add(out);
        }

        return outputs;
    }
}
warning

Write great descriptions: The description on @InvocableMethod and each @InvocableVariable is read by the LLM to understand when and how to call your action. Treat them like API documentation — be precise about what each field means and when the action should be used.

Flow Actions

Auto-launched Flows can also be surfaced as Agentforce actions — no Apex required. This is ideal for admins or when the logic already exists in Flow. Mark the Flow's input/output variables as Available for Input and Available for Output to expose them to the agent.

Flow Variable Configuration Checklist
// In Flow Builder, for each variable you want the agent to use:

// INPUT variables (agent provides values TO the flow):
// ✅ Data Type: Text, Number, Boolean, Record, etc.
// ✅ "Available for Input" = true
// ✅ Description filled in (the LLM reads this)

// OUTPUT variables (flow returns values TO the agent):
// ✅ "Available for Output" = true
// ✅ Description filled in

// Flow-level settings:
// ✅ Flow Type: Auto-launched Flow (No Trigger)
// ✅ API Name is meaningful (shown in Agent Builder)
// ✅ Description explains when to use this flow

// In Agent Builder:
// Setup → Agents → [Agent] → Topics → [Topic] → Actions → Add Action
// Filter by "Flow" → select your Auto-launched Flow
// The LLM will map conversation context to flow variables automatically

Prompt Templates

Prompt Templates let you define reusable, data-merged prompts that the agent (or your own Apex/Flow) can invoke. They support merge fields from any Salesforce object and can be versioned and shared across agents.

Apex — Invoking a Prompt Template
import ConnectApi.EinsteinLLM;
import ConnectApi.EinsteinPromptTemplateGenerationsInput;
import ConnectApi.EinsteinPromptTemplateGenerationsRepresentation;

public class PromptTemplateService {

    public static String generateCaseEmail(Id caseId) {
        ConnectApi.EinsteinPromptTemplateGenerationsInput input =
            new ConnectApi.EinsteinPromptTemplateGenerationsInput();

        // Reference the template by its API name
        input.promptTemplateName = 'Case_Resolution_Email';

        // Provide the record context for merge fields
        input.inputParams = new Map<String, ConnectApi.WrappedValue>{
            'Input:CaseId' => ConnectApi.EinsteinLLM.wrap(caseId)
        };

        input.isPreview = false;

        ConnectApi.EinsteinPromptTemplateGenerationsRepresentation result =
            ConnectApi.EinsteinLLM.generateMessagesForPromptTemplate(input);

        return result.generations[0].text;
    }
}

Agent Builder: Step-by-Step

Agentforce agents are created and configured in Setup → Agents. Here's the end-to-end process for standing up a new agent.

1
Create the Agent

Setup → Agents → New Agent. Choose a type (Service, Sales, Custom), give it a Name and a Role Description. The role description sets the agent's personality and overall scope — e.g., "You are a helpful service agent for Acme Corp. You help customers with orders, returns, and account questions."

2
Add Topics

Inside the agent, go to Topics tab → New Topic. Write a descriptive Scope field — this is the most important configuration you'll do. Add actions to each topic. Start with 3–5 focused topics rather than one massive topic.

3
Configure Actions

Actions → Add Action → select Apex, Flow, or API. Fill in the Action Description (used by LLM), map input/output variables, and set confirmation behavior — some actions should ask the user before executing (e.g., canceling an order).

4
Test in Agent Builder

Use the built-in conversation simulator in Agent Builder. Type test messages that match each topic's expected triggers. Check which topic and action the agent selected — use the Reasoning Trace to debug unexpected behavior.

5
Activate & Deploy

Activate the agent and assign it to a channel — Service Cloud Messaging, a website bot widget, Slack, or a custom channel via API. Set guardrails (out-of-scope message handling) before going live.

Testing & Debugging Agents

Agent behavior depends on LLM reasoning, which means deterministic unit tests alone aren't sufficient. Use a layered testing strategy.

Apex — Testing Invocable Action Logic
// Unit test the Apex action independently of the agent runtime
@isTest
private class GetOrderStatusActionTest {

    @TestSetup
    static void makeData() {
        Order__c order = new Order__c(
            Order_Number__c = 'ORD-99999',
            Status__c = 'Shipped',
            Estimated_Delivery__c = Date.today().addDays(3),
            Tracking_URL__c = 'https://track.example.com/ORD-99999'
        );
        insert order;
    }

    @isTest
    static void validOrder_returnsStatusAndTracking() {
        GetOrderStatusAction.ActionInput inp = new GetOrderStatusAction.ActionInput();
        inp.orderNumber = 'ORD-99999';

        Test.startTest();
        List<GetOrderStatusAction.ActionOutput> results =
            GetOrderStatusAction.execute(new List<GetOrderStatusAction.ActionInput>{ inp });
        Test.stopTest();

        System.assertEquals(1, results.size(), 'Should return one result');
        System.assertEquals('Shipped', results[0].status, 'Status should be Shipped');
        System.assertNotEquals(null, results[0].trackingUrl, 'Tracking URL should be present');
        System.assertEquals(null, results[0].errorMessage, 'No error expected');
    }

    @isTest
    static void invalidOrder_returnsErrorMessage() {
        GetOrderStatusAction.ActionInput inp = new GetOrderStatusAction.ActionInput();
        inp.orderNumber = 'ORD-DOESNOTEXIST';

        Test.startTest();
        List<GetOrderStatusAction.ActionOutput> results =
            GetOrderStatusAction.execute(new List<GetOrderStatusAction.ActionInput>{ inp });
        Test.stopTest();

        System.assertNotEquals(null, results[0].errorMessage, 'Should return an error message');
        System.assertEquals(null, results[0].status, 'Status should be null on error');
    }
}

Debugging with Reasoning Trace

Every agent conversation in the simulator exposes a Reasoning Trace — a step-by-step log of what the LLM decided. Use it to diagnose:

search
Wrong topic selected — Your topic descriptions are too similar or ambiguous. Make them more distinct and add "Do NOT use for..." clauses.
bolt
Wrong action selected — Improve the description field on your @InvocableMethod. Be explicit about the trigger condition.
input
Incorrect input mapping — Improve the description on your @InvocableVariable fields. Include format hints like "Order number in format ORD-XXXXX".
error
Action fails at runtime — The trace shows the exception. Check your Apex error handling — always return a graceful errorMessage instead of throwing exceptions the agent can't handle.

Agentforce vs Einstein Bots

If you've used Einstein Bots before, here's how Agentforce differs — and when to use each.

Feature Agentforce Einstein Bots
Decision Logic LLM-driven (natural language intent classification) Rule/dialog-tree driven (explicit if/then flows)
Configuration Topics + Actions + natural language descriptions Dialog nodes, intents, entities, buttons
Flexibility High — handles open-ended, varied phrasing naturally Lower — requires explicit intent training or buttons
Predictability Lower — LLM decisions vary; needs prompt tuning Higher — deterministic dialog flows
Best For Open-ended conversations, complex multi-step tasks Highly structured workflows with known paths
Grounding Data Cloud, Knowledge, CRM context, retrieval CRM data via Apex/Flow actions
Required Skill Prompt engineering + Apex/Flow Dialog design + Apex/Flow

Best Practices

verified

Design checklist for production-ready Agentforce agents:

✅ Keep topics narrow and non-overlapping — one clear job per topic

✅ Write action descriptions like API docs — who uses it, when, and what each field means

✅ Always return a graceful errorMessage from Apex actions — never let unhandled exceptions bubble to the LLM

✅ Use confirmation prompts for destructive actions (cancel, delete, update)

✅ Unit test every Apex action independently before wiring to the agent

✅ Add an "Out of Scope" system message telling the agent how to handle irrelevant requests

✅ Use Named Credentials for any external API calls within actions

✅ Monitor conversations with Einstein Conversation Insights after launch

Topics per agent (no hard limit)
20
Max actions per topic (recommended)
5
Max reasoning hops per turn
100
SOQL / DML limits (standard Apex)