Manage Conversations in React Native

Learn how to launch, manage, and enrich Agentforce conversations in your React Native application.

Launch a Conversation

There are two methods for opening the conversation UI:

launchConversation()

Opens the conversation UI. If an existing conversation is available, it's preserved and the user can continue where they left off.

import { AgentforceService } from "@salesforce/react-native-agentforce";

// Must configure first
await AgentforceService.configure({
  /* ... */
});

// Launch -- resumes existing conversation if available
await AgentforceService.launchConversation();

This is the recommended method for most use cases. It avoids discarding conversation history and provides a smoother user experience.

startNewConversation()

Closes any existing conversation and starts fresh. The previous conversation is terminated and a new one is created.

// Force a fresh conversation
await AgentforceService.startNewConversation();

Use this when you explicitly want to discard the previous conversation, for example, when the user switches accounts, resolves an issue, or navigates to a different context.

Preconditions

Both methods require:

  1. The SDK must be configured via configure(). If not, the native module rejects with NOT_CONFIGURED.
  2. On Android, a current Activity must be available. If not, the promise rejects with ERROR: Activity not available.

Error Handling

try {
  await AgentforceService.launchConversation();
} catch (error) {
  // error.code can be:
  //   'NOT_CONFIGURED' -- configure() was not called
  //   'LAUNCH_ERROR'   -- SDK failed to start session (iOS)
  //   'ERROR'          -- general error (Android)
  console.error("Launch failed:", error.message);
}

Close a Conversation

Terminate the current conversation and dismiss the conversation UI:

const success = await AgentforceService.closeConversation();

The user can also close the conversation by:

  • iOS: Tapping the close button in the chat view's top bar
  • Android: Tapping the back arrow in the toolbar

Conversation Lifecycle

Understanding how conversations are managed helps you build better user experiences.

Conversation Reuse

Calling launchConversation() multiple times reuses the same conversation object. This means:

  • The user sees their previous messages when re-opening the chat.
  • The agent retains context from the ongoing session.
  • Additional context set earlier is still active.

When Conversations are Cleared

Conversations are cleared when:

  • closeConversation() is called
  • startNewConversation() is called
  • resetSettings() is called (clears everything)
  • Switching modes (for example, calling configure() with type: 'employee' after previously configuring type: 'service')
  • setEmployeeAgentId() is called with a different agent ID (iOS only)

Additional Context

Additional context provides contextual information to the Agentforce agent during a conversation. This helps the agent deliver more personalized and relevant responses.

note: setAdditionalContext() must be called after launchConversation() or startNewConversation(). The context is set on the active conversation object, which doesn't exist until a conversation is launched.

Basic Usage

// Step 1: Launch conversation
await AgentforceService.launchConversation();

// Step 2: Set context
await AgentforceService.setAdditionalContext({
  variables: [
    { name: "userId", type: "Text", value: "005xx0000001234" },
    { name: "accountId", type: "Text", value: "001xx0000001234" },
    { name: "priority", type: "Text", value: "high" },
  ],
});

Context Variable Types

Type Description Example Value
Text String value 'Jane Smith'
Number Numeric value 15234.56
Boolean True/false true
Date ISO date string '2024-01-15'
DateTime ISO datetime string '2026-03-11T10:30:00.000Z'
Json JSON data (object or string) { language: 'en' }
List Array value ['ORD-001', 'ORD-002']
Money Monetary value 50000
Object Key-value map { street: '123 Main St', city: 'SF' }
Ref Reference value '003xx0000001234AAA'
Variable Generic variable 'sess_abc123'

Validation Rules

The bridge validates context variables before sending them to the native SDK:

  • Type names are case-sensitive. Use 'Text' not 'text', 'Boolean' not 'boolean'. Invalid types cause an error.
  • Each variable must have a non-empty name and type. Missing fields cause an INVALID_CONTEXT error.
  • Validation errors are thrown synchronously before the native call, so you can catch them immediately.
  • The description field is only supported on Android. On iOS, it's silently ignored.

Complete Example with All Types

This example demonstrates all 11 context variable types:

await AgentforceService.setAdditionalContext({
  variables: [
    // Text -- simple string value
    {
      name: "customerName",
      type: "Text",
      value: "Jane Smith",
    },

    // Number -- numeric value (double precision)
    {
      name: "accountBalance",
      type: "Number",
      value: 15234.56,
    },

    // Boolean -- true/false
    {
      name: "isVIPCustomer",
      type: "Boolean",
      value: true,
    },

    // Date -- ISO date string
    {
      name: "memberSince",
      type: "Date",
      value: "2024-01-15",
    },

    // DateTime -- ISO datetime string with timezone
    {
      name: "lastInteraction",
      type: "DateTime",
      value: "2026-03-11T10:30:00.000Z",
    },

    // Json -- JSON data (can be string or object)
    {
      name: "preferences",
      type: "Json",
      value: {
        language: "en",
        timezone: "America/Los_Angeles",
        notifications: true,
      },
    },

    // List -- array of values
    {
      name: "recentOrderIds",
      type: "List",
      value: ["ORD-2026-001", "ORD-2026-002", "ORD-2026-003"],
    },

    // Money -- monetary value
    {
      name: "creditLimit",
      type: "Money",
      value: 50000,
    },

    // Object -- key-value map
    {
      name: "shippingAddress",
      type: "Object",
      value: {
        street: "123 Market Street",
        city: "San Francisco",
        state: "CA",
        zip: "94105",
        country: "US",
      },
    },

    // Ref -- reference to another record
    {
      name: "primaryContactId",
      type: "Ref",
      value: "003xx0000001234AAA",
    },

    // Variable -- generic variable
    {
      name: "sessionToken",
      type: "Variable",
      value: "sess_abc123def456",
    },

    // With description (Android only, ignored on iOS)
    {
      name: "currentCaseId",
      type: "Text",
      value: "500xx0000009876AAA",
      description: "The active support case for this customer",
    },
  ],
});

