13.3 Apex Actions for Flow, LWC, and Agentforce

Key Takeaways

  • The User Interface objective requires implementing Apex that works with page components including Lightning Web Components, Flow, and Agentforce, which are three consumers reached through two annotations
  • @AuraEnabled exposes Apex to LWC and Aura, while @InvocableMethod exposes the same class to Flow and to Agentforce Builder as a custom agent action
  • An invocable method must be public or global and static, take exactly one List parameter, and return void or a List; only one method per Apex class may carry @InvocableMethod
  • Complex inputs and outputs use inner wrapper classes whose fields are annotated @InvocableVariable, because multi-argument signatures are not allowed
  • Agentforce reads the label and description on @InvocableMethod and @InvocableVariable to choose the action and fill its parameters, so vague description text is a functional defect
Last updated: August 2026

13.3 Apex Actions for Flow, LWC, and Agentforce

Quick Answer: Apex reaches declarative and AI surfaces through annotations. @AuraEnabled exposes a method to LWC and Aura. @InvocableMethod exposes it to Flow and makes it selectable in Agentforce Builder as a custom agent action. An invocable method must be public/global, static, take a List, and return a List, and only one method per class may carry the annotation. Complex inputs and outputs use wrapper classes whose fields are marked @InvocableVariable. Your label and description text is not decoration—Agentforce's reasoning engine reads it to decide when to call your action.

The User Interface domain objective reads: "Implement Apex to work with various types of page components, including Lightning Web Components, Flow, and Agentforce." Section 12.4 covered the LWC half in depth. This section closes the other two and shows why they share one mechanism.

Three Bridges Out of Apex

ConsumerAnnotationShape
LWC / Aura@AuraEnabled (add cacheable=true for @wire reads)Ordinary signature; the value returns to JavaScript
Flow (screen, record-triggered, scheduled)@InvocableMethodList in, List out
Agentforce custom agent action@InvocableMethod — the same method, surfaced in Agentforce BuilderList in, List out

The important insight for the exam: Flow and Agentforce share one annotation. There is no separate "agent" annotation to learn. Publish an invocable method and it becomes available both on the Flow canvas and in the agent-action catalog.

The Invocable Method Contract

public with sharing class EscalateCaseAction {

    public class Request {
        @InvocableVariable(label='Case ID' description='The Case to escalate' required=true)
        public Id caseId;

        @InvocableVariable(label='Reason' description='Why the case is being escalated')
        public String reason;
    }

    public class Result {
        @InvocableVariable(label='Escalated' description='True when the case was escalated')
        public Boolean escalated;

        @InvocableVariable(label='Message' description='Human-readable outcome for the user or agent')
        public String message;
    }

    @InvocableMethod(
        label='Escalate Case'
        description='Escalates a support case and records the escalation reason on the case record.'
        category='Support'
    )
    public static List<Result> escalate(List<Request> requests) {
        Set<Id> caseIds = new Set<Id>();
        for (Request r : requests) {
            caseIds.add(r.caseId);
        }
        Map<Id, Case> cases = new Map<Id, Case>(
            [SELECT Id, Status, Escalation_Reason__c FROM Case WHERE Id IN :caseIds]
        );

        List<Result> results = new List<Result>();
        List<Case> toUpdate = new List<Case>();
        for (Request r : requests) {
            Case c = cases.get(r.caseId);
            Result res = new Result();
            if (c == null) {
                res.escalated = false;
                res.message = 'Case not found or not accessible.';
            } else {
                c.Status = 'Escalated';
                c.Escalation_Reason__c = r.reason;
                toUpdate.add(c);
                res.escalated = true;
                res.message = 'Case escalated.';
            }
            results.add(res);
        }

        if (!toUpdate.isEmpty()) {
            update toUpdate;
        }
        return results;
    }
}

Rules the exam tests:

