---
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-07-23"
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
```
**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")
}
}
}
}
```