Study guide

13.3 Apex Actions for Flow, LWC, and Agentforce

Salesforce Certified Platform Developer I Exam

Track your progress as you read

Finished sections get a check mark.

1 Introduction & Exam Overview

1.1 Current Exam Facts 1.2 Blueprint Weights & Study Strategy

2 Platform Fundamentals

2.1 Multi-Tenant Architecture & Shared Resources 2.2 MVC Mapping on the Lightning Platform 2.3 Declarative vs Programmatic Decisions 2.4 Agentforce for Developers: Use Cases & Limitations

3 Data Modeling & Schema

3.1 Objects, Fields & Schema Design 3.2 Relationship Types & Implications 3.3 Schema Design Impact on Apex 3.4 Data Import & Export for Development

4 Platform Data Features

4.1 Formula Fields & Roll-Up Summaries 4.2 Core CRM Objects & Standard Schema 4.3 AppExchange Extensions & Platform Boundaries

5 Declarative Process Automation

5.1 Record-Triggered Flows & Declarative Automation 5.2 Approval Processes & Business Rules 5.3 When to Use Apex vs Declarative Tools

6 Apex Language Basics

6.1 Variables, Constants & Apex Data Types 6.2 Lists, Sets & Maps 6.3 Control Flow & Exception Handling 6.4 Classes, Interfaces & OOP Patterns

7 SOQL, SOSL & DML

7.1 SOQL Query Fundamentals 7.2 SOSL Search Fundamentals 7.3 DML Operations & Bulkification 7.4 Governor Limits & Transaction Boundaries

8 Apex Triggers & Order of Execution

8.1 Trigger Structure & Context Variables 8.2 Bulk Trigger Patterns & Best Practices 8.3 Save Order of Execution 8.4 Recursion, Cascading & Transaction Control

9 Asynchronous Apex

9.1 @future Methods 9.2 Queueable Apex 9.3 Batch Apex 9.4 Schedulable Apex & Job Orchestration

10 Security, Events & Schema Access

10.1 Sharing, FLS, CRUD & Injection Prevention 10.2 Platform Events Publish & Subscribe 10.3 Programmatic Schema Access (Describe)

11 Visualforce

11.1 Visualforce Pages & Markup 11.2 Standard, Custom Controllers & Extensions 11.3 Visualforce in Lightning Experience

12 Lightning Components

12.1 Lightning Component Framework Benefits 12.2 Aura Component Structure & Resources 12.3 Lightning Web Components Fundamentals 12.4 LWC Data Access: Wire, Imperative & Events

13 UI Composition & Apex Integration Patterns

13.1 Composing UI in Lightning Apps 13.2 UI Security, Performance & Accessibility Patterns 13.3 Apex Actions for Flow, LWC, and Agentforce

14 Apex Testing

14.1 Testing Framework & Coverage Requirements 14.2 Writing Unit Tests for Triggers & Classes 14.3 Test Data Strategies & Isolation 14.4 Executing Tests & Execute Anonymous Differences

15 Debugging & Developer Tools

15.1 Debug Logs & Monitoring 15.2 Developer Console, CLI, VS Code & Workbench 15.3 Sandboxes, Scratch Orgs & Environment Strategy

16 Deployment & Release

16.1 Change Sets & Metadata Deployment 16.2 Unlocked Packages, Metadata API & Salesforce DX 16.3 Release Readiness & Credential Maintenance

13.3 Apex Actions for Flow, LWC, and Agentforce

Key Takeaways Explain This Topic AI

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

Consumer Annotation Shape

LWC / Aura @AuraEnabled (add cacheable=true for @wire reads) Ordinary signature; the value returns to JavaScript

Flow (screen, record-triggered, scheduled) @InvocableMethod List in, List out

Agentforce custom agent action @InvocableMethod — the same method, surfaced in Agentforce Builder List 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:

  • Rule Detail
  • Access modifier public or global
  • Static Instance methods cannot be invocable
  • One per class Only one method in a class may carry @InvocableMethod
  • Parameter Exactly one parameter, and it must be a List
  • Return void or a List ; a returned list aligns positionally with the input list
  • Complex data Use an inner class with @InvocableVariable fields; a multi-argument signature is not allowed
  • Callouts Add 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:

  • Whether this action is the right one for what the user asked
  • 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.query — bind 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

  • Requirement Answer
  • 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 developer Put 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 agent One invocable method serves both
  • The logic must run on every save regardless of UI A 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.