RuleDetail
Access modifierpublic or global
StaticInstance methods cannot be invocable
One per classOnly one method in a class may carry @InvocableMethod
ParameterExactly one parameter, and it must be a List
Returnvoid or a List; a returned list aligns positionally with the input list
Complex dataUse an inner class with @InvocableVariable fields; a multi-argument signature is not allowed
CalloutsAdd callout=true to the annotation when the method performs an HTTP callout

Note the bulk signature. Even when Agentforce sends a single request per conversational turn, and even when a screen Flow calls it once, the platform hands you a list—because a record-triggered Flow processing 200 records will. The bulkification discipline from Chapter 8 applies unchanged: collect ids, query once, DML once. The example above does exactly that, and it is the difference between an action that survives a data load and one that throws a LimitException.

Why label and description Matter Far More for Agentforce

For Flow, label and description are convenience text an admin reads on the canvas. For Agentforce, they are functional. The agent's reasoning engine reads the action's label, its description, and the label and description on every @InvocableVariable to decide:

  1. Whether this action is the right one for what the user asked
  2. Which value to put in each input parameter

Consequences you should be able to state on an exam item:

  • A description of "Handles cases" gives the agent nothing to discriminate on—it may fire your action for unrelated requests, or skip it when it should run.
  • An input labelled "input1" with no description leaves the agent guessing what to pass into it.
  • Two actions with near-identical descriptions make selection unreliable.

Rule: write the description as if for a competent colleague who cannot read the method body—state what the action does, what it needs, and what it returns. Keep the text in the Apex annotation and in the action configuration in sync, because drift between them is a real maintenance defect.

Security Does Not Change at the Boundary

An invocable method is an entry point, and entry points are exactly where the Chapter 10 rules bite:

  • Declare with sharing on a class that an agent or a screen Flow calls on behalf of a user. Apex runs in system mode for CRUD and FLS by default, and an agent action is not a privileged context that exempts you.
  • Enforce field access with USER_MODE, WITH SECURITY_ENFORCED, or Security.stripInaccessible when the running user's permissions should govern the result.
  • Never concatenate an agent-supplied or Flow-supplied string into Database.querybind it. Input reaching an agent action is user-influenced text and must be treated as untrusted.
  • Return a safe message, not a raw exception carrying internal details, because the agent may surface your string to the end user verbatim.

Choosing the Bridge

RequirementAnswer
A Lightning Web Component needs server data on load@AuraEnabled(cacheable=true) with @wire
An LWC button performs a write@AuraEnabled imperative call
An admin must reorder the logic without a developerPut the Apex behind @InvocableMethod and let Flow orchestrate
A conversational agent must take a real action on a record@InvocableMethod published as a custom agent action
The same logic must serve a screen Flow and an agentOne invocable method serves both
The logic must run on every save regardless of UIA trigger, not an invocable action

Exam Checklist

  • @AuraEnabled goes to LWC and Aura; @InvocableMethod goes to Flow and Agentforce
  • public/global, static, one per class, List in / List out
  • Complex parameters use inner classes with @InvocableVariable
  • callout=true when the action performs an HTTP callout
  • Descriptions drive agent action selection—vague text is a functional defect, not a style nit
  • Sharing, CRUD/FLS, and bind variables apply at the entry point like anywhere else

Bottom line: one annotation, @InvocableMethod, is how Apex becomes something an admin can drag onto a Flow canvas and something an Agentforce agent can decide to call on its own. Get the method shape right, write descriptions that actually describe, and keep the entry point bulk-safe and secure.

Test Your Knowledge

A developer needs one Apex method that a screen Flow can call and that also appears as a custom action in Agentforce Builder. What is the correct approach?

A
B
C
D
Test Your Knowledge

An Apex agent action is defined with the description "Handles records" and an input variable labelled "input1" with no description. The agent calls the action at the wrong times and passes the wrong values. What is the root cause?

A
B
C
D
Test Your Knowledge

Which signature is valid for a method intended to be exposed to Flow and Agentforce?

A
B
C
D