# Compose Integration

The AI components work seamlessly with the Stream Chat Android SDK.

### StreamingText

You can easily integrate the message streaming view into your Compose chat UI.

One option is to use it when rendering messages:

```kotlin
@Composable
fun MessageItem(message: Message) {
    val isGenerating = message.extraData["generating"] == true
    val isFromAI = message.extraData["ai_generated"] == true

    if (isFromAI) {
        StreamingText(
            text = message.text,
            animate = isGenerating
        )
    } else {
        Text(text = message.text)
    }
}
```

You can also add thinking indicators, for example at the bottom of the message list:

```kotlin
@Composable
fun ChatScreen(channelId: String) {
    val chatClient = ChatClient.instance()
    val channel = chatClient.channel(channelId)

    val context = LocalContext.current
    val factory = MessagesViewModelFactory(
        context = context,
        channelId = channelId,
    )
    val viewModel = viewModel(
        modelClass = MessageListViewModel::class.java,
        factory = factory,
    )

    var assistantState by remember { mutableStateOf<String?>(null) }

    // Listen to AI typing indicator events
    LaunchedEffect(channelId) {
        channel.subscribeFor<AIIndicatorUpdatedEvent> { event ->
            assistantState = event.aiState
        }
    }

    Column {
        // Message list
        MessageList(viewModel)

        // Typing indicator overlay
        if (assistantState != null) {
            AITypingIndicator(
                label = {
                    Text(
                        when (assistantState) {
                            "AI_STATE_THINKING" -> "Thinking"
                            "AI_STATE_CHECKING_SOURCES" -> "Checking sources"
                            "AI_STATE_GENERATING" -> "Generating response"
                            else -> ""
                        }
                    )
                }
            )
        }

        // Composer
        ChatComposer(
            onSendClick = { messageData ->
                channel.sendMessage(
                    Message(
                        text = messageData.text,
                        attachments = messageData.attachments.map { uri ->
                            // Convert URI to attachment
                        }
                    )
                ).enqueue()
            },
            onStopClick = {
                channel.sendEvent(EventType.AI_TYPING_INDICATOR_STOP).enqueue()
            },
            isGenerating = assistantState == "AI_STATE_GENERATING",
        )
    }
}
```

For a reference implementation showing how to integrate these components with Stream Chat's client API, please check our [sample app](https://github.com/GetStream/stream-chat-android-ai).


---

This page was last updated at 2026-04-17T17:33:31.935Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/v6/ai-integrations/compose-integration/](https://getstream.io/chat/docs/sdk/android/v6/ai-integrations/compose-integration/).