note: The description field is only supported on Android. On iOS, it's ignored.

Hidden Prechat Fields

Hidden prechat fields let you pass values to the Service Agent prechat form without displaying them to the user. Common use cases include pre-populating a ContactId, AccountId, or session token.

warning: Android Limitation On Android, hidden prechat fields are stored but not sent to the native SDK during session initialization. This feature is fully functional on iOS only. If hidden prechat fields are critical to your use case, use iOS or wait for a future bridge update.

note: Hidden prechat fields only apply to Service Agent conversations. They have no effect for Employee Agent conversations.

Usage

Register hidden prechat fields before calling launchConversation():

// Step 1: Register hidden prechat fields
await AgentforceService.registerHiddenPreChatFields({
  ContactId: "003xx0000001234AAA",
  AccountId: "001xx0000005678AAA",
  Subject: "Mobile App Support Request",
});

// Step 2: Launch conversation
await AgentforceService.launchConversation();

Reading and Clearing Fields

// Read current fields
const fields = await AgentforceService.getHiddenPreChatFields();
console.log(fields); // { ContactId: '003xx...', AccountId: '001xx...' }

// Clear all fields
await AgentforceService.clearHiddenPreChatFields();

Complete Hidden Prechat Example

This example shows the full flow of configuring, registering hidden fields, and launching:

import React, { useState } from "react";
import { View, Button, Text, Alert, StyleSheet } from "react-native";
import { AgentforceService, HiddenPreChatFields } from "@salesforce/react-native-agentforce";

export default function ServiceAgentWithPrechat() {
  const [currentFields, setCurrentFields] = useState<HiddenPreChatFields>({});

  const handleLaunchWithFields = async () => {
    try {
      // Step 1: Configure
      await AgentforceService.configure({
        type: "service",
        serviceApiURL: "https://mycompany-support.my.salesforce-scrt.com",
        organizationId: "00Dxx0000001234EAA",
        esDeveloperName: "My_Service_Agent",
      });

      // Step 2: Register hidden fields (before launch)
      await AgentforceService.registerHiddenPreChatFields({
        ContactId: "003xx0000001234AAA",
        AccountId: "001xx0000005678AAA",
        Subject: "Mobile App Support",
        Origin: "Mobile",
        Priority: "High",
      });

      // Read back to verify
      const fields = await AgentforceService.getHiddenPreChatFields();
      setCurrentFields(fields);

      // Step 3: Launch -- hidden fields are sent during session initialization
      await AgentforceService.launchConversation();
    } catch (error) {
      Alert.alert("Error", String(error));
    }
  };

  const handleClearFields = async () => {
    await AgentforceService.clearHiddenPreChatFields();
    setCurrentFields({});
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hidden Prechat Fields</Text>

      <View style={styles.fieldList}>
        {Object.entries(currentFields).map(([key, value]) => (
          <Text key={key} style={styles.field}>
            {key}: {value}
          </Text>
        ))}
        {Object.keys(currentFields).length === 0 && (
          <Text style={styles.empty}>No fields registered</Text>
        )}
      </View>

      <Button title="Launch with Fields" onPress={handleLaunchWithFields} />
      <View style={styles.spacer} />
      <Button title="Clear Fields" onPress={handleClearFields} color="red" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 24 },
  title: { fontSize: 20, fontWeight: "bold", marginBottom: 16 },
  fieldList: { marginBottom: 24, padding: 12, backgroundColor: "#f5f5f5", borderRadius: 8 },
  field: { fontSize: 14, marginBottom: 4, fontFamily: "monospace" },
  empty: { color: "#999", fontStyle: "italic" },
  spacer: { height: 12 },
});

Platform Presentation Differences

The conversation UI is presented differently on each platform.

iOS

The conversation UI is presented as a full-screen modal:

  • Dismissal triggers onContainerClose, which calls dismiss(animated: true).
  • The SDK's built-in top bar is shown.
  • The chat view is a SwiftUI view created by the SDK.

Android

The conversation UI is launched as a separate Activity:

  • The user closes the conversation by tapping the back arrow.
  • It displays a Material 3 Scaffold with a Salesforce-blue top app bar.
  • AgentforceConversationActivity is a ComponentActivity that uses Jetpack Compose.
Aspect iOS Android
Presentation Full-screen modal New Activity
Top bar SDK-provided Custom Material 3 TopAppBar
Close mechanism onContainerClose callback Back arrow / system back
Transition Cover vertical animation Standard activity transition

See Also