Theme
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
- Open the Agent Assist Admin Portal → Settings → Assist Configuration → Widget
- Set CCaaS Provider to
Salesforce - Enter the Salesforce Domain (e.g.,
yourorg.my.salesforce.com) - Add your Salesforce org domains to Allowed Origins:
https://yourorg.lightning.force.comhttps://yourorg.my.salesforce.comhttps://yourorg--c.develop.vf.force.com(VF page domain)
- 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
| Field | Value |
|---|---|
| Label | AgentAssistWidget |
| Name | AgentAssistWidget |
| Available for Lightning Experience | Checked |
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.comwith your actual Agent Assist widget domainYOUR_EMBED_TOKENwith 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.
- Go to Setup → App Manager
- Find your Service Console app → click the dropdown arrow → Edit
- Go to Utility Items (Desktop Only)
- Click Add Utility Item → select Visualforce Page
- Configure:
| Setting | Value |
|---|---|
| Label | AI Assist |
| Icon | knowledge or einstein |
| Visualforce Page | AgentAssistWidget |
| Panel Width | 420 |
| Panel Height | 650 |
| Start automatically | Checked |
- 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:
| Feature | Recommended for Salesforce | Why |
|---|---|---|
knowledge_search | On | Agents can manually search KB |
quick_replies | On | Suggested responses for chat |
follow_up_questions | On | AI follow-ups |
transcript_panel | Off | Salesforce has its own transcript |
summary_panel | On | Conversation summary |
send_message | Off | Agents reply through Salesforce, not the widget |
coaching | On | For 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.xmlDeploy 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/agentAssistBridgeWhat the LWC does:
- Subscribes to three standard Salesforce LMS message channels:
lightning__conversationAgentSend— agent sends a messagelightning__conversationEndUserMessage— customer sends a messagelightning__conversationEnded— conversation ends
- On each event, broadcasts
postMessageto 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
- Open a messaging conversation in Service Console
- Click the gear icon → Edit Page (Lightning App Builder)
- In the left component panel, search for
agentAssistBridge - Drag it onto the page layout (anywhere — it is invisible, just subscribes to events)
- Click Save → Activate → 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
- Open Service Console with both the AI Assist utility bar and a messaging conversation active
- Open browser DevTools → Console
- Look for
[AgentAssist LWC] Bridge active, recordId: ... - Send a message as the customer — you should see:
[AgentAssist LWC] Customer sent: ...[AgentAssist VF] Relayed: EndUser ...
- 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.IOChat 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 widgetTroubleshooting
| Issue | Fix |
|---|---|
| Widget shows blank | Check 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 failed | Verify the Salesforce Domain is set correctly in OmniBots Admin Portal (Step 1) |
| No RAG suggestions from chat | Verify the LWC is deployed and on the messaging record page. Check console for [AgentAssist LWC] logs |
[AgentAssist LWC] logs but no [AgentAssist VF] Relayed | The VF utility bar iframe is not receiving postMessages. Verify the VF page has the relay script from Step 2 |
| Duplicate RAG queries | Widget is loaded in multiple places. Keep it in one location only |
| CORS errors on userinfo | Token validation happens server-side. If you see CORS errors, ensure the widget is NOT calling Salesforce APIs from the browser |
| Widget disconnects | Check Socket.IO reconnection; verify JWT expiry; ensure embed token has not expired |
| LWC not visible in App Builder | LWC must be deployed via Salesforce CLI (sf project deploy start). Developer Console cannot create LWCs |
sf_token not injected | Verify the VF page uses {!$Api.Session_ID} merge field (not a hardcoded value) |
Next Steps
- Widget Deployment — General widget deployment reference
- CCaaS Integration — Other CCaaS platform integrations
- Agent Getting Started — How agents interact with the widget
- Feature Toggles — Full list of widget feature flags
