Custom Lightning Types on Mobile with the Agentforce Mobile SDK

Use Custom Lightning Types (CLTs) to control how structured agent action data appears in Agentforce on mobile. In apps that integrate the Agentforce Mobile SDK, you can route CLT output and input through native UI (SwiftUI or Jetpack Compose) by implementing a view provider and using the AFMobileCustom/ prefix in your CLT metadata.

For LWC-based CLT overrides in the Salesforce mobile app, see Custom Lightning Types in the Salesforce Mobile App in Salesforce Help.

Configure CLT metadata for mobile 

Agentforce CLT UI configuration is organized by channel, similar to desktop. For Agentforce on mobile, add a lightningMobileGenAi folder next to your existing channel folders (for example lightningDesktopGenAi). You can configure desktop and mobile independently.

Output (renderer) — example layout for a type named flightResponse:

1+--lightningTypes
2    +--flightResponse
3        +--schema.json
4        +--lightningDesktopGenAi
5            +--renderer.json
6        +--lightningMobileGenAi
7            +--renderer.json

Input (editor) — example layout for a type named flightFilter:

1+--lightningTypes
2    +--flightFilter
3        +--schema.json
4        +--lightningDesktopGenAi
5            +--editor.json
6        +--lightningMobileGenAi
7            +--editor.json

Renderer override for native mobile (output) 

In lightningMobileGenAi/renderer.json, use the top-level $ override and set definition to an AFMobileCustom/… identifier that your app handles.

1{
2  "renderer": {
3    "componentOverrides": {
4      "$": {
5        "definition": "AFMobileCustom/FlightDetails"
6      }
7    }
8  }
9}

Map schema fields to native properties 

If your native view expects different property names than the schema, use attributes (same idea as desktop channel overrides):

1{
2  "renderer": {
3    "componentOverrides": {
4      "$": {
5        "definition": "AFMobileCustom/FlightDetails",
6        "attributes": {
7          "flightCost": "{!$attrs.price}",
8          "discountPercentage": "{!$attrs.discountPercentage}"
9        }
10      }
11    }
12  }
13}

Editor override for native mobile (input) 

In lightningMobileGenAi/editor.json:

1{
2  "editor": {
3    "componentOverrides": {
4      "$": {
5        "definition": "AFMobileCustom/FlightFilter"
6      }
7    }
8  }
9}

The editor is shown when the type is used as input in the mobile conversation; implementation uses the same view provider pattern as renderers.

Implement native UI on iOS 

  1. Conform to AgentforceViewProviding.
  2. Return true from canHandle(type:) for each AFMobileCustom/… definition you support.
  3. Return the appropriate SwiftUI view from view(for:data:).
Example view provider (SwiftUI)
1import SwiftUI
2import AgentforceSDK
3
4class FlightDetailsViewProvider: AgentforceViewProviding {
5    func canHandle(type: String) -> Bool {
6        type == "AFMobileCustom/FlightDetails"
7    }
8
9    @MainActor
10    func view(for type: String, data: [String: Any]) -> AnyView {
11        switch type {
12        case "AFMobileCustom/FlightDetails":
13            return AnyView(FlightDetailsView(data: data))
14        default:
15            return AnyView(EmptyView())
16        }
17    }
18}

Register the provider when you create AgentforceClient. Pass viewProvider along with credentialProvider, mode, and other required parameters for your agent type (employee, service, or full configuration), as described in Integrate Agentforce SDK.

Register the view provider
1let client = AgentforceClient(
2    credentialProvider: credentialProvider,
3    mode: .employeeAgent(config),
4    viewProvider: FlightDetailsViewProvider(),
5    themeManager: AgentforceDefaultThemeManager()
6)

For more on client setup, see iOS configuration in the Agentforce Mobile SDK reference (including AgentforceClient and AgentforceConfiguration).

Implement native UI on Android 

  1. Implement AgentforceViewProvider.
  2. Return true from canHandle(definition:) for each AFMobileCustom/… definition.
  3. In GetView, read payload data (for example from AgentforceComponent / view.properties) and compose your UI.
Example view provider (Jetpack Compose)
1class FlightDetailsViewProvider : AgentforceViewProvider {
2    override fun canHandle(definition: String): Boolean {
3        return definition == "AFMobileCustom/FlightDetails"
4    }
5
6    @Composable
7    override fun GetView(modifier: Modifier, view: AgentforceComponent) {
8        val flightData = view.properties["value"]
9        FlightDetailsCard(modifier = modifier, data = flightData)
10    }
11}

Register the provider on AgentforceConfiguration:

Register the view provider
1val config = AgentforceConfiguration.builder(
2    authCredentialProvider = /* your provider */
3)
4    .setViewProvider(FlightDetailsViewProvider())
5    // ... other configuration
6    .build()

See Integrate Agentforce SDK and Android configuration in the Agentforce Mobile SDK reference for setViewProvider and related builder options.

Handle multiple definitions in one provider 

You can implement canHandle / GetView (or view(for:data:) on iOS) for several AFMobileCustom/… strings in a single class.

iOS (SwiftUI)

Single provider for renderer and editor
1class MyAppViewProvider: AgentforceViewProviding {
2    func canHandle(type: String) -> Bool {
3        type == "AFMobileCustom/FlightDetails" ||
4        type == "AFMobileCustom/FlightFilter"
5    }
6
7    @MainActor
8    func view(for type: String, data: [String: Any]) -> AnyView {
9        switch type {
10        case "AFMobileCustom/FlightDetails":
11            return AnyView(FlightDetailsView(data: data))
12        case "AFMobileCustom/FlightFilter":
13            return AnyView(FlightFilterView(data: data))
14        default:
15            return AnyView(EmptyView())
16        }
17    }
18}

Android (Jetpack Compose)

Single provider for renderer and editor
1class MyAppViewProvider : AgentforceViewProvider {
2    override fun canHandle(definition: String): Boolean {
3        return definition in listOf(
4            "AFMobileCustom/FlightDetails",
5            "AFMobileCustom/FlightFilter"
6        )
7    }
8
9    @Composable
10    override fun GetView(modifier: Modifier, view: AgentforceComponent) {
11        when (view.definition) {
12            "AFMobileCustom/FlightDetails" ->
13                FlightDetailsCard(modifier = modifier, data = view.properties["value"])
14            "AFMobileCustom/FlightFilter" ->
15                FlightFilterEditor(modifier = modifier, data = view.properties["value"])
16            else -> { /* no-op */ }
17        }
18    }
19}

React Native apps 

Custom Lightning Types are supported in apps that use the Agentforce React Native SDK when you render them with native-style overrides: CLT metadata that uses the AFMobileCustom/… prefix, implemented through the native iOS and Android SDKs behind the bridge.

  1. Enable enableCustomViewProvider in feature flags.
  2. Register a View Provider delegate and map each AFMobileCustom/… definition string to a React Native component (registered with AppRegistry), the same way you map other SDK component definitions. See Delegates.

Tip: Before mapping a definition in your componentMap, log the actual definition prop that the native SDK sends to the rendered component. The native canHandle() lookup is an exact string match — any mismatch (casing, extra whitespace, typo) silently renders nothing.

Not supported in React Native today — using Lightning web components (LWC) as the CLT renderer or editor inside the bridge, and using React web components inside CLT. Those UI paths are separate from the native-override flow above. For details and caveats, see React Native SDK Limitations.

See also