# Display live transcripts (/en/ai/platform/build/transcripts)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

When interacting with conversational AI in real time, you can enable live transcripts to display the conversation content. This page explains how to implement live transcripts in your app.

## Understand the tech

Agora provides a flexible, scalable, and standardized conversational AI engine toolkit. The toolkit supports **iOS**, **Android**, and **Web** platforms, and encapsulates scenario-based APIs. You can use these APIs to integrate the capabilities of the [Agora Signaling SDK](/en/realtime-media/rtm) and [Agora RTC SDK](/en/realtime-media/rtc/get-started-sdk) to enable the following features:

- [Interrupt agents](shape-the-conversation/interrupt-agent)
- [Display live transcripts](transcripts)
- [Client-side events](handle-runtime-events/event-notifications)
- [Set optimal audio parameters](../best-practices/audio-setup) for iOS and Android
- [Send picture messages](send-multimodal-messages)

The toolkit receives transcript content through the `onTranscriptUpdated` callback and supports monitoring the following transcript data types:

- **Agent transcript**: The agent's speech, including streaming updates and final results.
- **User transcript**: The user's speech, including real-time display and status management.
- **Transcript status**: State changes such as in progress, completed, or interrupted.

The following diagram outlines the step-by-step process to integrate live transcript functionality into your application:

**Transcript rendering workflow**

