Building An Agentforce Service Agent for Order Updates, Returns, Refunds and Human Agent Handoffs

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:

  1. Help the customer directly when it can safely do so.
  2. 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 ContextAgent GreetingVerification 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 emailGeneric greetingAsk for email and phone
Multiple matchesGeneric greetingAsk for email and phone
MismatchGeneric greetingEscalate 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:

  1. Customer enters through a channel.
  2. Agent receives the message and available context.
  3. Agent verifies the customer.
  4. Agent retrieves the right operational data.
  5. Agent responds if it can.
  6. Agent escalates if needed.
  7. Agent writes guidance to the Case.
  8. 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 LabelAPI NameTypePurpose
Customer ToneCustomer_Tone__cPicklistAngry, Frustrated, Disappointed, Neutral, Happy, Satisfied
Sentiment LevelSentiment_Level__cPicklistRed, Yellow, Green
Agent RecommendationAgent_Recommendation__cLong Text AreaSuggested response approach for human agent
Agent BriefAgent_Brief__cLong Text AreaSummary of conversation, order context, and unresolved issue
Verification StatusVerification_Status__cPicklistNot Started, Pending, Verified, Failed
Verified ContactVerified_Contact__cLookup(Contact)Contact verified during conversation
Last Verified EmailLast_Verified_Email__cEmailEmail used for verification
Last Verified PhoneLast_Verified_Phone__cPhonePhone used for verification
Escalation ReasonEscalation_Reason__cLong Text AreaWhy the agent escalated
Last Agent ActionLast_Agent_Action__cTextLast 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:

ActionTypePurpose
Verify CustomerApex or FlowMatch phone and email to Contact
Get Order UpdatesApex, Flow, or APIRetrieve order status
Get Tracking InfoApex or MuleSoft APIRetrieve shipment tracking
Check Return EligibilityFlow or ApexDetermine return eligibility
Get Refund StatusApex or APIRetrieve refund status
Generate Case BriefPrompt Template or ApexSummarize customer issue
Update Case IntelligenceApex or FlowWrite 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:

  1. Email alone may not be enough to verify the customer.
  2. The query assumes one matching Contact.
  3. It assumes the latest order is the order the customer means.
  4. It exposes a tracking number immediately.
  5. It has no escalation behavior.
  6. It writes nothing useful back to Case.
  7. 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:

  • OrderLookupService
  • TrackingService
  • ReturnEligibilityService
  • RefundStatusService
  • CaseInsightService

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:

  1. Make the customer tone visible.
  2. Make the recommendation visible.
  3. 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 Customer
  • Get Recent Orders
  • Get Order Status
  • Get Tracking Details
  • Check Return Eligibility
  • Get Refund Status
  • Update 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
  • Email
  • 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

ScenarioExpected Result
Phone available, one Contact foundGreet by name and ask for email
Email available, one Contact foundGreet by name and ask for phone
Phone and email match same ContactMark verified
Email and phone do not matchDo not disclose data
Multiple Contacts matchAsk for more detail or escalate
Customer refuses verificationEscalate
Customer provides order number before verificationAsk for verification first

Order Tests

ScenarioExpected Result
One recent orderProvide order status
Multiple recent ordersAsk which order
No orders foundExplain and escalate if needed
Delayed shipmentExplain delay using available data
Tracking unavailableDo not invent tracking

Return And Refund Tests

ScenarioExpected Result
Return eligibleExplain next step
Return window expiredExplain policy and escalation option
Refund issuedProvide confirmed status
Refund pendingExplain current stage
Refund data unavailableEscalate

Sentiment Tests

Customer MessageExpected ToneSentiment
“This is ridiculous. I want someone now.”AngryRed
“I’m frustrated. This is the second delay.”FrustratedRed
“That’s disappointing.”DisappointedYellow
“Okay, thanks for checking.”SatisfiedGreen
“Great, that helps.”HappyGreen

LWC Tests

Case Field StateExpected Card
Sentiment Level = RedRed card
Sentiment Level = YellowYellow card
Sentiment Level = GreenGreen card
No sentiment yetYellow default
No recommendation yetEmpty-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:

  1. What happened?
  2. How does the customer feel?
  3. 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.

Was this helpful?

Leave a Reply

Your email address will not be published. Required fields are marked *

Ready to Upskill and Grow Your Career?

Explore our Skill-Building Cohorts and take the next step toward your dream career.