Agentforce Models AI API: Posting Chatter with Apex

In this article, we’ll explore how to use the Agentforce Models AI API to automatically generate and post Chatter messages when a Salesforce Case status changes. Leveraging Apex @future methods and OpenAI-powered prompts, we offload the writing to AI—so agents can focus on solving problems, not posting updates.

Let’s walk through a practical and scalable use case: Automatically generating Chatter posts when a Case transitions to “Working” using the Agentforce AI Models API.

🧠 The Idea

Every time a support Case enters the “Working” status, we want to notify internal stakeholders with a professionally written Chatter message. Instead of hardcoding a message, we’ll let AI craft a natural, contextual update—tailored to each Case.

💡 Design Overview

This solution uses:

  • Apex Triggers + Handler Pattern
  • @future(callout=true) method to invoke the AI API asynchronously
  • Agentforce’s aiplatform.ModelsAPI.createGenerations() to generate the message
  • Chatter FeedItem to post the result

⚙️ How It Works

1. Trigger Fires

The CaseTrigger invokes the CaseTriggerHandler on insert and update.

trigger CaseTrigger on Case (after insert, after update) {
    if (Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)) {
        CaseTriggerHandler.handleAfterInsertOrUpdate(Trigger.new, Trigger.oldMap);
    }
}

2. Business Logic in Handler

We detect when a Case changes status to “Working” and queue it for Chatter posting.

public class CaseTriggerHandler {

    public static void handleAfterInsertOrUpdate(List<Case> newCases, Map<Id, Case> oldMap) {
        if (newCases == null || newCases.isEmpty()) {
            return;
        }

        List<Id> toChatter = new List<Id>();

        for (Case newCase : newCases) {
            if (newCase == null || String.isBlank(newCase.Status)) {
                continue;
            }

            Case oldCase = oldMap != null ? oldMap.get(newCase.Id) : null;
            String oldStatus = oldCase != null ? oldCase.Status : null;

            // Check for transition to 'Working'
            if (oldStatus != 'Working' && newCase.Status == 'Working') {
                toChatter.add(newCase.Id);
            }
        }

        // Trigger async actions
        for (Id caseId : toChatter) {
            CaseChatterAIService.postChatterOnCaseCloseAsync(caseId);
        }
    }
}

3. AI Generates Message Asynchronously

The core of this approach is CaseChatterAIService, which builds a prompt and sends it to the AI model.

public class CaseChatterAIService {

    private static final String MODEL_NAME = 'sfdc_ai__DefaultOpenAIGPT4OmniMini';
    private static final String PROMPT_TEMPLATE = 
        'Generate a positive and professional Chatter message announcing that Case #%s titled "%s" has been handled by the agent. ' +
        'Here are the relevant details:\n%s';

    @future(callout = true)
    public static void postChatterOnCaseCloseAsync(Id caseId) {
        if (caseId == null) {
            return;
        }

        try {
            Case caseRecord = [
                SELECT Id, CaseNumber, Subject, Status, Priority, Owner.Name 
                FROM Case 
                WHERE Id = :caseId 
                LIMIT 1
            ];

            String caseDetails = String.format(
                'Case Number: {0}\nSubject: {1}\nStatus: {2}\nPriority: {3}\nOwner: {4}', 
                new List<String>{
                    String.valueOf(caseRecord.CaseNumber),
                    String.valueOf(caseRecord.Subject),
                    String.valueOf(caseRecord.Status),
                    String.valueOf(caseRecord.Priority),
                    String.valueOf(caseRecord.Owner.Name)
                }
            );

            String prompt = String.format(
                PROMPT_TEMPLATE,
                new List<String>{
                    String.valueOf(caseRecord.CaseNumber),
                    String.valueOf(caseRecord.Subject),
                    caseDetails
                }
            );

            aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();

            aiplatform.ModelsAPI.createGenerations_Request request = 
                new aiplatform.ModelsAPI.createGenerations_Request();
            request.modelName = MODEL_NAME;

            aiplatform.ModelsAPI_GenerationRequest requestBody = 
                new aiplatform.ModelsAPI_GenerationRequest();
            requestBody.prompt = prompt;
            request.body = requestBody;

            aiplatform.ModelsAPI.createGenerations_Response response = modelsAPI.createGenerations(request);

            String chatterMessage = (response != null && response.Code200 != null)
                ? response.Code200.generation.generatedText
                : null;

            if (String.isNotBlank(chatterMessage)) {
                FeedItem post = new FeedItem();
                post.ParentId = caseRecord.Id;
                post.Body = chatterMessage;
                insert post;
            }

        } catch (QueryException qe) {
            System.debug(LoggingLevel.ERROR, 'Query failed for Case Id: ' + caseId + ' => ' + qe.getMessage());
        } catch (aiplatform.ModelsAPI.createGenerations_ResponseException ae) {
            System.debug(LoggingLevel.ERROR, 'AI API error for Case Id: ' + caseId + ' => ' + ae.getMessage());
        } catch (DmlException de) {
            System.debug(LoggingLevel.ERROR, 'DML error while posting to Chatter for Case Id: ' + caseId + ' => ' + de.getMessage());
        } catch (Exception e) {
            System.debug(LoggingLevel.ERROR, 'Unexpected error for Case Id: ' + caseId + ' => ' + e.getMessage());
        }
    }
}

Key Benefits

  • Real-Time AI Messaging: Trigger contextual Chatter updates right from Apex, no manual effort required.
  • Fully Native: No external integrations or third-party AI calls—Salesforce-hosted Gen AI does the heavy lifting.

⚠️ Gotchas and Best Practices

  • Callout Limits: @future(callout=true) allows external calls but still has per-transaction limits.
  • Resilience: Catch exceptions from the AI API or DML and log them (as demonstrated).
  • Avoid Redundant Posts: Use status comparisons in the handler to prevent duplicate AI requests.
  • Test AI Output Quality: Model hallucination is rare but possible—validate critical messages before posting if needed.

🔚 Final Thoughts

With Agentforce Models AI API, Chatter becomes more than a collaboration tool—it becomes a canvas for real-time, intelligent communication. This is Apex infused with AI, native to the Salesforce Platform, and built for scale.

Agentforce is here—and Chatter just got a lot smarter.

Demo: Agentforce Models AI API: Posting Chatter with Apex

Agentforce Models AI API: Posting Chatter with Apex

we’ll explore how to use the Agentforce Models AI API to automatically generate and post Chatter messages when a Salesforce Case status changes. Leveraging Apex @future methods and OpenAI-powered prompts, we offload the writing to AI—so agents can focus on solving problems, not posting updates.

Do you need help?

Are you stuck while working on this requirement? Do you want to get review of your solution? Now, you can book dedicated 1:1 with me on Lightning Web Component and Agentforce completely free.

GET IN TOUCH

Schedule a 1:1 Meeting with me

One comment

Leave a Reply