Using Prompt Templates in LWC & Apex | Step-by-Step Guide with Code #Salesforce #Agentforce #Trailhead

 


With the rise of Agentforce and Einstein 1, Salesforce developers now have access to powerful AI capabilities directly from Apex, Flows, and Lightning Web Components. One of the most flexible and scalable ways to use AI in Salesforce is through Prompt Templates.

In this post, I’ll show you how to invoke Prompt Templates programmatically using both Apex and Lightning Web Components (LWC)—a pattern that unlocks endless AI-assisted automation and UI use cases inside your org.

What Are Prompt Templates?

Prompt Templates let you standardize:

  • System instructions
  • Tone
  • Context variables
  • Guardrails
  • Expected output format

They are reusable and can be called from:

  • Apex
  • Flow
  • Lightning Web Components
  • Agentforce Actions
  • External integrations

This approach ensures consistency when multiple components use the same AI logic.

Use Case: Generating AI Responses Dynamically from UI or Backend

Imagine you want to:

  • Generate article summaries
  • Rewrite product descriptions
  • Create chat-like AI responses inside LWC
  • Build a custom AI form-filling or recommendation interface

Prompt Templates + Apex/LWC make this seamless.


Step 1: Create a Prompt Template in Prompt Builder

Navigate to:

Setup → Einstein → Prompt Builder → New Prompt Template

Example configuration:

  • Name: Adventure Promotion
  • Type: Flex Template
  • Input Variables:

    • In my case it's the Id value from Adventure_Master__c object.

Step 2: Invoke Prompt Template Using Apex

Here’s a simple example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public with sharing class SocialMediaPostsController {
    @AuraEnabled
    public static String generateSocialMediaPosts(String adventureActivityId) {
        // Create inputs
        Map<String, String> adventureActivity = new Map<String, String>();
        adventureActivity.put('id', adventureActivityId);
        ConnectApi.WrappedValue adventureActivityValue = new ConnectApi.WrappedValue();
        adventureActivityValue.value = adventureActivity;
        Map<String, ConnectApi.WrappedValue> inputParams = new Map<String, ConnectApi.WrappedValue>();
        inputParams.put('Input:Adventure_Activity', adventureActivityValue);

        // Configure invocation parameters
        ConnectApi.EinsteinPromptTemplateGenerationsInput executeTemplateInput = new ConnectApi.EinsteinPromptTemplateGenerationsInput();
        executeTemplateInput.additionalConfig = new ConnectApi.EinsteinLlmAdditionalConfigInput();
        executeTemplateInput.additionalConfig.applicationName = 'PromptBuilderPreview';
        executeTemplateInput.isPreview = false;
        executeTemplateInput.inputParams = inputParams;

        try {
            // Call the service
            ConnectApi.EinsteinPromptTemplateGenerationsRepresentation generationsOutput = ConnectApi.EinsteinLLM.generateMessagesForPromptTemplate(
                'Adventure_Promotion',
                executeTemplateInput
            );
            ConnectApi.EinsteinLLMGenerationItemOutput response = generationsOutput.generations[0];
            return response.text;
        } catch (Exception e) {
            System.debug(e.getMessage());
            throw e;
        }
    }
}


Step 3: Calling the Apex Method from a Lightning Web Component

Your LWC can now call Apex and display the AI-generated response in real time.

LWC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<template>
    <lightning-card title="Adventure Social Media Posts" icon-name="utility:socialshare">
        <div class="slds-p-around_small">
            <lightning-button
                variant="brand"
                label="Generate Social Media Post"
                title="Generate Social Media Post"
                onclick={handleGeneratePosts}
                class="slds-m-bottom_small"
            ></lightning-button>

            <template if:true={showSpinner}>
                <div class="slds-is-relative slds-m-vertical_medium">
                    <lightning-spinner alternative-text="Generating posts..." size="medium"></lightning-spinner>
                </div>
            </template>

            <template if:true={error}>
                <div class="slds-text-color_error slds-m-bottom_medium">
                    Error: {error.message}
                </div>
            </template>

            <template if:false={showSpinner}>
                <div class="slds-grid slds-gutters slds-wrap">
                    <div class="slds-col slds-size_1-of-1 slds-p-around_small">
                        <lightning-textarea
                            label="LinkedIn Post"
                            value={linkedinPost}
                            readonly
                            rows="10"
                            class="post-textarea"
                        >
                        </lightning-textarea>
                    </div>
                    <div class="slds-col slds-size_1-of-1 slds-p-around_small">
                        <lightning-textarea
                            label="Twitter Post"
                            value={twitterPost}
                            readonly
                            rows="10"
                            class="post-textarea"
                        >
                        </lightning-textarea>
                    </div>
                    <div class="slds-col slds-size_1-of-1 slds-p-around_small">
                        <lightning-textarea
                            label="Slack Post"
                            value={slackPost}
                            readonly
                            rows="10"
                            class="post-textarea"
                        >
                        </lightning-textarea>
                    </div>
                </div>
            </template>
        </div>
    </lightning-card>
</template>


JS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import { LightningElement, api } from 'lwc';
import generateSocialMediaPosts from '@salesforce/apex/SocialMediaPostsController.generateSocialMediaPosts';

export default class AdventureSocialLWC extends LightningElement {
    @api recordId;
    
    linkedinPost = '';
    twitterPost = '';
    slackPost = '';
    error;
    showSpinner = false;

    async handleGeneratePosts() {
        this.showSpinner = true;
        this.error = undefined;
        this.linkedinPost = '';
        this.twitterPost = '';
        this.slackPost = '';

        try {
            const posts = await generateSocialMediaPosts({
                adventureActivityId: this.recordId
            });
            
            // Try to parse as JSON first
            try {
                const parsedPosts = JSON.parse(posts);
                this.linkedinPost = parsedPosts.linkedin || '';
                this.twitterPost = parsedPosts.twitter || '';
                this.slackPost = parsedPosts.slack || '';
            } catch (parseError) {
                // If parsing fails, treat the entire response as a single post
                // and distribute it among the platforms (this is a fallback)
                this.linkedinPost = posts;
                this.twitterPost = posts;
                this.slackPost = posts;
            }
        } catch (error) {
            this.error = error;
            console.error('Error generating social media posts:', JSON.stringify(error));
        } finally {
            this.showSpinner = false;
        }
    }
}


js-meta.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>65.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Adventure Social LWC</masterLabel>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage">
            <objects>
                <object>Adventure_Master__c</object>
            </objects>
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
                <supportedFormFactor type="Small" />
            </supportedFormFactors>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>


Invoking Prompt Templates directly from Apex and LWC opens the door to true AI-powered experiences inside custom Salesforce apps.

You can use this pattern for:

  • Knowledge assistants
  • Dynamic form builders
  • Text generation tools
  • Internal copilots
  • Guided selling panels
  • Customer service helpers

…and anything else that needs smart, controlled AI outputs inside Salesforce UI.


Output



Watch Complete Video Tutorial Below

 If you have any question please leave a comment below.

If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !

Thanks

Post a Comment

0 Comments