Receive event notifications
Real-time conversational AI applications require responsive user interfaces that react to agent events. This page demonstrates how to implement event handling to create dynamic, interactive experiences with conversational agents.
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 Chat SDK and Video SDK to enable the following features:
Interrupt agents
Display live subtitles
Receive event notifications
Set optimal audio parameters
(iOS and Android only)
The component provides a set of callback methods that allow you to listen for various agent-related events and system information:
-
onAgentStateChanged
: Listen for agent state changes through Signaling presence events. Possible states include:silent
,listening
,thinking
, andspeaking
. Use this callback to update the agent UI or track the conversation flow. -
onAgentInterrupted
: Listen for agent interruption events through Signaling messages. Use this to handle scenarios where the agent is interrupted mid-response. -
onAgentMetrics
: Listen for agent performance metrics through Signaling messages. Metrics include LLM reasoning delay, TTS synthesis delay, and more. Use this callback to monitor system performance. -
onAgentError
: Listen for agent error events through Signaling messages. These may include errors in agent modules such as LLM or TTS. Use this callback for error monitoring, logging, and implementing graceful degradation strategies.
Prerequisites
Before you begin, ensure the following:
- You have implemented the Conversational AI Engine REST quickstart.
- Your app integrates Video SDK v4.5.1 or later and includes the video quickstart implementation.
- You have enabled Signaling in the Agora Console and completed Signaling quickstart for basic messaging.
- You maintain active and authenticated RTC and Signaling instances that persist beyond the component's lifecycle. The toolkit does not manage the initialization, lifecycle, or authentication of RTC or Signaling.
Implementation
This section describes how to implement Conversational AI engine events using the toolkit.
- Android
- iOS
- Web
-
Integrate the toolkit
Copy the
convoaiApi
folder to your project and import the toolkit before calling the toolkit API. Refer to Folder structure to understand the role of each file. -
Create a toolkit instance
Create a configuration object with the Video SDK and Signaling engine instances. Use the configuration to create a toolkit instance.
// Create a configuration object for the Video SDK and Chat SDK instances val config = ConversationalAIAPIConfig( rtcEngine = rtcEngineInstance, rtmClient = rtmClientInstance, enableLog = true ) // Create the toolkit instance val api = ConversationalAIAPIImpl(config)
-
Register events
Call the
addHandler
method to register and implement agent-related event callbacks.// Register event callbacks api.addHandler(object : IConversationalAIAPIEventHandler { // Listen for agent state changes 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") } } } // Listen for agent interruption events override fun onAgentInterrupted(agentUserId: String, event: InterruptEvent) { Log.d("AgentInterrupt", "Agent $agentUserId interrupted at turn ${event.turnId}") showInterruptNotification() } // Monitor agent performance metrics 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}") } } } // Handle agent errors override fun onAgentError(agentUserId: String, error: ModuleError) { Log.e("AgentError", "Error in ${error.type}: ${error.message} (code: ${error.code})") when (error.type) { ModuleType.LLM -> { showErrorMessage("AI processing failed. Please try again later.") } ModuleType.TTS -> { showErrorMessage("Speech synthesis failed.") } else -> { showErrorMessage("System error: ${error.message}") } } } // Handle debug logs override fun onDebugLog(log: String) { if (BuildConfig.DEBUG) { Log.d("ConvoAI", log) } // Optional: Send logs to a remote server for diagnostics } })
-
Subscribe to the channel
Subtitles are delivered through Signaling channel messages. To receive subtitle data, call
subscribeMessage
before starting the agent session.api.subscribeMessage("channelName") { error -> if (error != null) { // Handle error } }
-
Add a Conversational AI agent to the channel
To start a Conversational AI agent, 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 Video SDK channel and is ready to interact with the user.
-
Unsubscribe from the channel
After an agent session ends, unsubscribe from channel messages to release subtitle-related resources:
api.unsubscribeMessage("channelName") { error ->
if (error != null) {
// Handle the error
}
} -
Release resources
At the end of each call, use the
destroy
method to clean up the cache.api.destroy()
-
Integrate the toolkit
Copy the
ConversationalAIAPI
folder to your project and import the toolkit before calling the toolkit APIs. Refer to Folder structure to understand the role of each file. -
Create a toolkit instance
Create a configuration object with the Video SDK and Signaling engine instances, then use the configuration to create a toolkit instance.
// Create configuration objects for the Video SDK and Chat SDK instances let config = ConversationalAIAPIConfig( rtcEngine: rtcEngine, rtmEngine: rtmEngine, enableLog: true ) /// Create component instance convoAIAPI = ConversationalAIAPIImpl(config: config)
-
Register events
Call the
addHandler
method to register and implement agent-related event callbacks.// Make your class conform to the ConversationalAIAPIEventHandler protocol class ConversationViewController: UIViewController, ConversationalAIAPIEventHandler { // Implement protocol methods func onAgentStateChanged(agentUserId: String, event: StateChangeEvent) { // Update the UI to reflect the agent's current state DispatchQueue.main.async { self.updateAgentStatus(event.state) } } func onAgentInterrupted(agentUserId: String, event: InterruptEvent) { // Called when the agent is interrupted. Update the UI or log the event. print("Agent \(agentUserId) interrupted at turn \(event.turnId)") DispatchQueue.main.async { self.showInterruptNotification() } } func onAgentMetrics(agentUserId: String, metrics: Metric) { // Monitor agent performance metrics for debugging and optimization switch metrics.type { case .llm: print("LLM latency: \(metrics.value)ms") // Log LLM response time for performance analysis case .tts: print("TTS latency: \(metrics.value)ms") // Log TTS synthesis time case .unknown: print("Unknown metric: \(metrics.name) = \(metrics.value)") } } func onAgentError(agentUserId: String, error: ModuleError) { // Handle agent error events print("Error in \(error.type): \(error.message) (code: \(error.code))") DispatchQueue.main.async { switch error.type { case .llm: // LLM error. You may want to retry or use a fallback. self.showErrorMessage("AI processing failed. Please try again later.") case .tts: // TTS error. Consider switching to text mode. self.showErrorMessage("Speech synthesis failed.") case .mllm: // MLLM error self.showErrorMessage("Multimodal AI processing failed.") case .unknown: // Other error types self.showErrorMessage("System error: \(error.message)") } } } // Helper method for updating the UI with the agent's current state private func updateAgentStatus(_ state: AgentState) { let (text, color): (String, UIColor) = { switch state { case .idle: return ("Idle", .gray) case .silent: return ("Waiting...", .gray) case .listening: return ("Listening...", .blue) case .thinking: return ("Thinking...", .orange) case .speaking: return ("Speaking...", .green) case .unknown: return ("Unknown", .red) } }() statusLabel.text = text statusLabel.textColor = color } private func showInterruptNotification() { statusLabel.text = "Conversation interrupted" statusLabel.textColor = .red } private func showErrorMessage(_ message: String) { let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } } // Register the event callback handler convoAIAPI.addHandler(handler: self)
-
Subscribe to the channel
Subtitles are delivered through Signaling channel messages. To receive subtitle data, call
subscribeMessage
before starting the agent session.convoAIAPI.subscribeMessage(channelName: channelName) { error in if let error = error { print("Subscription failed: \(error.message)") } else { print("Subscription successful") } }
-
Agent joins the channel
To start a Conversational AI agent, configure the following parameters in your
POST
request:Parameter Required Description advanced_features.enable_rtm
Yes Enables the Chat service. parameters.data_channel
Yes Sets the data transmission channel to "rtm"
.parameters.enable_metrics
Optional Enables collection of agent performance data. parameters.enable_error_message
Optional Enables reporting of agent error events. After a successful request, the agent joins the specified Video SDK channel and the user can begin interacting with it.
-
Unsubscribe from the channel
After each agent session ends, unsubscribe from channel messages to release subtitle-related resources.
// Unsubscribe from channel messages convoAIAPI.unsubscribeMessage(channelName: channelName) { error in if let error = error { print("Unsubscription failed: \(error.message)") } else { print("Unsubscribed successfully") } }
-
Release resources
At the end of each call, use the
destroy
method to clean up the cache.convoAIAPI.destroy()
-
Integrate the toolkit
Copy the
conversational-ai-api
file to your project and import the toolkit before calling its API. Refer to Folder structure to understand the role of each file. -
Create a toolkit instance
Before joining a Video SDK channel, create video and Signaling engine instances and pass in to the toolkit instance.
// Create configuration objects for RTC and RTM instances ConversationalAIAPI.init({ rtcEngine, rtmEngine, }) // Get the API instance (singleton) const conversationalAIAPI = ConversationalAIAPI.getInstance()
-
Register events
Call the
addHandler
method to register and implement agent-related event callbacks.// Listen for agent state changes conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_STATE_CHANGED, onAgentStateChanged) // Listen for agent performance metrics conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_METRICS, onAgentMetricsChanged) // Listen for agent error events conversationalAIAPI.on(EConversationalAIAPIEvents.AGENT_ERROR, onAgentError)
-
Subscribe to the channel Agent-related events are delivered through Signaling messages. Before starting an agent session, call
subscribeMessage
to receive these events:conversationalAIAPI.subscribeMessage(channel_name)
-
Add a Conversational AI agent to the channel
To start a Conversational AI agent, 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 Video SDK channel and is ready to interact with the user.
-
Unsubscribe from the channel
After each agent session ends, unsubscribe from channel messages to release resources associated with callback events:
conversationalAIAPI.unsubscribeMessage(channel_name)
-
Release resources
At the end of each call, use the
destroy
method to clean up the cache.conversationalAIAPI.destroy()
Reference
This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.
Sample project
Refer to the following open-source sample code for your reference.
Folder structure
To integrate the client components, only the files and folders listed below are required. You do not need to copy any other files.
- Android
- iOS
- Web
IConversationalAIAPI.kt
: Defines the API interface, data structures, and enumerations.ConversationalAIAPIImpl.kt
: Contains the main implementation logic of the ConversationalAI API.ConversationalAIUtils.kt
: Provides utility functions and manages event callbacks.v3/
: Contains the subtitle rendering module.TranscriptionController.kt
: Controls subtitle rendering and synchronization.MessageParser.kt
: Parses transcription and message data.
ConversationalAIAPI.swift
: Defines the API interface, data structures, and enumerations.ConversationalAIAPIImpl.swift
: Contains the main implementation logic of the ConversationalAI API.Transcription/
TranscriptionController.swift
: Manages subtitle rendering and transcription control.
index.ts
: Defines the main API class.type.ts
: Contains API interfaces, data structures, and enumerations.utils/
index.ts
: Provides general utility functions for the API.events.ts
: Defines the event management class, which can be extended to support event listening and broadcasting.sub-render.ts
: Implements the subtitle rendering module.
API reference
- Android
- iOS
- Web