React Native Quickstart
Build a cross-platform voice AI client with React Native.
Recipe prompt
Paste into Cursor, Claude Code, v0, or your coding agentYou are implementing the "React Native Quickstart" recipe in this project.
Read the recipe markdown first:
https://raw.githubusercontent.com/AgoraIO-Conversational-AI/recipe-client-rn-quickstart/main/README.md
Use the source repository for cross-reference:
https://github.com/AgoraIO-Conversational-AI/recipe-client-rn-quickstart
Build this recipe into the user's app using the markdown as the implementation guide. Inspect related source files through the repository links when the recipe points to them. Ask before installing new dependencies.Recipe
Rendered from the configured recipe markdown.
recipe-client-rn-quickstart
A bare React Native (TypeScript) voice-agent quickstart that talks to a bundled, keyless Python backend and renders live transcript by reusing the npm `agora-agent-client-toolkit` — no port, no vendoring. React Native runs JS, so it consumes the same engine-agnostic toolkit the web recipes use, over two thin Agora engine adapters.
recipe-client-rn-quickstart/
├── server/ # reused keyless Python/FastAPI backend (get_config, startAgent, stopAgent)
└── rn/ # bare React Native app (the star)How it works
- Toolkit, reused not vendored:
agora-agent-client-toolkit(MIT,
engine-agnostic) is npm installed. AgoraVoiceAI.init(...) emits TRANSCRIPT_UPDATED / AGENT_STATE_CHANGED.
- Engine adapters (the net-new work) in
rn/src/agora/: RtcEngineAdapterover `react-native-agora`
(RTC) — implements the toolkit's RTCEngine and owns the channel join with the microphone published (ChannelMediaOptions { publishMicrophoneTrack: true, autoSubscribeAudio: true, clientRoleType: Broadcaster }).
RtmEngineAdapterover `agora-react-native-rtm`
(RTM 2.x) — implements the toolkit's RTMEngine and carries the transcript (our agent uses data_channel:"rtm"). It translates each native RTM MessageEvent into the { publisher, messageType, message } shape the toolkit reads.
- Lifecycle:
getConfig→ RTMlogin+ RTCjoin→AgoraVoiceAI.init→
`subscribeMessage(channel)` BEFORE `startAgent` → transcript upserted by (turnId, type) and rendered in a FlatList keyed by ` ${turnId}-${type} `.
- Render mode:
TranscriptHelperMode.TEXT(full-text transcript updates). - Zero-key: the backend uses a managed keyless cascade — only
AGORA_APP_ID / AGORA_APP_CERTIFICATE are required.
Run it
1. Backend
cd server
uv venv venv && . venv/bin/activate
uv pip install -r requirements.txt -r requirements-dev.txt
python src/server.py # binds 0.0.0.0:8000Provide AGORA_APP_ID / AGORA_APP_CERTIFICATE via .env.local (see .env.example).
2. React Native app (Android)
cd rn
npm install
npx react-native run-android # starts Metro + installs on a running emulator/deviceThe app reaches the backend at AGENT_BACKEND_URL = http://10.0.2.2:8000 (rn/src/config.ts) — 10.0.2.2 is the Android emulator's alias for the host's localhost. (For an iOS simulator, use http://localhost:8000.) Grant the microphone permission when prompted, then tap Connect — the agent greets you on join.
Testing
cd rn
npx tsc --noEmit # typecheck (pins the Agora SDK + toolkit signatures)
npm test # Jest unit test for BackendApi (mocked fetch)
cd android && ./gradlew assembleDebug # native build (Agora RTC + RTM autolinking)cd server && pytest -q # backend testsCI (.github/workflows/ci.yml) runs the server tests plus the RN typecheck, Jest, and assembleDebug. docker.yml builds and smoke-tests the backend image.