Welcome! This post is about building an Agentforce Service Agent that can respond to customer questions about order updates, tracking information, returns, and refunds. That part sounds simple enough. A customer asks, “Where is my order?” The agent looks up the order. The agent answers.
And yet.
And yet, and yet, and yet.
The dangerous part of customer service automation is not that the agent might fail to answer. That failure is visible. The customer notices. The support team notices. Someone fixes the configuration.
The more dangerous failure is when the agent answers too early, with too much confidence, using data the customer has not been verified to receive.
A customer asking for a tracking number is not just asking for a tracking number. They are asking the system to expose fulfillment data. A customer asking about a refund is not just asking about a refund. They are asking the system to expose payment status, return eligibility, order history, and sometimes account-level information.
So the first principle for this build is straightforward:
The agent should not answer private order, return, refund, or tracking questions until the customer has been verified.
The second principle is equally important:
When the conversation escalates, the human agent should not have to reconstruct the conversation from scratch.
That means the agent should do two jobs at once:
- Help the customer directly when it can safely do so.
- Prepare the human agent when escalation becomes necessary.
The second job is where the Case object becomes useful. Instead of treating the Case as a passive record created after the conversation goes poorly, we can use it as the shared workspace between Agentforce and the human service team.
The result is an Agentforce solution that:
- Greets the customer by name when phone or email context is already available.
- Verifies the customer before disclosing order, tracking, return, or refund details.
- Answers supported questions using Salesforce data, external order systems, carrier APIs, refund systems, and knowledge.
- Writes customer tone, recommended response, and case brief onto the Case record.
- Displays that intelligence in a Lightning Web Component card.
- Changes the card color based on customer sentiment:
- Red for angry or frustrated customers.
- Yellow for disappointed or moderately unhappy customers.
- Green for happy or satisfied customers.
Let’s build it.
Agentforce For Service
Agentforce should not be designed as a prettier chatbot.
That sentence is worth sitting with for a moment, because many AI service implementations go wrong at exactly this point. A traditional chatbot is usually designed around decision trees. The designer tries to predict the customer’s phrasing, route the customer through a fixed path, and hope that the available menu options map well enough to the customer’s real problem.
Agentforce should instead be designed around work.
The customer has a job to be done:
- Find my order.
- Tell me where the package is.
- Explain why the package is delayed.
- Start a return.
- Check whether I am eligible for a refund.
- Tell me when my refund will arrive.
- Escalate me to a human because this is not acceptable.
The human support agent also has a job to be done:
- Understand the customer quickly.
- Know what the customer already asked.
- Know what the AI already answered.
- Understand the customer’s emotional state.
- Respond with the right tone.
- Avoid repeating verification steps unnecessarily.
- Resolve the case.
Agentforce sits between these two jobs. The solution works when the agent respects both.
The Problem With “Just Answer The Customer”
Let’s imagine a customer starts a chat:
Where is my order?
A naive AI implementation might immediately search for a recent order based on the chat session, find the order, and respond:
Your order #10004567 shipped yesterday and is currently in Mumbai. The tracking number is TRK92839102.
That sounds useful.
It is also exactly the kind of response that should make an architect nervous.
What if the chat was started by someone using a shared device? What if the email on the chat form was mistyped? What if the phone number belongs to a family member? What if multiple contacts share the same account? What if the order contains sensitive delivery information?
The agent has to pause before it helps.
That pause is not a bad customer experience. Done correctly, it is the foundation of a trustworthy customer experience.
Verifying The Customer Before Answering
The verification rule for this solution is:
- If phone or email is available from the channel context, use it to identify a possible Contact.
- If a single matching Contact is found, greet the customer by name.
- If the customer is not yet verified, ask for the missing verification detail.
- If neither phone nor email is available, ask for both email and phone number.
- Do not disclose private order, return, refund, tracking, or account data until verification succeeds.
- If verification fails too many times, escalate to a human agent.
That gives us a nice decision table:
| Available Context | Agent Greeting | Verification Step |
|---|---|---|
| Phone matches one Contact | “Hi Priya” | Ask for email |
| Email matches one Contact | “Hi Priya” | Ask for phone |
| Phone and email match same Contact | “Hi Priya” | Mark verified |
| No phone or email | Generic greeting | Ask for email and phone |
| Multiple matches | Generic greeting | Ask for email and phone |
| Mismatch | Generic greeting | Escalate or retry |
The goal is to avoid making the customer repeat information when the system already has enough context, while still protecting private information.
Designing The Agent Around Work, Not Around Prompts
The temptation with AI projects is to start with the prompt.
That’s backwards.
For this use case, start with the concepts:
- Customer identity.
- Verification status.
- Order status.
- Tracking status.
- Return eligibility.
- Refund status.
- Sentiment.
- Escalation readiness.
- Human agent recommendation.
Once those concepts are named, the implementation becomes cleaner. Each concept maps to data, an action, a field, a subagent, or a component.
This is the same reason good Apex code tends to improve when we stop stuffing everything into one method. Concepts want shape. If we do not give them shape intentionally, they still show up, just scattered across flows, prompts, Apex classes, screen components, and case comments.
The Architecture
Here’s the architecture for the solution:
flowchart LR
Customer[Customer<br/>Voice, Chat, Messaging] --> Channel[Digital Engagement / Voice Channel]
Channel --> Context[Channel Context<br/>Phone, Email, Name, Session Id]
Context --> Agent[Agentforce Service Agent]
Agent --> Verify[Verification Subagent]
Agent --> Order[Order Status Subagent]
Agent --> ReturnRefund[Returns & Refunds Subagent]
Agent --> Escalation[Escalation Summary Subagent]
Verify --> A1[Action: Verify Customer]
Order --> A2[Action: Get Order Updates]
Order --> A3[Action: Get Tracking Info]
ReturnRefund --> A4[Action: Check Return Eligibility]
ReturnRefund --> A5[Action: Get Refund Status]
Escalation --> A6[Action: Generate Case Brief]
Escalation --> A7[Action: Update Case Intelligence]
A1 --> CRM[(Salesforce CRM<br/>Contact, Account, Case)]
A2 --> OMS[(Order Management<br/>Order Summary / External OMS)]
A3 --> Carrier[(Carrier API<br/>FedEx, UPS, DHL, Shiprocket)]
A4 --> Policy[(Knowledge / Return Policy)]
A5 --> Payment[(Payment / Refund System)]
A6 --> Case[(Case Object)]
A7 --> Case
Case --> LWC[LWC Case Assist Card<br/>Tone, Recommendation, Brief]
LWC --> Human[Human Service Agent]
Human --> Customer
The diagram is intentionally simple. The actual implementation might include Data Cloud, MuleSoft, Named Credentials, Platform Events, Omni-Channel, Service Cloud Voice, Messaging for In-App and Web, and external order systems. Those details matter, but the conceptual flow remains the same:
- Customer enters through a channel.
- Agent receives the message and available context.
- Agent verifies the customer.
- Agent retrieves the right operational data.
- Agent responds if it can.
- Agent escalates if needed.
- Agent writes guidance to the Case.
- Human agent sees the LWC card and responds appropriately.
Data Model
For this implementation, we’ll assume the following Salesforce data model:
Standard Objects
- Contact
- Account
- Case
- Order Summary or Order
- Order Item Summary or Order Product
- Return Order, if Salesforce Order Management is used
- Knowledge Article, for return and refund policy content
External Systems
- Order Management System
- Shipping carrier API
- Payment gateway or refund processor
- ERP, if order fulfillment lives outside Salesforce
Custom Fields On Case
Create the following fields on Case:
| Field Label | API Name | Type | Purpose |
|---|---|---|---|
| Customer Tone | Customer_Tone__c | Picklist | Angry, Frustrated, Disappointed, Neutral, Happy, Satisfied |
| Sentiment Level | Sentiment_Level__c | Picklist | Red, Yellow, Green |
| Agent Recommendation | Agent_Recommendation__c | Long Text Area | Suggested response approach for human agent |
| Agent Brief | Agent_Brief__c | Long Text Area | Summary of conversation, order context, and unresolved issue |
| Verification Status | Verification_Status__c | Picklist | Not Started, Pending, Verified, Failed |
| Verified Contact | Verified_Contact__c | Lookup(Contact) | Contact verified during conversation |
| Last Verified Email | Last_Verified_Email__c | Email used for verification | |
| Last Verified Phone | Last_Verified_Phone__c | Phone | Phone used for verification |
| Escalation Reason | Escalation_Reason__c | Long Text Area | Why the agent escalated |
| Last Agent Action | Last_Agent_Action__c | Text | Last action executed by Agentforce |
You could put some of this data on a related custom object instead of Case. For example, Agent_Assist_Insight__c could track multiple snapshots over time. That is useful when you want history across a long case lifecycle.
For this blog post, I’ll keep the design focused on the Case object because the user requirement is to show the brief, tone, and recommendations as an LWC card on Case.
Agentforce Subagents
Create one Agentforce Service Agent and break its responsibility into subagents.
1. Customer Verification Subagent
Purpose:
Verify customer identity before any private information is disclosed.
Instructions:
You verify the customer before private information is shared.
If the channel context contains a phone number or email address, use it to identify the customer.
If a single matching Contact is found, greet the customer by first name.
If only phone is available, ask the customer to provide their email address.
If only email is available, ask the customer to provide their phone number.
If neither phone nor email is available, ask for both email and phone number.
Do not reveal order, refund, return, shipment, address, payment, or account-specific information until the Verify Customer action returns verified = true.
If verification fails two times, escalate to a human agent and update the Case brief.
This subagent owns the gate.
Everything else depends on it.
2. Order Status Subagent
Purpose:
Answer order update and tracking questions after verification.
Instructions:
You answer questions about order status, shipment status, delivery estimates, delays, and tracking numbers.
Before answering, confirm that Verification Status is Verified.
Use Get Order Updates for order status.
Use Get Tracking Info for shipment and carrier events.
If there are multiple recent orders, ask the customer which order they mean.
If order data is unavailable, apologize briefly, explain that the order details need review, and escalate to a human agent.
Never invent tracking numbers, delivery dates, refund dates, or carrier statuses.
3. Returns And Refunds Subagent
Purpose:
Answer return eligibility, return process, refund amount, and refund timing questions.
Instructions:
You answer questions about return eligibility, return process, refund status, refund timing, and refund policy.
Before answering, confirm that Verification Status is Verified.
Use Check Return Eligibility before saying whether an item can be returned.
Use Get Refund Status before saying whether a refund was issued.
Use Knowledge only for general policy explanations.
For account-specific refund status, use system data only.
If the customer is angry, disappointed, or mentions legal action, escalation, repeated failed attempts, missing refund, or damaged product, update the Case with a recommendation for a human agent.
4. Escalation Summary Subagent
Purpose:
Prepare the human agent.
Instructions:
You summarize the conversation for a human support agent.
Write a concise case brief.
Classify customer tone as Angry, Frustrated, Disappointed, Neutral, Happy, or Satisfied.
Map the customer tone to a sentiment level:
- Red for Angry or Frustrated
- Yellow for Disappointed or Neutral
- Green for Happy or Satisfied
Write a recommended response strategy for the human agent.
The recommendation should include:
- whether the agent should apologize
- whether the agent should acknowledge delay or inconvenience
- what information the agent should confirm
- the next best action
- what not to repeat if the customer has already provided it
This is the part that changes the service experience for human agents. Instead of opening a Case and reading a long transcript, the agent sees a colored card with a brief and recommendation.
Actions
The Agentforce actions are the contract between the agent’s reasoning and your business systems.
For this solution, create these actions:
| Action | Type | Purpose |
|---|---|---|
| Verify Customer | Apex or Flow | Match phone and email to Contact |
| Get Order Updates | Apex, Flow, or API | Retrieve order status |
| Get Tracking Info | Apex or MuleSoft API | Retrieve shipment tracking |
| Check Return Eligibility | Flow or Apex | Determine return eligibility |
| Get Refund Status | Apex or API | Retrieve refund status |
| Generate Case Brief | Prompt Template or Apex | Summarize customer issue |
| Update Case Intelligence | Apex or Flow | Write tone, recommendation, and brief to Case |
The action descriptions matter. A vague action description gives the agent too much room to choose incorrectly.
Poor description:
Gets customer information.
Better description:
Verifies whether the customer-provided email and phone number belong to a single Contact. Use this action before sharing order, shipment, return, refund, address, or payment information.
Poor description:
Gets order info.
Better description:
Retrieves order status, fulfillment status, estimated delivery date, and order summary for a verified Contact. Use only after customer verification succeeds.
The description is not documentation for humans only. It is part of how the agent decides what tool to use.
A Naive Approach To Customer Service Automation
Let’s start with the kind of implementation that looks acceptable in a demo:
public with sharing class OrderAnswerService {
public static String answerOrderQuestion(String email) {
Contact contact = [
SELECT Id, Name
FROM Contact
WHERE Email = :email
LIMIT 1
];
Order latestOrder = [
SELECT Id, Status, Tracking_Number__c
FROM Order
WHERE AccountId = :contact.AccountId
ORDER BY CreatedDate DESC
LIMIT 1
];
return 'Your latest order is ' + latestOrder.Status +
'. Tracking number: ' + latestOrder.Tracking_Number__c;
}
}
This is useful as a warning, not as a pattern.
There are several problems here:
- Email alone may not be enough to verify the customer.
- The query assumes one matching Contact.
- It assumes the latest order is the order the customer means.
- It exposes a tracking number immediately.
- It has no escalation behavior.
- It writes nothing useful back to Case.
- It gives the human agent no context if the customer gets transferred.
The issue is not that the code is short. Short code is often good. The issue is that the important concepts are missing.
There is no verification concept. There is no ambiguity concept. There is no customer tone concept. There is no human handoff concept.
Those concepts will still exist in the real world. The customer will still be frustrated. The Contact match will still be ambiguous. The order will still be delayed. The human agent will still need a summary.
The system simply will not represent those realities well.
Moving Verification Into A First-Class Concept
Let’s give verification a shape.
A simplified Apex action could look like this:
public with sharing class VerifyCustomerAction {
public class Request {
@InvocableVariable(required=false)
public String email;
@InvocableVariable(required=false)
public String phone;
@InvocableVariable(required=false)
public String caseId;
}
public class Response {
@InvocableVariable
public Boolean verified;
@InvocableVariable
public String contactId;
@InvocableVariable
public String contactName;
@InvocableVariable
public String status;
@InvocableVariable
public String message;
}
@InvocableMethod(label='Verify Customer')
public static List<Response> verify(List<Request> requests) {
List<Response> responses = new List<Response>();
for (Request req : requests) {
Response res = new Response();
if (String.isBlank(req.email) || String.isBlank(req.phone)) {
res.verified = false;
res.status = 'Pending';
res.message = 'Email and phone are required before private information can be shared.';
responses.add(res);
continue;
}
List<Contact> contacts = [
SELECT Id, Name, Email, Phone, MobilePhone
FROM Contact
WHERE Email = :req.email
AND (Phone = :req.phone OR MobilePhone = :req.phone)
LIMIT 2
];
if (contacts.size() == 1) {
Contact matchedContact = contacts[0];
res.verified = true;
res.contactId = matchedContact.Id;
res.contactName = matchedContact.Name;
res.status = 'Verified';
res.message = 'Customer verified.';
updateCaseVerification(req.caseId, matchedContact, req.email, req.phone, 'Verified');
} else if (contacts.isEmpty()) {
res.verified = false;
res.status = 'Failed';
res.message = 'No matching customer was found for the provided email and phone.';
updateCaseVerification(req.caseId, null, req.email, req.phone, 'Failed');
} else {
res.verified = false;
res.status = 'Ambiguous';
res.message = 'Multiple customers matched. Human review is required.';
updateCaseVerification(req.caseId, null, req.email, req.phone, 'Failed');
}
responses.add(res);
}
return responses;
}
private static void updateCaseVerification(
String caseId,
Contact contact,
String email,
String phone,
String status
) {
if (String.isBlank(caseId)) {
return;
}
Case c = new Case(
Id = caseId,
Verification_Status__c = status,
Last_Verified_Email__c = email,
Last_Verified_Phone__c = phone
);
if (contact != null) {
c.Verified_Contact__c = contact.Id;
}
update c;
}
}
This action does not answer the customer’s question. That’s the point.
It answers a more important system question first:
Are we allowed to answer the customer’s question?
That distinction is what keeps the agent safe.
Order And Tracking Actions
Once verification succeeds, the order subagent can retrieve order data.
A simplified order status response might look like this:
public with sharing class GetOrderUpdatesAction {
public class Request {
@InvocableVariable(required=true)
public String contactId;
@InvocableVariable(required=false)
public String orderNumber;
}
public class Response {
@InvocableVariable
public Boolean success;
@InvocableVariable
public String orderNumber;
@InvocableVariable
public String orderStatus;
@InvocableVariable
public String fulfillmentStatus;
@InvocableVariable
public String estimatedDeliveryDate;
@InvocableVariable
public String message;
}
@InvocableMethod(label='Get Order Updates')
public static List<Response> getUpdates(List<Request> requests) {
List<Response> responses = new List<Response>();
for (Request req : requests) {
Response res = new Response();
List<Order> orders = [
SELECT Id, OrderNumber, Status, Fulfillment_Status__c, Estimated_Delivery_Date__c
FROM Order
WHERE AccountId IN (
SELECT AccountId
FROM Contact
WHERE Id = :req.contactId
)
ORDER BY CreatedDate DESC
LIMIT 5
];
if (orders.isEmpty()) {
res.success = false;
res.message = 'No recent orders were found for the verified customer.';
} else if (String.isBlank(req.orderNumber) && orders.size() > 1) {
res.success = false;
res.message = 'Multiple recent orders were found. Ask the customer which order they mean.';
} else {
Order selectedOrder = selectOrder(orders, req.orderNumber);
if (selectedOrder == null) {
res.success = false;
res.message = 'The requested order was not found for the verified customer.';
} else {
res.success = true;
res.orderNumber = selectedOrder.OrderNumber;
res.orderStatus = selectedOrder.Status;
res.fulfillmentStatus = selectedOrder.Fulfillment_Status__c;
res.estimatedDeliveryDate = String.valueOf(selectedOrder.Estimated_Delivery_Date__c);
res.message = 'Order details retrieved.';
}
}
responses.add(res);
}
return responses;
}
private static Order selectOrder(List<Order> orders, String orderNumber) {
if (String.isBlank(orderNumber) && orders.size() == 1) {
return orders[0];
}
for (Order o : orders) {
if (o.OrderNumber == orderNumber) {
return o;
}
}
return null;
}
}
In a production implementation, I would usually avoid putting external carrier logic directly inside this class. The cleaner approach is to create separate services:
OrderLookupServiceTrackingServiceReturnEligibilityServiceRefundStatusServiceCaseInsightService
That keeps each concept isolated.
Case Intelligence
Now we get to the feature that helps the human agent.
When the conversation escalates, the agent should update the Case with:
- Customer tone
- Sentiment level
- Recommended response
- Brief summary
- Escalation reason
- Last action taken
Example Case brief:
Customer asked for the status of order #10004567. Customer was verified using email and phone. Agent retrieved tracking and found the package delayed by two days. Customer became frustrated because this is the second delay and requested a human agent.
Example recommendation:
Start by apologizing for the repeated delay. Do not ask the customer to repeat email or phone verification because verification is already complete. Confirm that the package is delayed by two days, explain the current carrier scan, and offer either continued tracking support or a return/refund review if the customer no longer wants the item.
Example tone:
Frustrated
Example sentiment level:
Red
This is the kind of summary that saves time in the console. The human agent can enter the conversation already knowing what happened, what not to repeat, and how carefully to phrase the next response.
A simplified update action:
public with sharing class UpdateCaseIntelligenceAction {
public class Request {
@InvocableVariable(required=true)
public String caseId;
@InvocableVariable(required=true)
public String customerTone;
@InvocableVariable(required=true)
public String agentBrief;
@InvocableVariable(required=true)
public String agentRecommendation;
@InvocableVariable(required=false)
public String escalationReason;
@InvocableVariable(required=false)
public String lastAgentAction;
}
public class Response {
@InvocableVariable
public Boolean success;
@InvocableVariable
public String message;
}
@InvocableMethod(label='Update Case Intelligence')
public static List<Response> updateCase(List<Request> requests) {
List<Response> responses = new List<Response>();
for (Request req : requests) {
Response res = new Response();
Case c = new Case(
Id = req.caseId,
Customer_Tone__c = req.customerTone,
Sentiment_Level__c = mapToneToSentiment(req.customerTone),
Agent_Brief__c = req.agentBrief,
Agent_Recommendation__c = req.agentRecommendation,
Escalation_Reason__c = req.escalationReason,
Last_Agent_Action__c = req.lastAgentAction
);
update c;
res.success = true;
res.message = 'Case intelligence updated.';
responses.add(res);
}
return responses;
}
private static String mapToneToSentiment(String tone) {
if (tone == 'Angry' || tone == 'Frustrated') {
return 'Red';
}
if (tone == 'Disappointed' || tone == 'Neutral') {
return 'Yellow';
}
if (tone == 'Happy' || tone == 'Satisfied') {
return 'Green';
}
return 'Yellow';
}
}
You might wonder why the sentiment mapping exists in Apex if the agent can classify the tone itself.
The answer is consistency.
The agent can classify the emotional tone. The system should own the mapping from tone to UI behavior.
That way, if the business later decides that “Neutral” should be green instead of yellow, you change deterministic logic, not a prompt.
Creating The Case Assist Card
The Case Assist Card is a Lightning Web Component placed on the Case record page. It reads the Case fields and displays the AI-generated guidance.
The component has three jobs:
- Make the customer tone visible.
- Make the recommendation visible.
- Make the brief visible.
The color is not decoration. It is operational priority.
A red card tells the human agent:
Slow down. Acknowledge the customer’s frustration first. Do not respond like this is a routine order update.
A yellow card tells the human agent:
The customer is not fully satisfied. Be careful, concise, and helpful.
A green card tells the human agent:
The customer is satisfied or calm. Continue with a standard helpful tone.
LWC HTML
<template>
<lightning-card title="Agentforce Case Assist" icon-name="standard:bot">
<div class={cardClass}>
<div class="header">
<div>
<p class="label">Customer Tone</p>
<p class="tone">{customerTone}</p>
</div>
<div>
<p class="label">Verification</p>
<p class="status">{verificationStatus}</p>
</div>
</div>
<div class="section">
<p class="label">Recommended Response</p>
<p>{agentRecommendation}</p>
</div>
<div class="section">
<p class="label">Case Brief</p>
<p>{agentBrief}</p>
</div>
<template if:true={escalationReason}>
<div class="section">
<p class="label">Escalation Reason</p>
<p>{escalationReason}</p>
</div>
</template>
</div>
</lightning-card>
</template>
LWC JavaScript
import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import CUSTOMER_TONE from '@salesforce/schema/Case.Customer_Tone__c';
import SENTIMENT_LEVEL from '@salesforce/schema/Case.Sentiment_Level__c';
import AGENT_RECOMMENDATION from '@salesforce/schema/Case.Agent_Recommendation__c';
import AGENT_BRIEF from '@salesforce/schema/Case.Agent_Brief__c';
import VERIFICATION_STATUS from '@salesforce/schema/Case.Verification_Status__c';
import ESCALATION_REASON from '@salesforce/schema/Case.Escalation_Reason__c';
const FIELDS = [
CUSTOMER_TONE,
SENTIMENT_LEVEL,
AGENT_RECOMMENDATION,
AGENT_BRIEF,
VERIFICATION_STATUS,
ESCALATION_REASON
];
export default class AgentforceCaseAssistCard extends LightningElement {
@api recordId;
@wire(getRecord, { recordId: '$recordId', fields: FIELDS })
caseRecord;
get fieldValues() {
return this.caseRecord?.data?.fields;
}
get customerTone() {
return this.fieldValues?.Customer_Tone__c?.value || 'Not evaluated';
}
get sentimentLevel() {
return this.fieldValues?.Sentiment_Level__c?.value || 'Yellow';
}
get agentRecommendation() {
return this.fieldValues?.Agent_Recommendation__c?.value || 'No recommendation generated yet.';
}
get agentBrief() {
return this.fieldValues?.Agent_Brief__c?.value || 'No case brief generated yet.';
}
get verificationStatus() {
return this.fieldValues?.Verification_Status__c?.value || 'Not Started';
}
get escalationReason() {
return this.fieldValues?.Escalation_Reason__c?.value;
}
get cardClass() {
const sentiment = this.sentimentLevel.toLowerCase();
if (sentiment === 'red') {
return 'assist-card red';
}
if (sentiment === 'green') {
return 'assist-card green';
}
return 'assist-card yellow';
}
}
LWC CSS
.assist-card {
border-radius: 0.75rem;
padding: 1rem;
border-left: 0.5rem solid;
}
.assist-card.red {
background: #fff1f1;
border-left-color: #ba0517;
}
.assist-card.yellow {
background: #fff8e6;
border-left-color: #dd7a01;
}
.assist-card.green {
background: #eefaf1;
border-left-color: #2e844a;
}
.header {
display: flex;
justify-content: space-between;
gap: 1rem;
margin-bottom: 1rem;
}
.section {
margin-top: 1rem;
}
.label {
font-size: 0.75rem;
text-transform: uppercase;
color: #5c5c5c;
font-weight: 700;
margin-bottom: 0.25rem;
}
.tone,
.status {
font-size: 1rem;
font-weight: 700;
}
LWC Meta XML
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>61.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<objects>
<object>Case</object>
</objects>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
Place this component on the Case Lightning Record Page used by service agents.
I usually prefer placing it near the top of the right sidebar. It should be visible without forcing the agent to scroll, but it should not replace the core case details, activity timeline, or related records.
The End-To-End Flow
Let’s walk through a real conversation.
Scenario 1: Phone Number Available From Voice
The customer calls from a known phone number.
The system finds one matching Contact:
Phone: +91 98765 43210
Matched Contact: Priya Shah
The agent starts:
Hi Priya, I can help with your order. For security, please confirm the email address on your account before I share order details.
Priya provides the email.
The Verify Customer action returns:
{
"verified": true,
"contactName": "Priya Shah",
"status": "Verified"
}
Now the agent can answer:
Thanks, Priya. Your order #10004567 has shipped and is currently in transit. The latest carrier update shows that it reached the Mumbai sorting facility today. The estimated delivery date is June 22.
No escalation is needed. The Case can still be updated with a green sentiment if a Case exists:
Tone: Satisfied
Sentiment: Green
Brief: Customer asked for order status and was given the current shipment update.
Recommendation: No human action required unless the customer asks a follow-up question.
Scenario 2: Chat Without Email Or Phone
The customer starts chat with:
Where is my refund? I have been waiting for days.
No phone or email is available.
The agent responds:
I can help check that. Before I access refund details, please provide the email address and phone number used on the order.
The customer provides both.
Verification succeeds.
The refund status action finds that the refund is pending because the returned item has not completed warehouse inspection.
The agent responds:
Thanks for verifying your details. Your return was received, and the refund is currently waiting for warehouse inspection to complete. Once inspection is completed, the refund will be released to the original payment method.
The customer responds:
That is not acceptable. I was told this would be done already.
Now the agent should update the Case:
Tone: Frustrated
Sentiment: Red
Brief: Customer asked about refund status. Customer was verified. Refund is pending because warehouse inspection is incomplete. Customer is frustrated because they expected the refund to be completed already.
Recommendation: Apologize for the delay. Acknowledge that the customer was previously told the refund would be completed. Do not ask for email or phone again. Confirm whether warehouse inspection can be expedited or whether a manual refund review is available.
Escalation Reason: Customer is frustrated about refund delay and wants human review.
The human agent opens the Case and immediately sees a red card.
That is the point of the LWC.
It turns conversation context into action context.
Agent Greeting Logic
The greeting experience deserves special attention because it shapes customer trust.
Use this hierarchy:
If Contact Is Found By Phone
Hi {FirstName}, I can help with that. For security, please confirm the email address on your account.
If Contact Is Found By Email
Hi {FirstName}, I can help with that. For security, please confirm the phone number on your account.
If Contact Is Found By Phone And Email
Hi {FirstName}, I can help with that.
Then continue to the relevant task.
If No Contact Is Found
I can help with that. Before I access order or refund details, please provide the email address and phone number used on the order.
If Multiple Contacts Are Found
I need to verify a few details before accessing order information. Please provide the email address and phone number used on the order.
Avoid saying:
I found multiple accounts with that phone number.
That reveals too much. The customer does not need to know how many records matched.
Prompt Template For Case Brief
You can create a prompt template for the escalation summary. The exact implementation depends on your org’s AI setup, but the instruction should be structured.
Example prompt:
You are generating a service handoff summary for a human support agent.
Use the conversation transcript, verified customer details, order data, refund data, and case context.
Return the following fields:
Customer Tone:
Choose one: Angry, Frustrated, Disappointed, Neutral, Happy, Satisfied.
Agent Brief:
Write 2 to 4 sentences. Include what the customer asked, what was verified, what data was found, what the agent already said, and what remains unresolved.
Agent Recommendation:
Write specific guidance for the human agent. Include how to respond, what to acknowledge, what to check next, and what not to ask again.
Escalation Reason:
Write one sentence explaining why the conversation is being escalated.
Rules:
- Do not invent order, tracking, refund, or policy details.
- Do not include sensitive payment details.
- Do not ask the human agent to repeat completed verification.
- Keep the recommendation operational and concise.
This is one of those places where brevity is a feature. A verbose AI summary is only slightly better than no summary. A human agent needs usable guidance, not a transcript rewritten in paragraph form.
Recommended Agentforce Build Steps
Here is the practical build sequence.
Step 1: Prepare Case Fields
Create the Case fields listed earlier.
Add them to the Case page layout, but do not rely on the layout alone. The LWC is the primary user experience for these fields.
Step 2: Build Verification Logic
Implement verification using Flow or Apex.
Use Apex if:
- Matching rules are complex.
- You need normalization for phone numbers.
- You need custom logging.
- You need to query multiple objects.
- You need deterministic handling for ambiguous matches.
Use Flow if:
- Matching is straightforward.
- Admins will own future updates.
- You want a low-code implementation.
Step 3: Build Order, Tracking, Return, And Refund Actions
Create actions with clear boundaries.
Do not create one giant “Customer Service Action” that does everything. That makes agent reasoning harder to test and harder to debug.
Better:
Verify CustomerGet Recent OrdersGet Order StatusGet Tracking DetailsCheck Return EligibilityGet Refund StatusUpdate Case Intelligence
Step 4: Create The Agentforce Service Agent
Create the service agent and define its role:
You are a customer service agent for ecommerce order support. You help verified customers with order updates, shipment tracking, returns, and refunds. You must verify the customer before sharing private information. When escalation is needed, you prepare a concise case brief and response recommendation for the human support agent.
Step 5: Create Subagents
Create the four subagents:
- Customer Verification
- Order Status
- Returns And Refunds
- Escalation Summary
Attach the relevant actions to each subagent.
Step 6: Ground The Agent
Ground the agent with:
- Return policy knowledge articles.
- Refund timing policy.
- Shipping delay policy.
- Order status definitions.
- Internal escalation policy.
- Contact, Case, and Order data.
- External order, carrier, and refund APIs where required.
Separate general policy answers from customer-specific answers.
For example:
- “What is your return policy?” can be answered from Knowledge.
- “Is my order eligible for return?” requires verified customer and order data.
- “Where is my refund?” requires verified customer and refund data.
Step 7: Add Guardrails
Add instructions that prevent unsafe responses:
Do not disclose order details before verification.
Do not disclose tracking numbers before verification.
Do not disclose refund status before verification.
Do not expose full delivery addresses.
Do not expose full payment details.
Do not claim a refund has been issued unless refund data confirms it.
Do not promise delivery by a date unless the order or carrier system provides that date.
If the customer asks for something outside your allowed scope, escalate to a human agent.
Step 8: Build And Deploy The LWC
Deploy the LWC to the Case record page.
Test the visual states:
- Red card for Angry or Frustrated.
- Yellow card for Disappointed or Neutral.
- Green card for Happy or Satisfied.
Step 9: Connect To Channels
Deploy the agent to the relevant channels:
- Messaging for Web
- Messaging for In-App
- Experience Cloud
- Service Cloud Voice
- Partner or customer portal
Pass available context into the agent session:
- Phone number
- Contact Id, if known
- Case Id, if already created
- Messaging session Id
- Voice call Id
Step 10: Monitor And Improve
Track:
- Verification success rate.
- Escalation rate.
- Deflection rate.
- Average handle time after escalation.
- Human agent edits to AI recommendation.
- Sentiment distribution.
- Cases where the agent selected the wrong action.
- Cases where the LWC recommendation was ignored.
The best feedback loop is not “Did the AI answer?” It is “Did the AI reduce the amount of work needed to resolve the customer’s issue safely?”
Testing The Agent
Testing an Agentforce implementation requires more than happy-path testing.
Here are the scenarios I would include before production.
Verification Tests
| Scenario | Expected Result |
|---|---|
| Phone available, one Contact found | Greet by name and ask for email |
| Email available, one Contact found | Greet by name and ask for phone |
| Phone and email match same Contact | Mark verified |
| Email and phone do not match | Do not disclose data |
| Multiple Contacts match | Ask for more detail or escalate |
| Customer refuses verification | Escalate |
| Customer provides order number before verification | Ask for verification first |
Order Tests
| Scenario | Expected Result |
|---|---|
| One recent order | Provide order status |
| Multiple recent orders | Ask which order |
| No orders found | Explain and escalate if needed |
| Delayed shipment | Explain delay using available data |
| Tracking unavailable | Do not invent tracking |
Return And Refund Tests
| Scenario | Expected Result |
|---|---|
| Return eligible | Explain next step |
| Return window expired | Explain policy and escalation option |
| Refund issued | Provide confirmed status |
| Refund pending | Explain current stage |
| Refund data unavailable | Escalate |
Sentiment Tests
| Customer Message | Expected Tone | Sentiment |
|---|---|---|
| “This is ridiculous. I want someone now.” | Angry | Red |
| “I’m frustrated. This is the second delay.” | Frustrated | Red |
| “That’s disappointing.” | Disappointed | Yellow |
| “Okay, thanks for checking.” | Satisfied | Green |
| “Great, that helps.” | Happy | Green |
LWC Tests
| Case Field State | Expected Card |
|---|---|
| Sentiment Level = Red | Red card |
| Sentiment Level = Yellow | Yellow card |
| Sentiment Level = Green | Green card |
| No sentiment yet | Yellow default |
| No recommendation yet | Empty-state message |
Common Implementation Mistakes
Mistake 1: Letting The Agent Verify And Answer In One Step
Verification should happen before customer-specific answers. Combining verification and order lookup in one action makes the system harder to reason about and harder to audit.
Mistake 2: Treating Knowledge As Customer Data
Knowledge is good for general policy. It is not enough for customer-specific refund status.
The agent can answer:
Refunds are generally processed after returned items pass inspection.
But it should not answer:
Your refund will arrive tomorrow.
Unless a trusted system says so.
Mistake 3: Writing Long Case Summaries
A long summary is another transcript. The Case brief should be short, structured, and operational.
The human agent should understand three things within seconds:
- What happened?
- How does the customer feel?
- What should I do next?
Mistake 4: Making Color The Only Signal
Color helps, but color alone is not enough. The card should also show the tone text: Angry, Frustrated, Disappointed, Neutral, Happy, or Satisfied.
That supports accessibility and avoids ambiguity.
Mistake 5: Mapping Sentiment In The Prompt Only
Let the agent classify tone, but map tone to card color in deterministic logic.
Prompts are good for interpretation. Code is better for policy.
Wrapping Up
The interesting part of this Agentforce build is not that the agent can answer order questions. That is useful, but it is not the deeper design point.
The deeper point is that customer service automation needs memory, judgment, safety, and handoff readiness.
Verification gives the agent permission to answer.
Actions give the agent trusted business data.
Subagents give the work shape.
Case fields give the conversation a durable home.
The LWC card gives the human agent immediate context.
The color gives the agent a visual cue before they type the next response.
When these pieces are designed together, Agentforce becomes more than a front-line bot. It becomes a participant in the service process. It helps the customer when the path is safe and clear. It helps the human agent when the path needs judgment.
That is where the implementation starts to feel less like “AI support” and more like a proper service architecture.
The goal is not to replace the human agent.
The goal is to make sure that when the human agent enters the conversation, they enter with context, empathy, and the next best action already in front of them.

Leave a Reply