Loading
Salesforce now sends email only from verified domains. Read More
Agentforce and Einstein Generative AI
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          Add Apex Merge Fields to a Sales Email Prompt Template

          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

          • Manage Prompt Templates
          • Execute Prompt Templates

          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.

          1. In the Prompt Template Type dropdown, select Sales Email.
          2. For the Prompt Template Name, enter Apex: Nearby Events Marketing Email.
          3. For the Recipient Type, select Contact.
          4. Leave the Description field blank.
          5. Click Create, and you’re redirected to the Prompt Template Workspace.
          6. 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.
          7. 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.
          8. Use the search bar to replace the placeholders with merge fields.
            1. In the Prompt Template Workspace, delete the <Get_Events_Near_Contact__Prompt__Flow> placeholder.
            2. In the Prompt section, click the Resource search bar, and select Apex.
            3. Select Contact Events to add the ContactEventsPrompt Apex class to your template. Contact Events is the label attribute that you set in the @InvocableMethod annotation in the ContactEventsPrompt Apex class.
              The Apex class is inserted into the prompt template asApex:ContactEventsPrompt.
            4. Delete the <sender.Name__Merge_Field> placeholder.
            5. Click the Resource search bar, and select Sender | Full Name .
            6. Delete the <recipient.Name__Merge_Field> placeholder.
            7. Click the Resource search bar, and select Recipient | Full Name.
            8. Delete the <recipient.Company__Merge_Field> placeholder.
            9. Click the Resource search bar, and select Current Organization | Name.
           
          Loading
          Salesforce Help | Article