Add Apex Merge Fields to a Sales Email Prompt Template
Create an example sales email prompt template that uses Apex.
Required Editions
| Available in: Lightning Experience |
| Available in: Enterprise, Performance, and Unlimited Editions with the Einstein for Platform, or Einstein or Agentforce for Sales or Service add-on, or Agentforce Foundations |
| User Permissions Needed | |
|---|---|
| To create and manage prompt templates in Prompt Builder: | Prompt Template Manager permission set
OR Customize Application permission set |
Say you’re a Salesforce admin, and your sales team requests an easier way to send emails to contacts about nearby Marketing events.
You create an email prompt template that launches an Apex class to get Marketing events in the same city and state as your contact. The Apex class gets a list of events and their locations for the LLM.
Here’s the Apex class that we access as a resource in a prompt template.
public class ContactEventsPrompt {
@InvocableMethod(label='Contact Events'
description='Find Events for a Contact'
CapabilityType='PromptTemplateType://einstein_gpt__salesEmail')
public static List<Response> getContactsPrompt(List<Request> requests) {
// validate the expected number of requests as an input
if (requests.size() != 1)
throw new ListException('The requests list must contain one entry only');
Contact c = requests[0].Recipient;
// Protect against SOQL Injection
string searchCity = '%' + c.MailingCity + '%';
string searchState = '%' + c.MailingState + '%';
List<Event> events =
[SELECT Id, Subject, Description, Location, StartDateTime
FROM Event
WHERE IsArchived = false AND Location LIKE :searchCity
AND Location LIKE :searchState WITH USER_MODE];
string responseData = '';
if(events.isEmpty()) {
responseData = 'No upcoming Marketing events near you.';
} else {
for(Event e : events) {
responseData += 'Event details: ';
responseData += e.Subject;
responseData += ', ';
responseData += e.Description;
responseData += ', ';
responseData += e.Location;
responseData += '/nStart Time: ';
responseData += e.StartDateTime.format();
responseData += '.';
}
}
List<Response> responses = new List<Response>();
Response res = new Response();
res.Prompt = responseData;
responses.add(res);
return responses;
}
public class Request {
@InvocableVariable(required=true)
public User Sender;
@InvocableVariable(required=true)
public Contact Recipient;
}
public class Response {
@InvocableVariable
public String Prompt;
}
}The requirements for the Apex class are explained in Grounding with Apex Merge Fields.
Test coverage is important so let's add a test class. The test class simulates data sent from Prompt Builder. Two test cases are provided: one for when events are found, and one for when there are no events.
@IsTest
public class ContactEventsPrompt_Test {
@IsTest
public static void noEventsForContactResponse() {
List<ContactEventsPrompt.Request> requestsInput
= new List<ContactEventsPrompt.Request>();
ContactEventsPrompt.Request request
= new ContactEventsPrompt.Request();
request.Recipient = new Contact();
requestsInput.add(request);
List<ContactEventsPrompt.Response> responses =
ContactEventsPrompt.getContactsPrompt(requestsInput);
Assert.areEqual(1, responses.size());
ContactEventsPrompt.Response response = responses[0];
Assert.areEqual('No upcoming Marketing events near you.',
response.Prompt);
}
@IsTest
public static void findMatchingEventsForContact() {
Contact c = new Contact(LastName='TestContact',
MailingCity='San Francisco', MailingState='CA');
insert c;
Event e = new Event(Subject='Test Event', Description='Big Event',
Location='415 Mission St, San Francisco, CA 94105, USA',
StartDateTime=DateTime.newInstance(2023,09,28),
DurationInMinutes=5 );
insert e;
List<ContactEventsPrompt.Request> requestsInput
= new List<ContactEventsPrompt.Request>();
ContactEventsPrompt.Request request
= new ContactEventsPrompt.Request();
request.Recipient = c;
requestsInput.add(request);
Test.startTest();
List<ContactEventsPrompt.Response> responses =
ContactEventsPrompt.getContactsPrompt(requestsInput);
Test.stopTest();
Assert.areEqual(1, responses.size());
ContactEventsPrompt.Response response = responses[0];
Assert.areEqual(formatEventString(e), response.Prompt);
}
private static String formatEventString(Event event) {
String formattedEventString = 'Event details: ';
formattedEventString += event.Subject;
formattedEventString += ', ';
formattedEventString += event.Description;
formattedEventString += ', ';
formattedEventString += event.Location;
formattedEventString += '/nStart Time: ';
formattedEventString += event.StartDateTime.format();
formattedEventString += '.';
return formattedEventString;
}
}Now that the Apex class is ready, let’s call it from Prompt Builder.
In Prompt Builder, create a new prompt template.
- In the Prompt Template Type dropdown, select Sales Email.
- For the Prompt Template Name, enter Apex: Nearby Events Marketing Email.
- For the Recipient Type, select Contact.
- Leave the Description field blank.
- Click Create, and you’re redirected to the Prompt Template Workspace.
- In the Example Prompt Template Library, find the sales email prompt template “Draft an email for a contact about regional marketing events.” Copy and paste this template into the Prompt Template Workspace.
- Before you can run this template in Prompt Builder, in the Prompt section, click Insert Resource. The search field appears the first time you click this option.
-
Use the search bar to replace the placeholders with merge fields.
-
In the Prompt Template Workspace, delete the
<Get_Events_Near_Contact__Prompt__Flow>placeholder. - In the Prompt section, click the Resource search bar, and select Apex.
-
Select Contact Events to add the
ContactEventsPromptApex class to your template. Contact Events is the label attribute that you set in the@InvocableMethodannotation in theContactEventsPromptApex class.The Apex class is inserted into the prompt template asApex:ContactEventsPrompt. -
Delete the
<sender.Name__Merge_Field>placeholder. - Click the Resource search bar, and select Sender | Full Name .
-
Delete the
<recipient.Name__Merge_Field>placeholder. - Click the Resource search bar, and select Recipient | Full Name.
-
Delete the
<recipient.Company__Merge_Field>placeholder. - Click the Resource search bar, and select Current Organization | Name.
-
In the Prompt Template Workspace, delete the

