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)
- Toolkit, reused not vendored:
agora-agent-client-toolkit(MIT, engine-agnostic) isnpm installed.AgoraVoiceAI.init(...)emitsTRANSCRIPT_UPDATED/AGENT_STATE_CHANGED. - Engine adapters (the net-new work) in
rn/src/agora/:RtcEngineAdapteroverreact-native-agora(RTC) — implements the toolkit'sRTCEngineand owns the channel join with the microphone published (ChannelMediaOptions { publishMicrophoneTrack: true, autoSubscribeAudio: true, clientRoleType: Broadcaster }).RtmEngineAdapteroveragora-react-native-rtm(RTM 2.x) — implements the toolkit'sRTMEngineand carries the transcript (our agent usesdata_channel:"rtm"). It translates each native RTMMessageEventinto the{ publisher, messageType, message }shape the toolkit reads.
- Lifecycle:
getConfig→ RTMlogin+ RTCjoin→AgoraVoiceAI.init→subscribeMessage(channel)BEFOREstartAgent→ transcript upserted by(turnId, type)and rendered in aFlatListkeyed 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_CERTIFICATEare required.
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).
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.
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.