Skip to main content
The SDK does not force a launcher UI. Use the hook to connect Sagepilot to your own button, tab, badge, or help screen.
import { Pressable, Text } from "react-native";
import { useSagepilotChat } from "@sagepilot-ai/react-native-sdk";

export function SupportButton() {
  const { configured, unreadCount, presentMessages } = useSagepilotChat();

  return (
    <Pressable disabled={!configured} onPress={presentMessages}>
      <Text>
        Support{unreadCount > 0 ? ` (${unreadCount})` : ""}
      </Text>
    </Pressable>
  );
}

Open helpers

import { SagepilotChat } from "@sagepilot-ai/react-native-sdk";

SagepilotChat.present();
SagepilotChat.presentMessages();
await SagepilotChat.presentMessageComposer("I need help with my order");
await SagepilotChat.presentMessageComposer("I need help with my order", { mode: "auto" });
await SagepilotChat.presentMessageComposer("Start a new request", { mode: "new" });
await SagepilotChat.presentMessageComposer("I need help with this order", { chatId: savedChatId });
presentMessageComposer(message) uses { mode: "auto" } by default. It pre-fills the composer and lets Sagepilot reuse an existing conversation when one is available. If there is no existing conversation, Sagepilot starts a new one when the customer sends the message. Use { mode: "new" } only when the button or workflow should always start a fresh conversation. Use { chatId } when an app-owned surface should reopen a specific conversation, such as an order help button. presentMessageComposer() returns boolean by default. If behavior.waitForIdentifyBeforeComposer is true and identify() is already in flight, it returns Promise<boolean> and waits up to 60 seconds for identity to finish before opening. You can await it in both cases. For authenticated support flows, enable behavior.waitForIdentifyBeforeComposer and call identify() before opening chat:
const opened = await SagepilotChat.presentMessageComposer("I need help with my order");
Subscribe to conversation creation when your app needs to store a newly created chat ID:
await SagepilotChat.presentMessageComposer("I need help with this order", {
  mode: "new",
  metadata: { source: "order_help", orderId },
  onConversationCreated: ({ chat_id, metadata }) => {
    saveChatForOrder(metadata?.orderId, chat_id);
  }
});

const unsubscribe = SagepilotChat.onConversationCreated(({ chat_id }) => {
  cacheCreatedChat(chat_id);
});

Custom launcher example

import { Pressable, Text, View } from "react-native";
import { MessageCircle } from "lucide-react-native";
import { useSagepilotChat } from "@sagepilot-ai/react-native-sdk";

export function ChatLauncher() {
  const { configured, unreadCount, presentMessages, theme } = useSagepilotChat();
  const launcher = theme.launcher;

  return (
    <Pressable
      accessibilityRole="button"
      accessibilityLabel={launcher.label}
      disabled={!configured}
      onPress={presentMessages}
      style={({ pressed }) => ({
        alignItems: "center",
        backgroundColor: !configured
          ? launcher.disabledButtonColor
          : pressed
            ? launcher.pressedButtonColor
            : launcher.buttonColor,
        borderColor: !configured ? launcher.disabledBorderColor : launcher.borderColor,
        borderRadius: 28,
        borderWidth: 1,
        height: 56,
        justifyContent: "center",
        width: 56
      })}
    >
      <MessageCircle
        color={!configured ? launcher.disabledContentColor : launcher.iconColor}
        fill={!configured ? launcher.disabledContentColor : launcher.iconInsideColor}
        size={24}
      />
      {unreadCount > 0 ? (
        <View
          style={{
            alignItems: "center",
            backgroundColor: launcher.unreadBadgeColor,
            borderColor: launcher.unreadBadgeBorderColor,
            borderRadius: 9,
            borderWidth: 1,
            minWidth: 18,
            paddingHorizontal: 4,
            position: "absolute",
            right: -2,
            top: -2
          }}
        >
          <Text style={{ color: launcher.unreadBadgeTextColor, fontSize: 11 }}>
            {unreadCount}
          </Text>
        </View>
      ) : null}
    </Pressable>
  );
}