Client-side events
Updated
Use toolkit callbacks to update the UI and react to agent events during a live session.
Real-time Conversational AI applications require responsive user interfaces that react to agent events. This page explains how to implement client-side event handling with the Conversational AI Engine toolkit. Use this page when you need in-session events in a mobile or web client. If you need backend monitoring, alerting, or post-session analysis, use Webhooks instead.
For an overview that compares client toolkit and webhook delivery, see Get runtime events.
Understand the tech
Agora provides a flexible, scalable, and standardized Conversational AI Engine toolkit. The toolkit supports Android, iOS, and Web platforms, and encapsulates scenario-based APIs. You can use these APIs to integrate Agora Signaling SDK and RTC SDK capabilities to enable the following features:
- Interrupt agents
- Display live transcripts
- Monitor agent status, errors, and performance
- Set optimal audio parameters for iOS and Android
The toolkit exposes callback methods that let you listen for various agent-related events and system information:
onAgentStateChanged: Listen for agent state changes such assilent,listening,thinking, andspeaking.onAgentListeningChanged: Track when the agent starts or stops listening.onAgentThinkingChanged: Track when the agent starts or stops processing.onAgentSpeakingChanged: Track when the agent starts or stops playing speech.onAgentInterrupted: Handle interruption events triggered during a conversation.onAgentMetrics: Observe performance metrics such as LLM and TTS latency.onAgentError: Handle module-level failures such as LLM or TTS errors.
Prerequisites
- Implemented the Conversational AI Engine quickstart.
- Your app integrates Agora RTC SDK v4.5.1 or later and includes the RTC SDK quickstart.
- Enabled Signaling in the Agora Console and completed the Signaling quickstart for basic messaging.
- 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
-
Integrate the toolkit
Add the toolkit to your project using Maven or source code. See Install the Android toolkit. Refer to Folder structure to understand the role of each file.
-
Create a toolkit instance
val config = ConversationalAIAPIConfig( rtcEngine = rtcEngine, rtmClient = rtmClient, renderMode = TranscriptRenderMode.Word, enableLog = true, enableRenderModeFallback = true ) val api = ConversationalAIAPIImpl(config) -
Register events
api.addHandler(object : IConversationalAIAPIEventHandler { override fun onAgentStateChanged(agentUserId: String, event: StateChangeEvent) { when (event.state) { AgentState.SILENT -> updateAgentStatus("Waiting...") AgentState.LISTENING -> updateAgentStatus("Listening...") AgentState.THINKING -> updateAgentStatus("Thinking...") AgentState.SPEAKING -> updateAgentStatus("Speaking...") AgentState.UNKNOWN -> Log.w("AgentState", "Unknown agent state: $event") } } override fun onAgentInterrupted(agentUserId: String, event: InterruptEvent) { Log.d("AgentInterrupt", "Agent $agentUserId interrupted at turn ${event.turnId}") showInterruptNotification() } override fun onAgentMetrics(agentUserId: String, metric: Metric) { when (metric.type) { ModuleType.LLM -> Log.d("Metrics", "LLM latency: ${metric.value} ms") ModuleType.TTS -> Log.d("Metrics", "TTS latency: ${metric.value} ms") else -> Log.d("Metrics", "${metric.type}: ${metric.name} = ${metric.value}") } } override fun onAgentError(agentUserId: String, error: ModuleError) { Log.e("AgentError", "Error in ${error.type}: ${error.message} (code: ${error.code})") } }) -
Subscribe to the channel
api.subscribeMessage("channelName") { error -> if (error != null) { // Handle error } } -
Add a conversational AI agent to the channel
To start a conversational AI agent, configure:
Parameter Description Required advanced_features.enable_rtm: trueStarts the Signaling service Yes parameters.data_channel: "rtm"Enables Signaling as the data transmission channel Yes parameters.enable_metrics: trueEnables agent performance data collection Optional parameters.enable_error_message: trueEnables reporting of agent error events Optional -
Unsubscribe and release resources
api.unsubscribeMessage("channelName") { error -> if (error != null) { // Handle the error } } api.destroy()
-
Integrate the toolkit
Add the toolkit to your project using CocoaPods, Swift Package Manager, or source code. See Install the iOS toolkit. Refer to Folder structure to understand the role of each file.
-
Create a toolkit instance
let config = ConversationalAIAPIConfig( rtcEngine: rtcEngine, rtmEngine: rtmEngine, renderMode: .words, enableLog: true, enableRenderModeFallback: true ) convoAIAPI = ConversationalAIAPIImpl(config: config) -
Register events
class ConversationViewController: UIViewController, ConversationalAIAPIEventHandler { func onAgentStateChanged(agentUserId: String, event: StateChangeEvent) { DispatchQueue.main.async { self.updateAgentStatus(event.state) } } func onAgentInterrupted(agentUserId: String, event: InterruptEvent) { print("Agent \(agentUserId) interrupted at turn \(event.turnId)") } func onAgentMetrics(agentUserId: String, metrics: Metric) { switch metrics.type { case .llm: print("LLM latency: \(metrics.value)ms") case .tts: print("TTS latency: \(metrics.value)ms") case .unknown: print("Unknown metric: \(metrics.name) = \(metrics.value)") } } func onAgentError(agentUserId: String, error: ModuleError) { print("Error in \(error.type): \(error.message) (code: \(error.code))") } } convoAIAPI.addHandler(handler: self) -
Subscribe to the channel
convoAIAPI.subscribeMessage(channelName: channelName) { error in if let error = error { print("Subscription failed: \(error.message)") } else { print("Subscription successful") } } -
Add a conversational AI agent to the channel
To start a conversational AI agent, configure:
Parameter Description Required advanced_features.enable_rtm: trueStarts the Signaling service Yes parameters.data_channel: "rtm"Enables Signaling as the data transmission channel Yes parameters.enable_metrics: trueEnables collection of agent performance data Optional parameters.enable_error_message: trueEnables reporting of agent error events Optional -
Unsubscribe and release resources
convoAIAPI.unsubscribeMessage(channelName: channelName) { error in if let error = error { print("Unsubscription failed: \(error.message)") } else { print("Unsubscribed successfully") } } convoAIAPI.destroy()
-
Integrate the toolkit
Add the toolkit to your project using a package manager or source code. See Install the Web toolkit. Refer to Folder structure to understand the role of each file.
-
Create a toolkit instance
const config: IConversationalAIAPIConfig = { rtcEngine, rtmEngine, renderMode: ETranscriptHelperMode.WORD, enableLog: true, enableRenderModeFallback: true, } const conversationalAIAPI = await ConversationalAIAPI.init(config) -
Register events
conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_STATE_CHANGED, onAgentStateChanged) conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_METRICS, onAgentMetricsChanged) conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_ERROR, onAgentError) -
Subscribe to the channel
conversationalAIAPI.subscribeMessage(channel_name) -
Add a conversational AI agent to the channel
To start a conversational AI agent, configure:
Parameter Description Required advanced_features.enable_rtm: trueStarts the Signaling service Yes parameters.data_channel: "rtm"Enables Signaling as the data transmission channel Yes parameters.enable_metrics: trueEnables agent performance data collection Optional parameters.enable_error_message: trueEnables reporting of agent error events Optional -
Unsubscribe and release resources
conversationalAIAPI.unsubscribeMessage(channel_name) conversationalAIAPI.destroy()
Reference
Sample project
Related guides
Folder structure
IConversationalAIAPI.kt: API interface, data structures, and enumerationsConversationalAIAPIImpl.kt: main implementation logicConversationalAIUtils.kt: utility functions and event callback managementv3/TranscriptionController.kt: transcript rendering and synchronizationMessageParser.kt: transcription and message parsing
ConversationalAIAPI.swift: API interface, data structures, and enumerationsConversationalAIAPIImpl.swift: main implementation logicTranscription/TranscriptionController.swift: transcript rendering and control
index.ts: main API classtype.ts: API interfaces, data structures, and enumerationsutils/index.ts: general utility functionsevents.ts: event management classsub-render.ts: transcript rendering module