![](https://assets-docs.agora.io/images/conversational-ai/transcript-workflow.svg)

## Prerequisites

Before you begin, ensure the following:

- You have implemented the Conversational AI Engine [quickstart](../get-started/quickstart).
- Your app integrates Agora RTC SDK v4.5.1 or later and includes the [RTC SDK quickstart](/en/realtime-media/rtc/get-started-sdk).
- You have enabled Signaling in the Agora Console and completed the [Signaling quickstart](/en/realtime-media/rtm/quickstart) for basic messaging.
- You maintain active and authenticated RTC and Signaling instances that persist beyond the component lifecycle. The toolkit does not manage RTC or Signaling initialization, lifecycle, or authentication.

## Implementation

This section describes how to receive transcript content from the transcript processing module and display it in your app UI.

**Android**

1. **Integrate the toolkit**

   Add the toolkit to your project using Maven or source code. See [Install the Android toolkit](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#installation). Refer to [Folder structure](#reference) to understand the role of each file.

2. **Create a toolkit instance**

   Create a configuration object with the RTC SDK and Signaling engine instances. Set the transcript rendering mode, then use the configuration to create a toolkit instance.

   ```kotlin
   // Create configuration objects for the RTC and RTM instances
   val config = ConversationalAIAPIConfig(
       rtcEngine = rtcEngineInstance,
       rtmClient = rtmClientInstance,

       // Set the transcript rendering mode. Options:
       // - TranscriptRenderMode.Word: render transcript word by word.
       // - TranscriptRenderMode.Text: render the full sentence at once.
       renderMode = TranscriptRenderMode.Word,
       enableLog = true
   )

   // Create component instance
   val api = ConversationalAIAPIImpl(config)
   ```


3. **Subscribe to the channel**

   Transcript data is delivered through Signaling channel messages. To receive transcript data, call `subscribeMessage` before starting the agent session.

   ```kotlin
   api.subscribeMessage("channelName") { error ->
       if (error != null) {
           // Handle error
       }
   }
   ```


4. **Receive transcript**

   Call the `addHandler` method to register your implementation of the transcription callback.

   ```kotlin
   api.addHandler(covEventHandler)
   ```


5. **Implement UI rendering logic**

   Inherit your UI module from the `IConversationalAIAPIEventHandler` interface. Implement the `onTranscriptUpdated` method to handle transcript rendering to the UI.

   ```kotlin
   private val covEventHandler = object : IConversationalAIAPIEventHandler {
       override fun onTranscriptUpdated(agentUserId: String, transcript: Transcript) {
           // Handle transcript data and update the UI here
       }
   }
   ```


6. **Add a conversational AI agent to the channel**

   To [start a conversational AI agent](/en/api-reference/api-ref/conversational-ai/join), configure the following parameters in your `POST` request:

   | Parameter                               | Description                                        | Required |
   | --------------------------------------- | -------------------------------------------------- | -------- |
   | `advanced_features.enable_rtm: true`    | Starts the Signaling service                       | Yes      |
   | `parameters.data_channel: "rtm"`        | Enables Signaling as the data transmission channel | Yes      |
   | `parameters.enable_metrics: true`       | Enables agent performance data collection          | Optional |
   | `parameters.enable_error_message: true` | Enables reporting of agent error events            | Optional |

   After a successful response, the agent joins the specified RTC channel and is ready to interact with the user.

7. **Unsubscribe from the channel**

   After an agent session ends, unsubscribe from channel messages to release transcription resources.

   ```kotlin
   api.unsubscribeMessage("channelName") { error ->
       if (error != null) {
           // Handle the error
       }
   }
   ```


8. **Release resources**

   At the end of each call, use the `destroy` method to clean up the cache.

   ```kotlin
   api.destroy()
   ```

**iOS**

1. **Integrate the toolkit**

   Add the toolkit to your project using CocoaPods, Swift Package Manager, or source code. See [Install the iOS toolkit](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#installation). Refer to [Folder structure](#reference) to understand the role of each file.

2. **Create a toolkit instance**

   Create a configuration object with the RTC SDK and Signaling engine instances. Set the transcript rendering mode, then use the configuration to create a toolkit instance.

   ```swift
   // Create a configuration object for the RTC and RTM instances
   let config = ConversationalAIAPIConfig(
       rtcEngine: rtcEngine,
       rtmEngine: rtmEngine,
       /**
        * Set the transcript rendering mode. Available options:
        * - .words: Word-by-word rendering mode.
        * - .text: Sentence-by-sentence rendering mode.
        */
       renderMode: .words,
       enableLog: true
   )

   // Create the component instance
   convoAIAPI = ConversationalAIAPIImpl(config: config)
   ```


3. **Subscribe to the channel**

   Transcript data is delivered through Signaling channel messages. To receive transcript data, call `subscribeMessage` before starting the agent session.

   ```swift
   convoAIAPI.subscribeMessage(channelName: channelName) { error in
       if let error = error {
           print("Subscription failed: \(error.message)")
       } else {
           print("Subscription successful")
       }
   }
   ```


4. **Receive transcript**

   Call the `addHandler` method to register and implement the transcript callback.

   ```swift
   convoAIAPI.addHandler(handler: self)
   ```


5. **Implement UI rendering logic**

   Implement the `ConversationalAIAPIEventHandler` protocol in your UI module, and use `onTranscriptUpdated` to handle and render transcript updates.

   ```swift
   extension ChatViewController: ConversationalAIAPIEventHandler {
       public func onTranscriptUpdated(agentUserId: String, transcript: Transcript) {
           // Handle transcript data and update the UI here
       }
   }
   ```


6. **Add a conversational AI agent to the channel**

   To [start a conversational AI agent](/en/api-reference/api-ref/conversational-ai/join), configure the following parameters in your `POST` request:

   | Parameter                               | Description                                        | Required |
   | --------------------------------------- | -------------------------------------------------- | -------- |
   | `advanced_features.enable_rtm: true`    | Starts the Signaling service                       | Yes      |
   | `parameters.data_channel: "rtm"`        | Enables Signaling as the data transmission channel | Yes      |
   | `parameters.enable_metrics: true`       | Enables agent performance data collection          | Optional |
   | `parameters.enable_error_message: true` | Enables reporting of agent error events            | Optional |

   After a successful response, the agent joins the specified RTC channel and is ready to interact with the user.

7. **Unsubscribe from the channel**

   After each agent session ends, unsubscribe from channel messages to release transcript-related resources.

   ```swift
   convoAIAPI.unsubscribeMessage(channelName: channelName) { error in
       if let error = error {
           print("Unsubscription failed: \(error.message)")
       } else {
           print("Unsubscribed successfully")
       }
   }
   ```


8. **Release resources**

   At the end of each call, use the `destroy` method to clean up the cache.

   ```swift
   convoAIAPI.destroy()
   ```

**Web**

1. **Integrate the toolkit**

   Add the toolkit to your project using a package manager or source code. See [Install the Web toolkit](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#installation). Refer to [Folder structure](#reference) to understand the role of each file.

2. **Create a toolkit instance**

   Before joining an RTC channel, create RTC SDK and Signaling engine instances and pass them into the toolkit instance.

   ```ts
   // Initialize the component
   ConversationalAIAPI.init({
     rtcEngine,
     rtmEngine,

     /**
      * Set the rendering mode for transcript. Available options:
      * - ETranscriptHelperMode.WORD: render transcript word by word.
      * - ETranscriptHelperMode.TEXT: render the full transcript at once.
      */
     renderMode: ETranscriptHelperMode.WORD,
   })

   // Get the API instance (singleton)
   const conversationalAIAPI = ConversationalAIAPI.getInstance()
   ```


3. **Set audio parameters**

   In word-by-word rendering mode, you must receive audio timestamp metadata from RTC to synchronize subtitles with speech. Before creating the client object, configure the following parameter:

   ```ts
   AgoraRTC.setParameter('ENABLE_AUDIO_PTS_METADATA', true)
   const client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' })
   ```


4. **Subscribe to the channel**

   Agent-related events are delivered through Signaling messages. Before starting an agent session, call `subscribeMessage` to receive these events:

   ```ts
   conversationalAIAPI.subscribeMessage(channel_name)
   ```


5. **Receive transcript**

   Register an event listener to receive transcript updates:

   ```tsx
   import * as React from 'react'
   import {
     type IUserTranscription,
     type IAgentTranscription,
     type ISubtitleHelperItem,
     EConversationalAIAPIEvents,
   } from '@/conversational-ai-api/type'
   import { ConversationalAIAPI } from '@/conversational-ai-api'

   export const ChatHistory = () => {
     const [chatHistory, setChatHistory] = React.useState<
       ISubtitleHelperItem<Partial<IUserTranscription | IAgentTranscription>>[]
     >([])

     const conversationalAIAPI = ConversationalAIAPI.getInstance()
     conversationalAIAPI.on(
       EConversationalAIAPIEvents.TRANSCRIPT_UPDATED,
       setChatHistory
     )

     return (
       <>
         {chatHistory.map((message) => (
           <div key={`${message.uid}-${message.turn_id}`}>
             {message.uid}: {message.text}
           </div>
         ))}
       </>
     )
   }
   ```


6. **Add a conversational AI agent to the channel**

   To [start a conversational AI agent](/en/api-reference/api-ref/conversational-ai/join), configure the following parameters in your `POST` request:

   | Parameter                               | Description                                        | Required |
   | --------------------------------------- | -------------------------------------------------- | -------- |
   | `advanced_features.enable_rtm: true`    | Starts the Signaling service                       | Yes      |
   | `parameters.data_channel: "rtm"`        | Enables Signaling as the data transmission channel | Yes      |
   | `parameters.enable_metrics: true`       | Enables agent performance data collection          | Optional |
   | `parameters.enable_error_message: true` | Enables reporting of agent error events            | Optional |

   After a successful response, the agent joins the specified RTC channel and is ready to interact with the user.

7. **Unsubscribe from the channel**

   After each agent session ends, unsubscribe from channel messages to release resources associated with callback events.

   ```ts
   conversationalAIAPI.unsubscribeMessage(channel_name)
   ```


8. **Release resources**

   At the end of each call, use the `destroy` method to clean up the cache.

   ```ts
   conversationalAIAPI.destroy()
   ```

## Reference

This section contains supporting information that completes the guidance on this page.

**Android**

**Folder structure**

- `IConversationalAIAPI.kt`: API interface and related data structures and enumerations
- `ConversationalAIAPIImpl.kt`: ConversationalAI API main implementation logic
- `ConversationalAIUtils.kt`: tool functions and event callback management
- `subRender/`
  - `v3/`: transcription module
  - `TranscriptionController.kt`: transcription controller
  - `MessageParser.kt`: message parser

**API reference**

- [`addHandler`](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#addhandler)
- [`subscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#subscribemessage)
- [`unsubscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#unsubscribemessage)
- [`destroy`](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#destroy)
- [`onTranscriptUpdated`](/en/api-reference/api-ref/conversational-ai/client-toolkit/android#ontranscriptupdated)

**iOS**

**Folder structure**

- `ConversationalAIAPI.swift`: API interface and related data structures and enumerations
- `ConversationalAIAPIImpl.swift`: ConversationalAI API main implementation logic
- `Transcription/`
  - `TranscriptionController.swift`: transcription controller

**API reference**

- [`addHandler`](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#addhandler)
- [`subscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#subscribemessage)
- [`unsubscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#unsubscribemessage)
- [`destroy`](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#destroy)
- [`onTranscriptUpdated`](/en/api-reference/api-ref/conversational-ai/client-toolkit/ios#ontranscriptupdated)

**Web**

**Folder structure**

- `index.ts`: API class
- `type.ts`: API interface and related data structures and enumerations
- `utils/`
  - `index.ts`: API utility functions
  - `events.ts`: event management class
  - `sub-render.ts`: transcription module

**API reference**

- [`IConversationalAIAPIEventHandler interface`](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#iconversationalaiapieventhandlers-interface)
- [`EConversationalAIAPIEvents`](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#econversationalaiapievents)
- [`subscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#subscribemessage)
- [`unsubscribeMessage`](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#unsubscribe)
- [`destroy`](/en/api-reference/api-ref/conversational-ai/client-toolkit/web#destroy)
