
We can create custom Agentforce Agent actions using the Apex Rest Resource apex classes. This helps in reusing the existing Apex Development for the Agentforce Agent implementation.
Steps:
1. Install Salesforce Agentforce for Developers extension in your VS Code.
2. Run the following command.
sf project convert source-behavior -b decomposeExternalServiceRegistrationBeta

This helps in generating OpenAPI v3 specification in a YAML editor in the VS Code IDE.
3. Open the sfdx-project.json file in the VS Code. Confirm the sourceBehaviorOptions.

4. Execute the following.
SFDX: Refresh SObjects Definitions

Select All SObjects option.

5. Create an Apex class with RestResource annotation. The class should have one of the following sharing modifiers.
- with sharing
- without sharing
- inherited
The Apex Class should have at least one method with the following annotation.
- @HttpGet
- @HttpPost
- @HttpPut
- @HttpPatch
- @HttpDelete
Sample Apex Class:
@RestResource( urlMapping='/AccountManagement/*' )
global with sharing class AccountRESTController {
@HttpGet
global static Account doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String accountId = req.requestURI.substring(
req.requestURI.lastIndexOf('/') + 1
);
Account result = [
SELECT Id, Name, Phone, Website
FROM Account
WHERE Id = :accountId
];
return result;
}
@HttpPost
global static String doPost(
String name,
String phone,
String website
) {
Account account = new Account();
account.Name = name;
account.phone = phone;
account.website = website;
insert account;
return account.Id;
}
@HttpDelete
global static void doDelete() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String accountId = req.requestURI.substring(
req.requestURI.lastIndexOf('/') + 1
);
Account account = [
SELECT Id
FROM Account
WHERE Id = :accountId
];
delete account;
}
}
6. Use the following command.
SFDX: Create OpenAPI Document from this Class (Beta)
Choose the default folder “externalServiceRegistration”.

7. Deploy both the Apex Class and the externalServiceRegistration-meta.xml file created for the Apex Class.
8. Go to API Catalog in Salesforce Setup to verify.

9. You should be able to reference the methods when you create Apex Agent Action.

Another Example:
Apex Class:
@RestResource( urlMapping='/CaseApexAPI/v1/Cases/*' )
global without sharing class CaseRESTAPIController {
@HttpPost
global static String importCase(
String subject,
String description
) {
System.debug( '### importCase ###' );
System.debug( 'subject: ' + subject );
System.debug( 'description: ' + description );
Case objCase = new Case(
Status= 'New',
Origin= 'Web',
Priority= 'Low',
Subject = subject,
Description = description
);
try {
insert objCase;
return 'Case created for you!!!';
} catch ( DMLException e ) {
return e.getMessage();
}
}
}
externalServiceRegistration-meta.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ExternalServiceRegistration xmlns="http://soap.sforce.com/2006/04/metadata">
<description>This is auto-generated OpenAPI v3 spec for CaseRESTAPIController.</description>
<label>CaseRESTAPIController</label>
<schema>openapi: 3.0.0
servers:
- url: /services/apexrest
info:
title: CaseRESTAPIController
version: 1.0.0
description: This is auto-generated OpenAPI v3 spec for CaseRESTAPIController.
paths:
/CaseApexAPI/v1/Cases:
description: Default description for the path.
post:
description: Create Case
operationId: importCase
parameters: []
requestBody:
description: Create Case
required: true
content:
application/json:
schema:
type: object
properties:
subject:
description: Enter the subject
type: string
description:
description: Enter the description
type: string
responses:
'200':
description: Case created
content:
text:
schema:
type: string
</schema>
<schemaType>OpenApi3</schemaType>
<schemaUploadFileExtension>yaml</schemaUploadFileExtension>
<schemaUploadFileName>caserestapicontroller_openapi</schemaUploadFileName>
<status>Complete</status>
<systemVersion>3</systemVersion>
<operations>
<name>importCase</name>
<active>true</active>
</operations>
<registrationProvider>CaseRESTAPIController</registrationProvider>
<registrationProviderType>ApexRest</registrationProviderType>
<namedCredential>null</namedCredential>
</ExternalServiceRegistration>
Use the following help article if you face any issue due to ExternalServiceRegistration.
Reference Article:
https://developer.salesforce.com/docs/einstein/genai/guide/agent-apex.html