Agentforce Script: Rendering Rich Text Area Fields
Agentforce Scripts orchestrate AI interactions, and they can return more than plain text. One of the things they can do, which gets overlooked, is render the contents of a Rich Text Area (RTA) field inside the interaction itself, so an agent or a customer sees formatted content instead of a wall of markup.
What follows is how to display RTA field content from an Agentforce Script: where the data comes from, what the output has to look like, and the parts that bite. It assumes you are a Salesforce developer, architect or administrator already working on an Agentforce implementation.
Understanding Rich Text Area Fields and Agentforce Scripts
Rich Text Area fields store formatted text: bold, italics, bullet points, numbered lists, hyperlinks, even embedded images. Push that through an AI interaction by concatenating the raw HTML and you get a cluttered, unreadable result. Agentforce Scripts give you a structured way to process and present it instead.
Agentforce Scripts are Apex classes that implement specific interfaces, which is how they hook into the AI interaction lifecycle. With RTA fields, the work is in how you retrieve the data and then how you instruct Agentforce to display it. Agentforce typically expects output in a structured format, often JSON, which it then interprets and presents to the end user.
Retrieving Rich Text Area data
First, get the data out of Salesforce, normally with a SOQL query inside your Apex class. Say you have a custom object called Case_Feedback__c with an RTA field named Customer_Comments__c:
List<Case_Feedback__c> feedbackRecords = [SELECT Id, Customer_Comments__c FROM Case_Feedback__c WHERE Id = :recordId LIMIT 1];
if (!feedbackRecords.isEmpty()) {
Case_Feedback__c feedback = feedbackRecords[0];
String richTextContent = feedback.Customer_Comments__c;
// Process richTextContent here
}
A few things about RTA data will catch you out. The content is stored as HTML, so feedback.Customer_Comments__c hands you a string full of markup, and you have to decide whether to display it as-is (which Agentforce may interpret) or parse and sanitize it first. The field can also be empty, so your logic has to handle null and empty strings gracefully. And your Apex user needs read access to the RTA field you are querying, which is easy to forget until a test user sees nothing.
Strategizing the Output for Agentforce
Agentforce Scripts don't render HTML the way a Visualforce page might. They define structured responses, and Agentforce uses those responses to construct the user interface. Displaying RTA content therefore means telling Agentforce how to present the HTML, usually by returning a specific output structure it recognizes.
That structure is often JSON. A common approach uses the AgentBotResponse and AgentBotMessage objects, or whatever similar custom structures your Agentforce configuration expects.
Option 1: direct HTML rendering (if the Agentforce UI supports it)
In some Agentforce configurations, the UI components can render raw HTML. Where that holds, pass the HTML content straight through in your structured response.
// Inside your Agentforce Script Apex class
public virtual AgentBotResponse processRequest(AgentBotRequest request) {
String recordId = request.get('recordId'); // Assuming recordId is passed in the request
String htmlContent = '';
List<Case_Feedback__c> feedbackRecords = [SELECT Id, Customer_Comments__c FROM Case_Feedback__c WHERE Id = :recordId LIMIT 1];
if (!feedbackRecords.isEmpty() && feedbackRecords[0].Customer_Comments__c != null) {
htmlContent = feedbackRecords[0].Customer_Comments__c;
}
AgentBotResponse response = new AgentBotResponse();
List<AgentBotMessage> messages = new List<AgentBotMessage>();
// Create a message that Agentforce can render as rich text
// The exact structure depends on your Agentforce configuration.
// Often, a 'text' or 'html' field is expected.
AgentBotMessage richTextMessage = new AgentBotMessage();
richTextMessage.set('type', 'text'); // Or 'html' if your Agentforce UI component supports it
richTextMessage.set('value', htmlContent);
messages.add(richTextMessage);
response.set('messages', messages);
return response;
}
A warning on that snippet: AgentBotMessage and its properties (type, value) are illustrative. You have to check your own Agentforce implementation's documentation, or an existing configuration, for the exact structure Agentforce expects when rendering rich text or HTML. The type might be text with the HTML sitting in value, or there might be a dedicated html type.
Option 2: parsing and reformatting HTML
Direct HTML rendering is not always what you want. Security concerns can rule it out, or you may want the content reformatted into a more standardized agent-facing view. That means parsing the HTML, extracting the text or structure you care about, and rebuilding it with simpler text elements or a more controlled HTML structure.
For complex HTML parsing, a third-party Apex library or a more thorough parsing approach is worth the effort. For many everyday RTA fields, basic string manipulation or regular expressions will get you there.
The example below extracts plain text. It is a very basic illustration and it is not a robust HTML parser. For production, use something more careful if your RTA content is complex.
// Inside your Agentforce Script Apex class
public virtual AgentBotResponse processRequest(AgentBotRequest request) {
String recordId = request.get('recordId');
String plainTextContent = 'No comments available.';
List<Case_Feedback__c> feedbackRecords = [SELECT Id, Customer_Comments__c FROM Case_Feedback__c WHERE Id = :recordId LIMIT 1];
if (!feedbackRecords.isEmpty() && feedbackRecords[0].Customer_Comments__c != null) {
plainTextContent = extractPlainTextFromHtml(feedbackRecords[0].Customer_Comments__c);
}
AgentBotResponse response = new AgentBotResponse();
List<AgentBotMessage> messages = new List<AgentBotMessage>();
AgentBotMessage textMessage = new AgentBotMessage();
textMessage.set('type', 'text');
textMessage.set('value', 'Customer Comments:\n' + plainTextContent);
messages.add(textMessage);
response.set('messages', messages);
return response;
}
/**
* Very basic HTML to plain text extraction.
* Does NOT handle complex HTML, nested tags, or attributes robustly.
* Use with caution or opt for a dedicated HTML parser.
*/
private String extractPlainTextFromHtml(String htmlString) {
if (String.isBlank(htmlString)) {
return '';
}
// Remove common HTML tags
String plainText = htmlString.replaceAll('<br\s*/?>', '\n'); // Replace <br> with newline
plainText = plainText.replaceAll('<p[^>]*>', ''); // Remove <p> tags
plainText = plainText.replaceAll('</p>', '\n\n'); // Add newlines after </p>
plainText = plainText.replaceAll('<li[^>]*>', '- '); // Replace <li> with bullet point
plainText = plainText.replaceAll('</li>', ''); // Remove closing </li>
plainText = plainText.replaceAll('<strong[^>]*>', ''); // Remove <strong>
plainText = plainText.replaceAll('</strong>', ''); // Remove </strong>
plainText = plainText.replaceAll('<em[^>]*>', ''); // Remove <em>
plainText = plainText.replaceAll('</em>', ''); // Remove </em>
plainText = plainText.replaceAll('<a[^>]*href="([^"]*)"[^>]*>', '$1 '); // Extract link URL
plainText = plainText.replaceAll('</a>', ''); // Remove closing </a>
plainText = plainText.replaceAll('<h[1-6][^>]*>', ''); // Remove heading tags
plainText = plainText.replaceAll('</h[1-6]>', '\n\n');
plainText = plainText.replaceAll('<[^>]+>', ''); // Remove any remaining tags
// Decode HTML entities (basic example)
plainText = plainText.replaceAll(' ', ' ');
plainText = plainText.replaceAll('<', '<');
plainText = plainText.replaceAll('>', '>');
plainText = plainText.replaceAll('&', '&');
return plainText.trim();
}
If you do parse, decide up front what you are parsing for. Do you need to preserve formatting like bullet points, or only extract the core text? The extractPlainTextFromHtml method above is a starting point. For anything sturdier, look at specialized Apex HTML parsing libraries if you have access to one, or carefully craft regular expressions against the RTA content patterns you actually expect.
Advanced Scenarios and Best Practices
1. Handling embedded images
Rich Text Area fields can contain embedded images, and you have three ways to deal with them. The simplest is to ignore them: strip the image tags in your HTML parsing logic. If the images are hosted publicly and you want them displayed, you can extract the src attribute from the <img> tag and pass that URL to an Agentforce component capable of displaying images, which takes a more sophisticated parser. And if the images are critical and stored as Salesforce Files related to the record, your Agentforce Script may need to query those Files and return their URLs or relevant metadata for display.
2. Security considerations
Rendering arbitrary HTML from RTA fields can open you up to cross-site scripting, particularly where the content is user-generated and not properly sanitized. Agentforce's rendering engine might have sanitization built in. Be aware of the risk rather than assuming it is handled.
If the RTA content is entered directly by users, sanitize it server-side in your Apex before passing it to Agentforce. Libraries like ApexSecurity (if you use it) or careful regex can help. Where you control what gets saved into the field in the first place, enforce a stricter set of allowed HTML tags with a validation rule or an Apex trigger on the object itself.
3. Performance
Keep the SOQL efficient: SELECT only the fields you need and LIMIT where appropriate. If RTA fields can hold very large amounts of HTML, cap how much data you process or display before it turns into a performance problem.
4. Agentforce configuration decides what works
Whether any of this renders comes down to how Agentforce itself is configured to interpret the responses coming back from your Apex scripts.
Check the latest Salesforce documentation for Agentforce and for the specific AI framework you are using (Einstein Bots, Copilot integrations, and so on) for how it handles rich text, HTML, and structured message types. If you already have Agentforce implementations running, look at how they return messages and data, which will tell you a lot about the expected JSON structure. Then build it up in stages: start with simple text outputs, add RTA rendering, and test at each step.
Leave a Comment