Native voice assistant integration for Expo apps with Siri and Google Assistant support.
- 🎙️ Siri Integration - SiriKit and App Intents (iOS 16+) support
- 🤖 Google Assistant - App Actions and Built-in Intents
- 🔧 Config Plugin - Automated native setup for iOS/Android
- 📱 Cross-Platform - Unified API for both platforms
- 🎯 TypeScript - Full type safety and IntelliSense
- 🧪 Well Tested - 89% test coverage with 72 tests
npx expo install expo-assistantAdd the config plugin to your app.json or app.config.js:
{
"expo": {
"plugins": [
[
"expo-assistant",
{
"intents": ["search", "media", "productivity"],
"enableSiriKit": true,
"enableAppActions": true
}
]
]
}
}import { VoiceAssistant, VoiceIntentBuilder, IntentCategory } from 'expo-assistant';
// Initialize voice assistant
const assistant = await VoiceAssistant.initialize();
// Create a search intent
const searchIntent = VoiceIntentBuilder
.create<{ query: string }>()
.withId('search-products')
.withCategory(IntentCategory.SEARCH)
.requiredParameter('query', {
type: ParameterType.STRING,
prompt: 'What would you like to search for?'
})
.withHandler({
handle: async (params) => {
const results = await searchProducts(params.query);
return { success: true, data: results };
}
})
.build();
// Register the intent
await assistant.registerIntent(searchIntent);
// Request permissions
await assistant.requestMicrophonePermission();
await assistant.requestSpeechRecognitionPermission();- Requires iOS 13.0+
- SiriKit for iOS 10+ compatibility
- App Intents for iOS 16+ features
- Automatic Info.plist and entitlements configuration via config plugin
- Requires Android API 23+
- Google Assistant App Actions
- Built-in Intents (BIIs) support
- Automatic AndroidManifest.xml and shortcuts.xml configuration via config plugin
- Search - Voice-powered search queries
- Media - Playback control (play, pause, skip)
- Productivity - Tasks, notes, reminders
- Health - Workouts and fitness tracking
- Communication - Messages and calls
- Travel - Reservations and navigation
- Finance - Payments and transactions
- Commerce - Shopping and orders
{
"expo": {
"plugins": [
[
"expo-assistant",
{
"intents": ["media", "productivity"],
"enableBackgroundExecution": true,
"ios": {
"siriUsageDescription": "Control music with your voice",
"alternativeAppNames": ["My Music App"],
"requiresUnlock": false
},
"android": {
"appActionsTestUrl": "https://myapp.com/test-actions",
"slicesEnabled": true
}
}
]
]
}
}initialize(config?)- Initialize the assistantregisterIntent(intent)- Register a voice intentunregisterIntent(intentId)- Unregister an intentexecuteIntent(intentId, params)- Execute an intent programmaticallyrequestMicrophonePermission()- Request mic accessrequestSpeechRecognitionPermission()- Request speech recognitioncheckCapabilities()- Check platform capabilities
Fluent API for building voice intents:
const intent = VoiceIntentBuilder
.create<ParamsType>()
.withId('unique-id')
.withCategory(IntentCategory.MEDIA)
.requiredParameter('title', { type: ParameterType.STRING })
.optionalParameter('artist', { type: ParameterType.STRING })
.withHandler({ handle: async (params) => {...} })
.configureIOS(ios => ios.addSiriPhrase('Play music'))
.configureAndroid(android => android.withCapability('actions.intent.PLAY_MEDIA'))
.build();const playIntent = VoiceIntentBuilder
.create<{ mediaTitle: string }>()
.withId('play-media')
.withCategory(IntentCategory.MEDIA)
.requiredParameter('mediaTitle', { type: ParameterType.STRING })
.withHandler({
handle: async ({ mediaTitle }) => {
await mediaPlayer.play(mediaTitle);
return { success: true };
}
})
.withBackgroundExecution()
.build();const todoIntent = VoiceIntentBuilder
.create<{ action: 'add' | 'complete'; item: string }>()
.withId('manage-todo')
.withCategory(IntentCategory.PRODUCTIVITY)
.requiredParameter('action', {
type: ParameterType.ENUM,
choices: ['add', 'complete']
})
.requiredParameter('item', { type: ParameterType.STRING })
.withHandler({
handle: async ({ action, item }) => {
if (action === 'add') {
return await todoService.add(item);
}
return await todoService.complete(item);
}
})
.build();- Expo SDK 53+ (tested with SDK 54)
- React Native 0.74.0+
- TypeScript 4.5+
- Physical device for testing (simulators have limited voice support)
- Config Plugin Guide - Detailed plugin configuration
- API Documentation - Full API reference
- Examples - Sample implementations
Contributions are welcome! Please read our contributing guidelines first.
MIT © shottah
Built with ❤️ using Expo Modules API