---
schema_version: "1"
id: 5d70a1afd7dd6c81d3258ef078fd2e94a6c3ae22cc498d2595f621e2c488bbca
title: Manage Conversations in React Native
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/genai/agentforce-mobile-sdk/guides/react-native/agentforce-mobile-sdk-react-native-conversations.md
canonical_url: https://developer.salesforce.com/docs/ai/agentforce-mobile-sdk/guide/agentforce-mobile-sdk-react-native-conversations.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 126779537f3cdc596e7064bae04c419a557ae2424562b2a2f447ef05d9d1c3aa
products:
  - Agentforce Mobile SDK
  - Agentforce and Einstein Generative AI
---
# 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.

```tsx
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.

```tsx
// 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

```tsx
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:

```tsx
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

```tsx
// 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:

```tsx
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()`:

```tsx
// 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

```tsx
// 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:

```tsx
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

- [Configure the SDK](https://developer.salesforce.com/docs/ai/agentforce-mobile-sdk/guide/agentforce-mobile-sdk-react-native-integration.md)
- [Delegates](https://developer.salesforce.com/docs/ai/agentforce-mobile-sdk/guide/agentforce-mobile-sdk-react-native-delegates.md)
- [Limitations](https://developer.salesforce.com/docs/ai/agentforce-mobile-sdk/guide/agentforce-mobile-sdk-react-native-limitations.md)
