Quickly Creating Cases from the Salesforce Service Console using Utility Actions

A practical guide to building a Service Console utility that lets agents capture case details quickly via an Aura-wrapped Lightning Web Component (LWC). Includes architecture, code snippets (Aura, LWC, Apex), and best practices for error handling and performance.

Overview

Call center agents need fast, reliable ways to capture case details while on a call. This post explains how to build a utility action for the Salesforce Service Console that opens a standalone LWC to capture case information, associate the case with a Contact record when available, and handle invalid contexts and performance delays gracefully.

Use case

Typical scenarios include:

  • Dual-monitor setups where the utility is used on a secondary screen.
  • Agents searching for contacts by PII (SSN, DOB, Name) while on calls.
  • Contact records that may load slowly due to backend latency.
  • Need to capture case details immediately and link them once the contact is available.

Solution architecture

The solution uses three parts:

  • Aura component as a wrapper to reliably pass recordId into the LWC.
  • Lightning Web Component (LWC) to provide the UI for capturing case details and invoking Apex to insert the Case.
  • Apex controller to insert the Case record securely from the LWC.

Why use Aura as a wrapper?

Sometimes LWC cannot reliably receive the recordId when launched from certain console contexts. Wrapping the LWC in a lightweight Aura component (using force:hasRecordId) ensures the recordId is consistently available and passed into the LWC.

Key features

  • Open the utility in a separate window so agents can multitask.
  • Search contacts by PII while continuing to type case details.
  • Link the case to a Contact when the record is loaded; prevent saves if context is invalid.
  • Minimize the utility programmatically to clear the screen while keeping data preserved.

Best practices

  • Validate the recordId prefix (e.g., ‘003’ for Contact) before attempting to set the ContactId on the Case.
  • Keep the Aura wrapper minimal — it should only capture recordId and pass it to the LWC.
  • Use optimistic UI where possible: let agents enter case details while contact data is still loading.
  • Handle Apex errors cleanly and show actionable toast messages to users.

Code snippets

Aura wrapper (markup)

<aura:component
implements="force:hasRecordId,flexipage:availableForAllPageTypes,lightning:utilityItem">
    <aura:attribute name="recordId" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<c:createCaseUtility contactId="{!v.recordId}"/>
</aura:component>

Aura controller (client-side JS)

({
    doInit: function (component, event, helper) {
        var recordId = component.get("v.recordId");
        if (!recordId) {
            console.warn("Record ID is undefined. Ensure the utility is launched from a record context.");
        } else {
            console.log("Record ID retrieved:", recordId);
        }
    }
});

LWC template (HTML)

<template>
    <lightning-card>
        <div class="slds-m-left_small slds-m-right_small">
            <!-- Inputs and comboboxes for case fields -->
            <lightning-input type="text" label="Contact Name" value={contactName} disabled></lightning-input>
            <lightning-input type="text" name="Subject" label="Subject" value={subject} data-field="Subject"></lightning-input>
            <lightning-combobox name="Status" label="Status" value={caseStatus} options={statusOptions} onchange={handleInputChange} data-field="CaseStatus"></lightning-combobox>
            <!-- (trimmed for brevity) -->
            <lightning-textarea label="Description" value={description} onchange={handleInputChange} data-field="Description"></lightning-textarea>
            <div class="slds-m-top_medium slds-text-align_right">
                <lightning-button class="slds-m-left_small" label="Save" variant="brand" onclick={handleSave}></lightning-button>
            </div>
        </div>
    </lightning-card>
</template>

LWC JavaScript (controller)

import { LightningElement, wire, api } from 'lwc';
import createCase from '@salesforce/apex/CreateCaseController.createCase';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { minimize, EnclosingUtilityId } from 'lightning/platformUtilityBarApi';
import { getRecord } from 'lightning/uiRecordApi';
const CONTACT_FIELDS = ['Contact.Name','Contact.Phone','Contact.AccountId'];

export default class CreateCaseUtility extends LightningElement {
    contactName;
    contactPhone;
    accountId;
    caseOrigin;
    caseType;
    description;
    caseReason;
    caseStatus;
    subject;

    @wire(EnclosingUtilityId) utilityId;

    currentRecordId;
    @api
    set contactId(value) {
        if (value !== this.currentRecordId) {
            this.currentRecordId = value;
        }
    }
    get contactId() {
        return this.currentRecordId;
    }

    @wire(getRecord, { recordId: '$currentRecordId', fields: CONTACT_FIELDS })
    wiredCase({ error, data }) {
        if (data) {
            this.contactName = data.fields.Name.value;
            this.contactPhone = data.fields.Phone.value;
            this.accountId = data.fields.AccountId.value;
        } else if (error) {
            console.error('Error fetching Contact:', error);
        }
    }

    handleInputChange(event) { /* ... */ }

    resetForm() { /* ... */ }

    async handleMinimize() { /* ... */ }

    showToast(title, message, variant) { /* ... */ }

    validateCaseId() { /* ... */ }

    handleSave() { /* ... */ }
}

Apex controller

public class CreateCaseController {
    @AuraEnabled public static void createCase(Case cse) {
        insert cse;
    }
}

How to add as a utility

Deploy the Aura and LWC bundles, then add the Aura component to the Service Console utility bar. Configure the utility to allow opening in a separate window to enable the dual-monitor workflow.

Conclusion

Using a minimal Aura wrapper and an LWC utility gives call center agents a fast, resilient way to capture case details without losing context. The pattern improves agent efficiency and data accuracy by preserving inputs while waiting for a contact record to load.

This matters for Salesforce admins, developers, and business users because it provides a pragmatic, low-risk enhancement to agent workflows that reduces AHT (average handle time) and improves case quality.