Fully on device
No account, no key, no per-request cost, and it works in airplane mode. Download local models and assign them. Slower, and the models are smaller than cloud ones.
You choose what powers each stage of the agent. This guide covers all of the options — the local models that need no account at all, the cloud providers that need an API key, phone calls through your own Twilio account, and MCP tool servers.
The app is not released yet. This guide is published early so you can see exactly what setup involves, and prepare the accounts you want before launch. Join the waitlist to hear when it ships.
Answering you takes three stages, and you pick what handles each one independently:
Speech to text Assistant (LLM) Text to speech
Music, Web Search, Calls, Navigation and where Notes are stored are chosen the same way. You are not tied to one vendor: run the assistant locally for privacy while using a cloud voice for quality, or any other combination that suits you.
Everything below lives under the gear icon, top-right. Two status icons at the top of the Voice tab tell you whether you are ready to go:
| Icon | Green when |
|---|---|
| AI engine | All three active engines (speech-to-text, assistant, text-to-speech) are ready. A local engine needs a model file assigned; API and system engines are always ready. |
| WiFi | The device has internet connectivity. |
The green AI icon answers “is a model assigned and valid”, not “will it fit in memory right now”. Those are different questions — see memory limits.
No account, no key, no per-request cost, and it works in airplane mode. Download local models and assign them. Slower, and the models are smaller than cloud ones.
Best quality and speed, and streaming listening stays available. You bring your own API keys and pay your provider directly for what you use.
The usual choice. A local assistant for privacy with a cloud voice for quality, or cloud everything with local engines configured as the offline fallback.
Local engines run entirely on the iPhone. Audio, transcripts and inference never leave the device, and nothing is sent to any provider. They need model files in GGUF format, which you download inside the app.
resolve/main/ that points at the .gguf file itself, not the model's web page.Only huggingface.co URLs are accepted — the allowlist is enforced at download time, so a link from anywhere else will be refused. Files are stored in the app's own sandbox and tracked in a manifest that survives restarts, and your engine and model choices persist too. You can also import model files through the Files app instead of downloading.
Browse GGUF models on Hugging Face
Assign a GGUF chat model to the Assistant role, then select llama.cpp (offline) under Settings → AI → Engines. One thing to know before you rely on it: Continuous (streaming) listening turns off while a local assistant is selected, because it processes one request at a time on the device. Auto (loop) listening still works.
Assign a Whisper GGUF model to the Speech-to-text role and select Whisper.cpp (offline) in the engine list. This is what lets the agent hear you with no network at all.
This is the one setup step that catches people out. OuteTTS 0.3 needs two GGUF files, not one:
Set the OuteTTS model path as the active text-to-speech model. The WavTokenizer file is discovered automatically from the same directory, provided its filename contains wavtokenizer or vocoder. If the voice never produces sound, that filename is the first thing to check. Output is 24 kHz mono audio.
Local models are the largest thing the app ever puts in memory. A recommended assistant model is around 1 GB, plus a few hundred megabytes of working memory while it answers. If the iPhone cannot spare that, iOS terminates the app rather than letting it continue — no crash report, it simply closes, which looks like a bug but is not one.
The app checks before loading and tells you, with the real numbers, if a model will not fit: close other apps, or assign a smaller model. If iOS kills it anyway — another app can claim the memory at any moment — the next launch writes a red entry in Settings → Logs → Engine Calls naming the model and how much memory was free, because an app that has been killed never gets to report it itself.
Available with no key and no download. Select Apple SpeechRecognizer for speech-to-text or Apple Siri voice for speech. One limit worth knowing: the Siri voice can only speak languages your device has a voice installed for. If you pick one it cannot speak, the app says so and names the fix — install the voice in iOS Settings → Accessibility → Spoken Content → Voices, or switch to ElevenLabs, Gemini or OpenAI, which are multilingual.
On iOS 26 or later, on a supported iPhone with Apple Intelligence switched on, you can pick it as the assistant. No key, no monthly cost, no multi-gigabyte download, and it works in airplane mode. It is not Siri — Apple provides no way for an app to ask Siri a question; this is the model underneath, used directly. Like llama.cpp, it disables continuous streaming listening, its answers arrive in one piece rather than word by word, and Apple's model is smaller than a cloud model, so reasoning-heavy requests may land better elsewhere.
Every credential goes in one place: Settings → Vault → API Keys. They are stored in the iOS Keychain, never in plain text and never in preferences, and requests go straight from your device to that provider. No bpaas.it server sits in between, and we never see your keys.
You only need keys for the engines you actually select. Get each one from the provider, then paste it into the Vault.
| Provider | What you need | Powers | Where to get it |
|---|---|---|---|
| OpenAI | API key | Speech-to-text (Whisper), assistant (GPT), text-to-speech, web search | platform.openai.com → API keys |
| Anthropic | API key | Assistant (Claude), web search | console.anthropic.com → API keys |
| Google Gemini | API key | Speech-to-text, assistant, text-to-speech | ai.google.dev → get an API key |
| ElevenLabs | API key. The voice is picked separately — see below | Speech-to-text, text-to-speech | elevenlabs.io → profile settings for the key; copy the voice ID from the voice you want |
| Google Search | API key and a Programmable Search engine ID (CX) | Web search | Custom Search JSON API for the key, Programmable Search Engine for the CX |
| Google (sign-in) | OAuth client ID | Google-account features | Google Cloud Console → Credentials → OAuth client ID (iOS) |
| Twilio | Five values — see Calls | Translated phone calls | console.twilio.com |
A note on cost. Because you bring your own keys, you pay each provider directly for what you use, at their rates. There is no markup from us, and no subscription to BPaaS for the app itself.
Once the keys are in the Vault, go to Settings → AI → Engines and pick the active engine for each capability. Where a provider offers several models or voices — OpenAI, Gemini, Claude, ElevenLabs — you choose which on that same screen. The ElevenLabs voice ID goes here rather than in the Vault: it identifies a voice, it is not a secret.
If you use the interpreter or translated calls, this decides whether the other person can follow you. The app tells the voice which language to speak, but how much notice it takes depends on the engine and, for two of them, on which model you picked:
| Engine | What it does with the language |
|---|---|
| Gemini TTS | Takes it directly, including the regional variant — Brazilian and European Portuguese stay distinct. |
| ElevenLabs TTS | Takes it, but only on the Turbo v2.5 and Flash v2.5 models. The multilingual default rejects the setting, so switch model if pronunciation matters. |
| OpenAI TTS | Has no language setting. The app asks the voice to speak the language instead, which works on GPT-4o mini TTS — on the older TTS-1 models nothing can be done. |
| Apple Siri voice | Picks a real voice for the language, or tells you it cannot. |
| OuteTTS (local) | One voice whatever the language — an accepted limit of the on-device model. |
When the app cannot pass the language on, it says so in Settings → Logs → Engine Calls against that spoken line, with the reason. That is the place to look if something still sounds wrong.
Each capability has its own offline engine choice, and a degraded-network tier, on the same Engines screen. This is what makes a mixed setup worthwhile: run cloud engines normally, and name a local model to take over when the connection goes. If you have a local model assigned, going offline — airplane mode included — no longer produces a connection error; the app answers on your local model instead, from the very first message.
A slow or flaky connection is treated differently on purpose: that still retries the cloud rather than quietly downgrading you.
Choose Apple Maps or Google Maps under Settings → AI → Engines. Both are free and neither needs an account or a key. Google Maps opens the app if it is installed, otherwise the browser.
iOS does not let an app embed either vendor's turn-by-turn guidance, so the maps app draws the route and speaks the turns while this app keeps listening in the background — the wake word still works mid-drive.
The two differ in one way worth knowing before you pick: asking to add a stop on the way routes via that stop and keeps your original destination in Google Maps, while Apple Maps has no multi-stop link, so it navigates to the stop and the assistant tells you what to say to carry on.
On-device storage is the default and, today, the only option — there is nothing to configure. Notes are kept encrypted on the phone, never appear in the shared timeline, and are excluded from diagnostics exports.
One thing to be deliberate about: tapping the lightbulb for ideas sends your notes to whichever assistant engine you have selected. If you would rather they never leave the device at all, pick a local assistant before using it.
Dictation follows the same rule — with the local Whisper engine selected it never leaves the device and works offline.
The translated-call modes place real phone calls through your Twilio account. Call tokens are created on your device with your own credentials, so no third-party server sits between you and Twilio. The Twilio SDK ships inside the app; there is nothing to install.
Five values go into Settings → Vault, all from the Twilio Console:
There is also a one-time setup inside the Twilio console itself to connect those pieces together. When a call cannot connect, the failure names the Twilio error code and the likely fix, and Settings → Logs → Engine Calls records the whole call lifecycle, so a misbehaving call is diagnosable from the log alone.
Want to try it without an account? Select the Loopback (Echo Test) call engine. It needs no Twilio account and no credentials: your microphone and the phrases the app speaks echo back as “the other party”, so you can exercise the whole call flow — even in the simulator.
Model Context Protocol is an open standard for exposing tools to an assistant. Register an HTTPS MCP server and its operations become things the agent can actually do — “ask the docs server about this repository”, query a database, reach a business system.
Six ways, all set up when you add the server or later on its page, where every field stays editable — including the method itself:
| Method | You supply |
|---|---|
| None | Nothing. The simplest servers to try first. |
| Bearer token | A long-lived token from the service. The simplest thing to register. |
| Custom header | A header name and its value. |
| Username & password | Both, stored in the Keychain like any other credential. |
| OAuth — client credentials | A client ID and secret from the provider's console. |
| OAuth — browser sign-in | A client ID, and the scopes the server's documentation lists. This is what “connect your account” services need. |
Google's servers use OAuth browser sign-in. Google's own documentation is the authority on which server you want and how to create a client — we deliberately do not reproduce those steps, because they change and a stale copy is worse than none:
Google MCP Toolbox documentation Google Cloud Console
Come back with a server URL, an OAuth Client ID, and the scopes that server's documentation asks for. Then:
Create an “iOS” OAuth client, not a “Web” one. iOS only lets the sign-in return to a custom address like yourapp:/callback, so a Web client cannot work from a phone. The app tells you so rather than leaving the browser hanging.
By default every call asks you first, showing exactly what would be sent, and you approve or deny by voice or text. Each server — and each individual operation — can relax or tighten that on its own settings page. Results come back labelled as external data, and the assistant can never approve its own request: only a message from you can. If a server is unreachable, missing a credential, or simply not signed in yet, its operations are not offered at all, rather than failing mid-conversation.
There is also a refreshable catalog repository of suggested MCP servers under the same settings screen. Only allowlisted domains are accepted, a refresh happens only when you tap it, and a fetched catalog can suggest a server — never enable one.
Works with the media library permission the app asks for. Catalog search — playing a song you do not already own — is off by default under Settings → AI → Engines → Apple Music Catalog, and additionally needs MusicKit enabled for the app and an active Apple Music subscription. While it is off, the agent simply does not offer catalog search, so it will not promise something it cannot do.
One honest limit: with Apple Music, volume and mute cannot be changed by software. iOS reserves system volume for the hardware buttons and Control Centre, and the agent says so rather than pretending.
Three options, all keyed from the Vault: Google Search (API key plus Programmable Search CX ID), OpenAI Web Search (your OpenAI key), or Claude Web Search (your Anthropic key). The agent searches, reads the top pages and answers with a summary rather than dumping links at you.