Learn how to invoke Salesforce Prompt Templates programmatically from Apex and Lightning Web Components to deliver consistent AI-driven experiences across your org.
Introduction
With Agentforce and Einstein 1, Salesforce makes powerful AI available inside Apex, Flows, and Lightning Web Components (LWC). Prompt Templates provide a scalable, centralized way to standardize AI system instructions, tone, context variables, guardrails and expected output formats. Calling Prompt Templates from Apex and LWC unlocks dynamic AI features—summaries, rewrites, chat responses, and more—inside your Salesforce UI.
What are Prompt Templates?
Prompt Templates let admins and developers define reusable AI prompts in Prompt Builder. Instead of duplicating instructions across components, you store the intended behavior and call the template with runtime inputs. Common uses include:
- System instructions and guardrails
- Tone and formatting rules
- Context variables passed from records or UI
- Consistent output formats (JSON, bullet lists, paragraphs)
Why this pattern matters
Maintaining templates in Prompt Builder centralizes AI behavior, makes testing easier, and ensures consistent outputs regardless of where the template is invoked (Apex, Flow, LWC, or Agentforce Actions).
Use cases
- Generate article summaries or product descriptions
- Create chat-style AI responses embedded in LWC
- Drive intelligent, context-aware form filling
- Build internal copilots for sales and service
Step 1: Create a Prompt Template in Prompt Builder
In Setup, open Einstein → Prompt Builder and create a new Prompt Template. Example configuration:
- Name: Adventure Promotion
- Type: Flex Template
- Input Variables: pass the Adventure_Master__c record Id or object as needed
Step 2: Invoke a Prompt Template from Apex
Use the ConnectApi EinsteinLLM methods to call a template and pass structured inputs. Below is a sample Apex controller that requests social media posts from the “Adventure_Promotion” template:
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: Call Apex from a Lightning Web Component
From LWC, call the Apex method and render the AI output in the UI. The LWC below triggers the Apex controller and displays LinkedIn/Twitter/Slack variations. It attempts to parse JSON returned from the template and falls back to a single text response if parsing fails.
<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>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;
}
}
}Best practices
- Design prompt templates with clear system instructions and expected output shapes (e.g., JSON) so Apex/LWC can parse reliably.
- Use preview and testing modes in Prompt Builder before enabling production calls.
- Handle timeouts, exceptions, and malformed responses gracefully in Apex and LWC.
- Control costs by caching or limiting calls for non-critical use cases.
Conclusion
Invoking Prompt Templates directly from Apex and LWC is a practical pattern to embed controlled, consistent AI inside Salesforce applications. It enables knowledge assistants, dynamic form builders, internal copilots, and more—while keeping AI behavior centralized and maintainable.
Why this matters for Salesforce teams: admins can manage prompt behavior centrally in Prompt Builder, developers can integrate AI with familiar Apex and LWC patterns, and business users get predictable, useful AI outputs that improve productivity.




Leave a Reply