Embed an AI voice agent with NowVoice
Use the NowVoice module to embed a real-time AI voice agent session into your Android application.
NowVoice features
NowVoice gives your app a complete, ready-to-launch voice agent experience. When a user starts a voice agent session, the SDK:
- Authenticates against your ServiceNow instance using the token your app provides.
- Opens a WebSocket connection to the configured voice agent endpoint.
- Launches a full-screen
Activitywith microphone controls and a live transcript. - Delivers real-time transcript messages and mute-state changes to your app through callbacks.
- Shows an optional post-call transcript summary screen on session end.
All public types in the NowVoice module are in the com.servicenow.nowsdk.voice package.
Theming
NowVoice integrates with the NowUI theming system. Implement NowVoiceTheme to apply custom colors. NowVoiceThemeDark is provided as a built-in alternative to the default light theme.
Mobile SDK instance settings
The NowVoice module reads the following keys from your ServiceNow instance's Mobile SDK settings response.
{ "voice": { "enabled": true, "configurations": [ { "voiceServiceId": "String", "voiceWebhookURL": "String", "mobileChannelType": "String", "mobileChannelId": "String" } ] }}Configure NowVoice
Configure NowVoice to add a real-time voice agent to your Android application.
Before you begin
Role required: admin
- Mobile SDK 2.22.0 or later must be added to your project via Gradle.
- Your ServiceNow instance must have voice agent services enabled. Confirm that
sdk.voice.enabledistruein the Mobile SDK settings.
Procedure
-
Declare permissions in your app's
AndroidManifest.xml.NowVoice requires microphone and internet permissions:
XML<uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />Note:
RECORD_AUDIOis a classified as a dangerous (runtime) permission. It must also be requested at runtime on Android 6.0 (API 23) and later. When permission is needed, NowVoice SDK automatically triggers a request before callingNowVoiceService.start(). -
Configure NowSDK.
If you have not already done so, call
NowSDK.configure()once at app launch. NowVoice requires NowSDK to be configured before any voice operations.Textimport com.servicenow.nowsdk.NowSDKimport com.servicenow.nowsdk.NowSDKConfiguration NowSDK.configure( NowSDKConfiguration.Builder(this) .authorizationProvider(yourAuthProvider) .build()) -
Create a NowVoiceService.
Import NowVoice and call
NowVoiceSDK.makeVoiceService(instanceURL). This is a suspend function; call it from a coroutine scope.JavaScriptimport com.servicenow.nowsdk.voice.NowVoiceSDKimport kotlinx.coroutines.launchimport java.net.URL lifecycleScope.launch { val result = NowVoiceSDK.makeVoiceService( instanceURL = URL("https://your-instance.service-now.com") ) result .onSuccess { voiceService -> // Service is ready; proceed to select an endpoint } .onFailure { error -> // Handle NowServiceError Log.e("NowVoice", "Service creation failed: $error") }} -
Select a voice endpoint.
Use
NowVoiceService.nowVoiceEndpointsto retrieve the available voice endpoints. In most apps there is a single endpoint.Textval endpoint = voiceService.nowVoiceEndpoints.firstOrNull() ?: return -
Launch the voice UI.
Call
start(context:endpoint:uiConfiguration:callbacks:theme:)to launch the full-screen voice agent Activity. This is a suspend function that returns after the session ends.JavaScriptvoiceService.start( context = this@MainActivity, endpoint = endpoint, uiConfiguration = NowVoiceUiConfiguration( hidePostCallTranscript = false, shouldBlockAttachmentSharing = false ), callbacks = object : NowVoiceCallbacks { override fun onCallEnd(conversationId: String?, error: NowVoiceError?) { if (error != null) { Log.e("NowVoice", "Session ended with error: $error") } else { Log.d("NowVoice", "Session complete. ID: $conversationId") } } override fun onMuteStateChanged(isMuted: Boolean) { // Update your UI to reflect the current mute state Log.d("NowVoice", "Microphone muted: $isMuted") } override fun onMessageReceived(message: TranscriptMessage) { // Receive real-time transcript messages Log.d("NowVoice", "${message.role}: ${message.content}") } }, theme = object : NowVoiceTheme {} // Uses default light theme) -
Apply a custom theme.
To apply custom colors, implement
NowVoiceThemeand pass it tostart(context:endpoint:uiConfiguration:callbacks:theme:)orupdateTheme(theme:). Or, use the prebuilt dark theme.JavaScript// Prebuilt dark themevoiceService.start(context, endpoint, theme = NowVoiceThemeDark()) // Custom themeval myTheme = object : NowVoiceTheme { override val primary: Int = Color.parseColor("#0072C6") override val backgroundPrimary: Int = Color.parseColor("#FFFFFF") // ... override additional properties as needed} // Apply theme at voice session launchvoiceService.start(context, endpoint, theme = myTheme) // Or update theme while a voice session is activevoiceService.updateTheme(NowVoiceThemeDark())
Result
The voice agent Activity launches full-screen. The user can begin a real-time voice session with transcript and mute-state updates delivered to your app through the configured callbacks.
Complete example
import com.servicenow.nowsdk.voice.*import kotlinx.coroutines.launchimport java.net.URL
class MainActivity : AppCompatActivity() {
private fun launchVoiceSession() { lifecycleScope.launch { val result = NowVoiceSDK.makeVoiceService( instanceURL = URL("https://your-instance.service-now.com") )
result.onSuccess { voiceService -> val endpoint = voiceService.nowVoiceEndpoints.firstOrNull() ?: return@onSuccess
voiceService.start( context = this@MainActivity, endpoint = endpoint, callbacks = object : NowVoiceCallbacks { override fun onCallEnd(conversationId: String?, error: NowVoiceError?) { runOnUiThread { updateUI(ended = true) } }
override fun onMuteStateChanged(isMuted: Boolean) { runOnUiThread { updateMuteButton(isMuted) } }
override fun onMessageReceived(message: TranscriptMessage) { runOnUiThread { appendTranscript(message) } } } ) }.onFailure { error -> Log.e("NowVoice", "Failed: $error") } } }}---
title: Embed an AI voice agent with NowVoice
description: Use the NowVoice module to embed a real-time AI voice agent session into your Android application.Configure NowVoice to add a real-time voice agent to your Android application.
locale: en-US
canonical_url: https://www.servicenow.com/docs/r/australia/api-reference/developer-guides/mobsdk-and-nowvoice.html
release: australia
product: Developer Guides
classification: developer-guides
topic_type: concept
last_updated: "2026-09-10"
reading_time_minutes: 4
breadcrumb: [Mobile SDK Developer Guide - Android, Developer guides, API implementation and reference]
---
# Embed an AI voice agent with NowVoice
Use the NowVoice module to embed a real-time AI voice agent session into your Android application.
## NowVoice features
NowVoice gives your app a complete, ready-to-launch voice agent experience. When a user starts a voice agent session, the SDK:
- Authenticates against your ServiceNow instance using the token your app provides.
- Opens a WebSocket connection to the configured voice agent endpoint.
- Launches a full-screen `Activity` with microphone controls and a live transcript.
- Delivers real-time transcript messages and mute-state changes to your app through callbacks.
- Shows an optional post-call transcript summary screen on session end.
All public types in the NowVoice module are in the `com.servicenow.nowsdk.voice` package.
## Theming
NowVoice integrates with the NowUI theming system. Implement [`NowVoiceTheme`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceThemeAndroidInterface.md) to apply custom colors. [`NowVoiceThemeDark`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceThemeDarkAndroidClass.md) is provided as a built-in alternative to the default light theme.
## Mobile SDK instance settings
The NowVoice module reads the following keys from your ServiceNow instance's Mobile SDK settings response.
```
{
"voice": {
"enabled": true,
"configurations": [
{
"voiceServiceId": "String",
"voiceWebhookURL": "String",
"mobileChannelType": "String",
"mobileChannelId": "String"
}
]
}
}
```
## Configure NowVoice
Configure NowVoice to add a real-time voice agent to your Android application.
### Before you begin
Role required: admin
- Mobile SDK 2.22.0 or later must be added to your project via Gradle.
- Your ServiceNow instance must have voice agent services enabled. Confirm that `sdk.voice.enabled` is `true` in the Mobile SDK settings.
### Procedure
1. Declare permissions in your app's `AndroidManifest.xml`.
NowVoice requires microphone and internet permissions:
```xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```
**Note:** `RECORD_AUDIO` is a classified as a dangerous \(runtime\) permission. It must also be requested at runtime on Android 6.0 \(API 23\) and later. When permission is needed, NowVoice SDK automatically triggers a request before calling [`NowVoiceService.start()`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceServiceAndroidAPI.md).
2. Configure NowSDK.
If you have not already done so, call [`NowSDK.configure()`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowSDKAndroidAPI.md) once at app launch. NowVoice requires NowSDK to be configured before any voice operations.
```kotlin
import com.servicenow.nowsdk.NowSDK
import com.servicenow.nowsdk.NowSDKConfiguration
NowSDK.configure(
NowSDKConfiguration.Builder(this)
.authorizationProvider(yourAuthProvider)
.build()
)
```
3. Create a NowVoiceService.
Import NowVoice and call [`NowVoiceSDK.makeVoiceService(instanceURL)`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceSDKAndroidAPI.md). This is a suspend function; call it from a coroutine scope.
```kotlin
import com.servicenow.nowsdk.voice.NowVoiceSDK
import kotlinx.coroutines.launch
import java.net.URL
lifecycleScope.launch {
val result = NowVoiceSDK.makeVoiceService(
instanceURL = URL("https://your-instance.service-now.com")
)
result
.onSuccess { voiceService ->
// Service is ready; proceed to select an endpoint
}
.onFailure { error ->
// Handle NowServiceError
Log.e("NowVoice", "Service creation failed: $error")
}
}
```
4. Select a voice endpoint.
Use [`NowVoiceService.nowVoiceEndpoints`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceServiceAndroidAPI.md) to retrieve the available voice endpoints. In most apps there is a single endpoint.
```kotlin
val endpoint = voiceService.nowVoiceEndpoints.firstOrNull() ?: return
```
5. Launch the voice UI.
Call [`start(context:endpoint:uiConfiguration:callbacks:theme:)`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceServiceAndroidAPI.md) to launch the full-screen voice agent Activity. This is a suspend function that returns after the session ends.
```kotlin
voiceService.start(
context = this@MainActivity,
endpoint = endpoint,
uiConfiguration = NowVoiceUiConfiguration(
hidePostCallTranscript = false,
shouldBlockAttachmentSharing = false
),
callbacks = object : NowVoiceCallbacks {
override fun onCallEnd(conversationId: String?, error: NowVoiceError?) {
if (error != null) {
Log.e("NowVoice", "Session ended with error: $error")
} else {
Log.d("NowVoice", "Session complete. ID: $conversationId")
}
}
override fun onMuteStateChanged(isMuted: Boolean) {
// Update your UI to reflect the current mute state
Log.d("NowVoice", "Microphone muted: $isMuted")
}
override fun onMessageReceived(message: TranscriptMessage) {
// Receive real-time transcript messages
Log.d("NowVoice", "${message.role}: ${message.content}")
}
},
theme = object : NowVoiceTheme {} // Uses default light theme
)
```
6. Apply a custom theme.
To apply custom colors, implement [`NowVoiceTheme`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceThemeAndroidInterface.md) and pass it to [`start(context:endpoint:uiConfiguration:callbacks:theme:)`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceServiceAndroidAPI.md) or [`updateTheme(theme:)`](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceServiceAndroidAPI.md). Or, use the [prebuilt dark theme](https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/api-reference/cllent-mobile-api-reference/NowVoiceThemeDarkAndroidClass.md).
```kotlin
// Prebuilt dark theme
voiceService.start(context, endpoint, theme = NowVoiceThemeDark())
// Custom theme
val myTheme = object : NowVoiceTheme {
override val primary: Int = Color.parseColor("#0072C6")
override val backgroundPrimary: Int = Color.parseColor("#FFFFFF")
// ... override additional properties as needed
}
// Apply theme at voice session launch
voiceService.start(context, endpoint, theme = myTheme)
// Or update theme while a voice session is active
voiceService.updateTheme(NowVoiceThemeDark())
```
### Result
The voice agent Activity launches full-screen. The user can begin a real-time voice session with transcript and mute-state updates delivered to your app through the configured callbacks.
### Complete example
```kotlin
import com.servicenow.nowsdk.voice.*
import kotlinx.coroutines.launch
import java.net.URL
class MainActivity : AppCompatActivity() {
private fun launchVoiceSession() {
lifecycleScope.launch {
val result = NowVoiceSDK.makeVoiceService(
instanceURL = URL("https://your-instance.service-now.com")
)
result.onSuccess { voiceService ->
val endpoint = voiceService.nowVoiceEndpoints.firstOrNull() ?: return@onSuccess
voiceService.start(
context = this@MainActivity,
endpoint = endpoint,
callbacks = object : NowVoiceCallbacks {
override fun onCallEnd(conversationId: String?, error: NowVoiceError?) {
runOnUiThread { updateUI(ended = true) }
}
override fun onMuteStateChanged(isMuted: Boolean) {
runOnUiThread { updateMuteButton(isMuted) }
}
override fun onMessageReceived(message: TranscriptMessage) {
runOnUiThread { appendTranscript(message) }
}
}
)
}.onFailure { error ->
Log.e("NowVoice", "Failed: $error")
}
}
}
}
```
| title | Embed an AI voice agent with NowVoice |
| description | Use the NowVoice module to embed a real-time AI voice agent session into your Android application.Configure NowVoice to add a real-time voice agent to your Android application. |
| locale | en-US |
| canonical_url | https://www.servicenow.com/docs/r/australia/api-reference/developer-guides/mobsdk-and-nowvoice.html |
| release | australia |
| product | Developer Guides |
| classification | developer-guides |
| topic_type | concept |
| last_updated | 2026-09-10 |
| reading_time_minutes | 4 |
| breadcrumb | Mobile SDK Developer Guide - AndroidDeveloper guidesAPI implementation and reference |