Skip to main content

Model selection

Start with a small model during development for faster iteration. Switch up when quality becomes the bottleneck.

Quantization trade-offs

Memory management

Unload what you are not using

Handle app lifecycle

Check headroom before downloading

models.state() reports storageUsedBytes and storageFreeBytes alongside what is loaded.

Close your sessions

Both session types own native resources: a RAG session holds an index, and a voice session holds the microphone and playback. Close them in cleanup, not on the next screen’s mount.
Only one RAG session can be open at a time, so a screen that opens a new one must close the old one first. See RAG.

Performance

Stream long responses

Cap output tokens

The default is 512. Raise it only where the answer needs the room, and lower it for voice, where a long reply is worse than a clipped one.

Pre-download during onboarding

Error handling

Skip crash reporting on user cancellation: e.isExpected is true for those codes. See Error handling.

Download progress UI

DownloadProgress.tsx
download throws on transfer failure, so wrap the call when you want to show the reason.

Graceful degradation

Security and privacy

Never log user content

Environment choice

Telemetry only flows in production.

React Native platform notes

Hermes and async iterables

Hermes cannot iterate the SDK’s async iterables with for await...of. It fails silently, so no values arrive and the UI hangs. Every streaming verb needs a manual next() loop, and iterator.return() in a finally to cancel the native work.

iOS: react-native-screens crashes

On iOS with New Architecture in RN 0.83 and up, react-native-screens crashes with errors like -[RCTView setColor:]. Use @react-navigation/stack instead of @react-navigation/native-stack, and mock react-native-screens in your Metro config.
metro.config.js

iOS vs Android New Architecture

Enable New Architecture on Android (newArchEnabled=true in gradle.properties) and disable it on iOS (new_arch_enabled: false in the Podfile). This avoids crashes with several native modules on iOS.

Use the SDK’s audio classes

Third-party recorders such as react-native-audio-recorder-player crash on iOS New Architecture, and the Web Audio AudioContext does not exist in React Native at all. AudioCaptureManager and AudioPlaybackManager from @runanywhere/core cover capture and playback on both platforms.

Audio data format

Audio crosses the bridge as binary, not base64. AudioCaptureManager emits 16 kHz mono Int16 little-endian Uint8Array chunks, which AudioInputs.pcm16 wraps directly. tts.synthesize returns Audio.data as a Uint8Array in the format named by Audio.format. AudioConvert.pcm16ToWav(buffer, sampleRate) adds a RIFF header when a consumer needs a self-describing container.

NitroModules manual setup

react-native-nitro-modules needs manual configuration on both platforms: add the NitroModules pod in your Podfile, and include it as a Gradle project in settings.gradle.

Duplicate native libraries on Android

Add pickFirsts for libc++_shared.so, libjsi.so, libfbjni.so, libfolly_runtime.so, and libreactnative.so in your app’s build.gradle packagingOptions.

Node path in Android Studio

Android Studio does not inherit terminal PATH. Add explicit Node binary search paths in your root build.gradle to fix node not found errors during Gradle builds.

Checklist

Pick a model size that fits the device you ship to
Stream long responses, and cap maxOutputTokens
Unload models when the app backgrounds
Close voice and RAG sessions in cleanup
Drive every stream with a manual iterator loop
Return the iterator in a finally so cancellation reaches native
Show download and load progress
Test on a physical device
Never log prompts or transcripts

Configuration

Initialization, events, logging

Error handling

SDKException reference

Quick Start

Getting started