All delegates use a NativeEventEmitter on the JS side to receive events from the native layer.
Why Register Before configure()?
The recommended order is to register delegates before calling configure(). Here’s why:
Logger: The SDK may emit log messages during initialization. If registered after configure(), those early messages are lost.
Navigation: The navigation bridge is passed to AgentforceConfiguration during configure(). Registering afterward still works because the bridge checks dynamically, but registering before is cleaner.
View Provider: Can be registered before or after configure() without issue. The native view provider checks the component map dynamically.
Logger Delegate
The Logger delegate forwards log messages from the native Agentforce SDK to your JavaScript code. This is useful for debugging, analytics, and monitoring.
The Navigation delegate lets your app handle navigation requests from the Agentforce SDK. When the agent presents a link, record reference, or other navigable element that the user taps, the SDK emits a navigation event.
Setup
1import { Linking } from "react-native";2import { AgentforceService } from "@salesforce/react-native-agentforce";34AgentforceService.setNavigationDelegate({5 onNavigate(request) {6 switch (request.type) {7 case "link":8 if (request.uri) {9 Linking.openURL(request.uri as string);10 }11 break;1213 case "record":14 // Navigate to a record detail screen in your app15 navigation.navigate("RecordDetail", {16 recordId: request.recordId,17 objectType: request.objectType,18 });19 break;2021 case "quickAction":22 console.log(`Quick action requested: ${request.actionName}`);23 break;2425 case "objectHome":26 navigation.navigate("ObjectList", {27 objectType: request.objectType,28 });29 break;3031 default:32 console.log("Unhandled navigation:", JSON.stringify(request));33 }34 },35});
Navigation Request Types
Type
Description
Fields
record
Navigate to a Salesforce record
recordId, objectType, pageReference?
link
Open an external or internal URL
uri, pageReference?
quickAction
Execute a Salesforce quick action
actionName, recordId?, objectType?
pageReference
Navigate to a Lightning page reference
pageReference
objectHome
Navigate to an object’s home/list page
objectType, pageReference?
app
Navigate to an app or external package
packageName, uri?
unknown
Catch-all for unrecognized types
raw
Clear the Delegate
1AgentforceService.clearNavigationDelegate();
View Provider Delegate
The View Provider delegate allows you to replace native SDK output views with custom React Native components. When the SDK renders a component type that matches your registered map, your React Native component is rendered instead.
Setup
There are two parts to registering a custom view:
Part 1: Register the React Native component with AppRegistry
1import { AppRegistry } from "react-native";2import { ViewProviderComponentData } from "@salesforce/react-native-agentforce";34function CustomRichTextView({ componentData }: { componentData: ViewProviderComponentData }) {5 const text = componentData.properties.text as string;6 return (7 <View style={{ padding: 12 }}>8 <Text style={{ fontSize: 16 }}>{text}</Text>9 </View>10 );11}1213// Register it with AppRegistry14AppRegistry.registerComponent("CustomRichTextView", () => CustomRichTextView);
Part 2: Register the component map with the bridge
Register the component and mapping in your App.tsx:
1import { AppRegistry } from "react-native";2import CustomAgentforceView from "./CustomAgentforceView";3import { AgentforceService } from "@salesforce/react-native-agentforce";45// Register the component with AppRegistry -- this makes it available6// for the native bridge to render via RCTRootView / ReactRootView.7AppRegistry.registerComponent("CustomAgentforceView", () => CustomAgentforceView);89// Register the mapping with the bridge10async function setupCustomViews() {11 await AgentforceService.setViewProviderDelegate({12 componentMap: {13 "copilot/richText": "CustomAgentforceView",14 "copilot/markdown": "CustomAgentforceView",15 "copilot/recordInfo": "CustomAgentforceView",16 "copilot/list": "CustomAgentforceView",17 },18 });19}2021// Call during app initialization22setupCustomViews();
When you register a View Provider, the following flow occurs:
You register a componentMap mapping SDK definition strings to React Native component names.
The native bridge stores this map in BridgeViewProvider.
When the SDK needs to render a view, it calls canHandle(definition) on the view provider.
If the definition matches a key in the map, the provider returns true.
The SDK then calls view() (iOS) or GetView() (Android), which creates an RCTRootView (iOS) or ReactRootView (Android).
Your React Native component is rendered, receiving componentData as its initial props containing the definition, name, properties, and any subComponents.
Feature Flag Requirement
The enableCustomViewProvider feature flag must be true: