Skip to content

Salesforce Service Cloud Integration

Agent Assist embeds into Salesforce Service Console as a Visualforce iframe in the utility bar. The agent's Salesforce session token is passed to the widget automatically — no OAuth redirect needed. Chat messages are forwarded in real-time via a Lightning Web Component that subscribes to Salesforce's standard Lightning Message Service channels.

Prerequisites

  • Salesforce Service Cloud (Enterprise or higher)
  • Messaging for In-App & Web (MIAW) configured for chat
  • OmniBots Agent Assist deployed (e.g., https://assist.yourdomain.com)
  • Salesforce Admin access
  • OmniBots tenant with assist_mode: "omni" or "google_native"
  • Salesforce CLI (sf) installed for LWC deployment

Step 1: Generate an Embed Token

  1. Open the Agent Assist Admin Portal → Settings → Assist Configuration → Widget
  2. Set CCaaS Provider to Salesforce
  3. Enter the Salesforce Domain (e.g., yourorg.my.salesforce.com)
  4. Add your Salesforce org domains to Allowed Origins:
    • https://yourorg.lightning.force.com
    • https://yourorg.my.salesforce.com
    • https://yourorg--c.develop.vf.force.com (VF page domain)
  5. Click Generate Embed Token — copy the token (starts with eyJ...)

Or via API:

bash
POST /api/v1/assist/widget/embed-token
{
  "origins": [
    "https://yourorg.lightning.force.com",
    "https://yourorg.my.salesforce.com",
    "https://yourorg--c.develop.vf.force.com"
  ],
  "label": "salesforce-production"
}

Save the returned token — you will need it in Step 2.


Step 2: Create a Visualforce Page

The Visualforce page acts as a container for the Agent Assist widget iframe and relays chat messages from the Lightning Web Component.

In Salesforce: Setup → Visualforce Pages → New

FieldValue
LabelAgentAssistWidget
NameAgentAssistWidget
Available for Lightning ExperienceChecked

Paste this code:

html
<apex:page showHeader="false" sidebar="false" standardStylesheets="false"
           applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
<html>
<head>
    <style>
        body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
        iframe { width: 100%; height: 100%; border: none; }
    </style>
</head>
<body>
    <iframe id="omnibots-assist"
        src="https://assist.yourdomain.com/?t=YOUR_EMBED_TOKEN&provider=salesforce&sf_token={!$Api.Session_ID}"
        allow="microphone; clipboard-write"
    ></iframe>

    <!-- Relay: forward postMessages from LWC to widget iframe -->
    <script>
    (function() {
        var widget = document.getElementById('omnibots-assist');

        window.addEventListener('message', function(event) {
            if (!event.data || !widget || !widget.contentWindow) return;
            if (event.data.type === 'sf-message') {
                widget.contentWindow.postMessage(event.data, '*');
                console.log('[AgentAssist VF] Relayed:',
                    event.data.sender,
                    (event.data.content || '').substring(0, 50));
            }
            if (event.data.type === 'sf-chat-ended') {
                widget.contentWindow.postMessage(event.data, '*');
                console.log('[AgentAssist VF] Relayed: chat ended');
            }
        });

        console.log('[AgentAssist VF] Message relay active');
    })();
    </script>
</body>
</html>
</apex:page>

Replace:

  • assist.yourdomain.com with your actual Agent Assist widget domain
  • YOUR_EMBED_TOKEN with the token from Step 1

How it works

{!$Api.Session_ID} is a Salesforce merge field — Salesforce injects the agent's current session token at render time. No OAuth redirect needed because the agent is already logged into Salesforce. Token validation happens server-side in the backend via /services/oauth2/userinfo.

WARNING

Do not add standardController="Case" to the <apex:page> tag. The widget does not read Salesforce record fields, and including a controller causes Unknown property errors.


Step 3: Add as a Utility Bar Item

This puts Agent Assist in the bottom utility bar — always accessible regardless of which record the agent is viewing.

  1. Go to Setup → App Manager
  2. Find your Service Console app → click the dropdown arrow → Edit
  3. Go to Utility Items (Desktop Only)
  4. Click Add Utility Item → select Visualforce Page
  5. Configure:
SettingValue
LabelAI Assist
Iconknowledge or einstein
Visualforce PageAgentAssistWidget
Panel Width420
Panel Height650
Start automaticallyChecked
  1. Click Save

WARNING

Only add the widget in one place (utility bar OR record page, not both). Having it in multiple places causes duplicate RAG queries.


Step 4: Configure Feature Flags

Control what agents see in the widget. In OmniBots Admin Portal → Settings → Assist Configuration → Widget Features:

FeatureRecommended for SalesforceWhy
knowledge_searchOnAgents can manually search KB
quick_repliesOnSuggested responses for chat
follow_up_questionsOnAI follow-ups
transcript_panelOffSalesforce has its own transcript
summary_panelOnConversation summary
send_messageOffAgents reply through Salesforce, not the widget
coachingOnFor supervisors

Step 5: Deploy the Lightning Web Component

The LWC forwards incoming and outgoing chat messages from Salesforce MIAW to the Agent Assist widget in real-time, triggering automatic RAG suggestions.

It uses Lightning Message Service (LMS) with standard Salesforce message channels — the same approach Google CCAI Agent Assist uses for their Salesforce integration.

5.1 Deploy via Salesforce CLI

LWCs cannot be created in Developer Console — they require Salesforce CLI.

The LWC source files are in the repository at salesforce-lwc/:

salesforce-lwc/
  sfdx-project.json
  force-app/main/default/lwc/agentAssistBridge/
    agentAssistBridge.html
    agentAssistBridge.js
    agentAssistBridge.js-meta.xml

Deploy steps:

bash
# 1. Install Salesforce CLI (if not installed)
npm install -g @salesforce/cli

# 2. Navigate to the project
cd salesforce-lwc

# 3. Authorize your Salesforce org (opens browser to log in)
sf org login web --instance-url https://yourorg.my.salesforce.com --set-default

# 4. Deploy the LWC
sf project deploy start --source-dir force-app/main/default/lwc/agentAssistBridge

What the LWC does:

  • Subscribes to three standard Salesforce LMS message channels:
    • lightning__conversationAgentSend — agent sends a message
    • lightning__conversationEndUserMessage — customer sends a message
    • lightning__conversationEnded — conversation ends
  • On each event, broadcasts postMessage to all iframes on the page (reaches the VF utility bar)
  • The VF page relay script (Step 2) forwards the message to the widget iframe inside it

5.2 Add the LWC to the Messaging Record Page

  1. Open a messaging conversation in Service Console
  2. Click the gear iconEdit Page (Lightning App Builder)
  3. In the left component panel, search for agentAssistBridge
  4. Drag it onto the page layout (anywhere — it is invisible, just subscribes to events)
  5. Click SaveActivate → assign to your org/app/record type

WARNING

The Enhanced Conversation Component must also be on the same page — the LMS message channels only fire when it is present and the conversation is active.

5.3 Verify It Works

  1. Open Service Console with both the AI Assist utility bar and a messaging conversation active
  2. Open browser DevTools → Console
  3. Look for [AgentAssist LWC] Bridge active, recordId: ...
  4. Send a message as the customer — you should see:
    • [AgentAssist LWC] Customer sent: ...
    • [AgentAssist VF] Relayed: EndUser ...
  5. The widget should show RAG suggestions triggered by the message

How It Works

Authentication Flow

Agent logs into Salesforce (already authenticated)


Visualforce page renders iframe with:
  ?t=<embed_token>&sf_token={!$Api.Session_ID}

        │ 1. Bootstrap: GET /api/v1/assist/widget/bootstrap?t=<embed_token>
        │    Returns: { provider: "salesforce", provider_config: { environment } }

        │ 2. Provider reads sf_token from URL params
        │    (No redirect — agent is already logged into Salesforce)

        │ 3. Token exchange: POST /api/v1/auth/token-exchange
        │    { provider: "salesforce", provider_token: <sf_token>, embed_token }
        │    Backend validates sf_token server-side via /services/oauth2/userinfo
        │    Returns: { token: "<omnibots_jwt>", agent_info: { name, email } }

        │ 4. Socket.IO connect with OmniBots JWT

assist-connector-service → real-time events via Socket.IO

Chat Message Flow

Customer sends message in Salesforce MIAW


Salesforce LMS: lightning__conversationEndUserMessage


agentAssistBridge LWC (subscribes via lightning/messageService)
  → broadcastToWidget() posts to all frames


VF page iframe receives postMessage → relay script
  → forwards to widget iframe inside


Agent Assist Widget (SalesforceProvider.onMessage)
  → forwardDigitalMessage() → triggerRagQuery()


assist-connector-service → RAG pipeline → suggestions appear in widget

Troubleshooting

IssueFix
Widget shows blankCheck allowed_origins includes your SF domain (.lightning.force.com, .my.salesforce.com, and --c...vf.force.com)
Stuck on "Authenticating..."Ensure VF page passes {!$Api.Session_ID} in the iframe URL
Unknown property 'Case.ContactId'Remove standardController="Case" from the VF page — use the simple iframe page from Step 2
Salesforce token validation failedVerify the Salesforce Domain is set correctly in OmniBots Admin Portal (Step 1)
No RAG suggestions from chatVerify the LWC is deployed and on the messaging record page. Check console for [AgentAssist LWC] logs
[AgentAssist LWC] logs but no [AgentAssist VF] RelayedThe VF utility bar iframe is not receiving postMessages. Verify the VF page has the relay script from Step 2
Duplicate RAG queriesWidget is loaded in multiple places. Keep it in one location only
CORS errors on userinfoToken validation happens server-side. If you see CORS errors, ensure the widget is NOT calling Salesforce APIs from the browser
Widget disconnectsCheck Socket.IO reconnection; verify JWT expiry; ensure embed token has not expired
LWC not visible in App BuilderLWC must be deployed via Salesforce CLI (sf project deploy start). Developer Console cannot create LWCs
sf_token not injectedVerify the VF page uses {!$Api.Session_ID} merge field (not a hardcoded value)

Next Steps

OmniBots Agent Assist