iOS CallKit + WebRTC for AI Voice Agents: 2026 Production Guide
CallKit + WebRTC + PushKit is the only Apple-blessed path for AI voice agents on iOS. Here is the 2026 production playbook with audio-session, ICE, and CXProvider details.
CallKit is not optional. Every iOS AI voice agent that wants to ring like a phone, survive backgrounding, and play audio over the right route in 2026 has to live inside CXProvider — and inside a WebRTC pipeline that knows how to share an AVAudioSession with it.
Background
Apple introduced CallKit in iOS 10 to give VoIP apps the same affordances as the native Phone app: lock-screen ringing, native call UI, integration with the Recents and Contacts databases, and proper audio routing through the system phone manager. In 2026, CallKit remains the only Apple-blessed path for "the app must ring even when killed". For AI voice agents, that means an inbound call from your scheduling assistant, your real-estate agent, or your healthcare intake bot must come up the same way as a FaceTime audio call.
WebRTC handles media; CallKit handles UX and the audio session; PushKit wakes the app. Skipping CallKit means iOS will throttle background CPU, the audio session will not switch routes correctly when AirPods connect, and the user will be unable to answer from the lock screen. Skipping WebRTC means you ship SIP-over-WebSocket, which is fine on Wi-Fi and dies on cellular NAT.
Architecture
```mermaid flowchart LR Server[Voice Agent Backend] -- VoIP push --> APNs[(Apple APNs)] APNs -- PushKit payload --> App[iOS App] App -- reportNewIncomingCall --> CXProvider[CallKit CXProvider] CXProvider -- user answers --> WebRTC[WebRTC PeerConnection] WebRTC -- DTLS-SRTP --> Gateway[Pion Go gateway 1.23] Gateway -- NATS --> Pod[6-container agent pod] ```
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
CallSphere implementation
CallSphere uses this exact stack for the iOS clients of two of its six verticals (real estate, healthcare, behavioral health, legal, salon, insurance):
- Real Estate (OneRoof) — Inbound buyer/seller calls land on a Pion Go gateway 1.23, which forwards over NATS to a 6-container pod (CRM, MLS, calendar, SMS, audit, transcript). The iOS app is a thin CallKit + WebRTC client. See /industries/real-estate.
- Healthcare — The same iOS client pattern, but the agent pod is OpenAI Realtime with HIPAA controls. See /industries/healthcare and /lp/healthcare.
- /demo browser path — On the marketing site, the same WebRTC pipeline runs in plain Safari/Chrome — no CallKit needed. Try it at /demo.
Across 37 agents, 90+ tools, 115+ database tables, and HIPAA + SOC 2 controls, the iOS layer is genuinely thin: it terminates SRTP, hands frames to AVAudioEngine, and lets CallKit own the UI. Pricing remains $149/$499/$1499 with the 14-day /trial; affiliates earn 22% — see /affiliate.
Build steps with code
```swift // 1. Configure CXProvider once at app launch let config = CXProviderConfiguration() config.supportsVideo = false config.maximumCallsPerCallGroup = 1 config.supportedHandleTypes = [.generic] let provider = CXProvider(configuration: config) provider.setDelegate(self, queue: nil)
// 2. On PushKit VoIP push, report immediately (within 5s) func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { let uuid = UUID() let update = CXCallUpdate() update.remoteHandle = CXHandle(type: .generic, value: payload.dictionaryPayload["from"] as? String ?? "AI Agent") update.hasVideo = false provider.reportNewIncomingCall(with: uuid, update: update) { error in completion() } }
// 3. On answer, configure RTCAudioSession before peer connection setup func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { let session = RTCAudioSession.sharedInstance() session.lockForConfiguration() try? session.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.allowBluetooth, .duckOthers]) try? session.setMode(AVAudioSession.Mode.voiceChat.rawValue) session.unlockForConfiguration() startWebRTC() action.fulfill() } ```
Pitfalls
- Forgetting reportNewIncomingCall within 5 seconds — iOS terminates your app and disables future PushKit deliveries. Apple enforces this OS-level since iOS 13.
- Configuring AVAudioSession before CallKit activates it — the system will silently reset your category. Always configure inside `provider:didActivate:` or after the answer action.
- Missing the `voip` background mode in Info.plist — PushKit silently fails.
- Using regular APNs instead of PushKit for incoming calls — regular pushes are not high-priority and will not wake a terminated app.
- Calling `AVAudioSession.setActive(true)` directly — let CallKit own activation.
FAQ
Is CallKit required for AI voice agents? Yes for inbound that should ring; outbound-only apps can skip it but lose proper audio routing.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
Does CallKit work in China? Apple disables CallKit in mainland China builds; ship a separate non-CallKit build for the App Store China region.
Can I show my own custom UI? Use CallKit's "non-UI" providers and present custom screens after answer; lock-screen ringing must still be CallKit.
Does it work with WebRTC's default RTCAudioSession? Yes — `RTCAudioSession.sharedInstance()` is designed for exactly this; do not instantiate `AVAudioSession` directly.
What happens during an interrupting phone call? CallKit pauses your call; WebRTC sees an audio interruption notification and you must hold and resume the peer connection.
Sources
- https://developer.apple.com/documentation/callkit
- https://developer.apple.com/documentation/pushkit/responding-to-voip-notifications-from-pushkit
- https://medium.com/@tsivilko/mastering-voip-audio-with-callkit-and-webrtc-on-ios-0f2092402331
- https://github.com/react-native-webrtc/react-native-callkeep
- https://www.videosdk.live/developer-hub/voip/ios-voip-callkit
Try the WebRTC + CallKit path live at /demo, browse plans at /pricing, or start a /trial.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.