When bringing AI capabilities into apps in iOS 27, you are faced with two paths running in opposite directions. If you want Siri to invoke features in your app at the system level, use App Intents; if you want to call models inside your app for long-document summarization, receipt extraction, or visual understanding, use Foundation Models. If you have previously written function calling or integrated MCP, the roles of these two sets of APIs will feel familiar: one turns your app into a tool for external models to call, while the other lets your app act as the caller sending requests to models.
These two paths have their own dedicated tracks within the system. Developers cannot replace Siri’s inference engine with custom models, nor can apps reach across sandboxes to directly read each other’s data. The system architecture enforces these boundaries strictly, and the two APIs address their respective engineering needs.
When a user says to their phone, “Hey Siri, remove milk from my shopping list,” that sentence ultimately triggers a specific function in the app, with parameters accurately mapped to the entry for milk. The intermediate speech recognition, intent inference, entity extraction, and parameter assembly are all handled by the system. Developers only need to declare two things clearly in advance: what actions the app supports executing, and what data those actions operate on (App Intents documentation).
The actions an app can execute map to AppIntent. For
example, deleting a list item is an AppIntent, where code
explicitly defines what inputs it receives and what logic executes when
triggered. By analogy to MCP, this is like a tool defined in an MCP
server, except it is written in native Swift code and determined at
compile time.
The data operated on by an action maps to AppEntity.
Tool parameters often point to specific objects, such as deleting a
particular to-do item or playing a specific song. AppEntity
annotates in-app data models with a unique identifier and several
attributes recognizable by the system, allowing the “milk” spoken by the
user to match accurately with a primary key in the database. This does
not require tearing down and redesigning existing database tables; it
simply requires conforming to a descriptive protocol for the system.
Every app has its own naming habits, and the system cannot memorize arbitrary vocabularies coined by every team. Apple’s solution is to define 12 generic domains covering Audio, Calendar, Mail, Messages, Maps, Photos, Reminders, and more (full list), and predefine standard actions and data templates for each domain. When developing a music app, as long as you adopt the Audio domain template, Siri naturally understands what play, pause, and playlists mean. This is equivalent to Apple pre-provisioning categorized tool namespaces, eliminating the cost for each team to define its own Schema.
The rules for adopting these domains are very clear. Three domains—Mail, Messages, and Clock—must be adopted in their entirety, with no support for cherry-picking individual actions (official rules). If a business scenario falls outside these 12 domains, the app cannot obtain Siri’s natural language understanding capabilities and must fall back to fixed-phrase invocation, requiring users to recite exact, word-for-word voice commands. Before writing code, check whether your core scenarios fall within these templates.
In addition to registering actions with the system, Siri must be able to search the app’s data at any time, which relies on Spotlight indexing. When a user asks Siri to retrieve meeting notes from last month, Siri queries the Spotlight index; if the app has not written that record into the index, Siri cannot find the content. The system also offers two supplementary channels: one automatically records high-frequency user interaction patterns in the UI in the background, and the other allows the app to proactively notify the system when a specific piece of content is currently active. For detailed mechanics, refer to session 345.
When writing code, you will also run into several runtime rules. When a user looks at the screen and says “open the third one,” for Siri to understand the referent on screen, the developer must have annotated the UI element with the corresponding entity attributes (session 343). Synchronous execution of an Intent is capped at 30 seconds by default. Long-running tasks such as video export or large file transcoding must adopt the dedicated long-running task API and continuously push progress to the system; otherwise, upon timeout or when system resources are constrained, the system will terminate the task (LongRunningIntent). SiriKit, used for many years in the past, is deprecated in iOS 27, making App Intents the sole entry channel into the system (SiriKit).
In popular domains like Mail and Calendar, several apps often
register identical action templates simultaneously, leaving multiple
competitors standing behind the same action. When a user issues an
ambiguous command, dispatch authority lies in the system orchestration
layer, distributed collectively by Siri and Shortcuts, with no channel
for third-party apps to invoke one another. As noted verbatim in WWDC26
lab session
8011, “There’s no API for a third-party app to invoke another app’s
intents directly”; Siri and Shortcuts are the orchestrators. When the
system is unsure, it displays a list for the user to select manually;
when an app itself encounters ambiguity while resolving parameters, it
can also proactively throw needsDisambiguationError to
present candidate results for the user to tap and confirm.
Apple has not publicly disclosed the specific scoring mechanism for tie-breaking; the only explicitly mentioned bonus factor is interaction donation. The more frequently a user taps inside an app in everyday use, the more Siri leans toward that app when making inferences; as stated verbatim in session 343: “Siri might infer the right app to use for that contact”. Viewed through an MCP lens, when multiple servers register tools with identical names, how an intermediate gateway performs intent routing is a black box on iOS. Merely registering actions with the system is just completing declarations and does not guarantee that Siri will invoke them every time; the developer’s sole lever is to get users using the app frequently in real life, building scheduling advantage through genuine interaction records.
Another category of requirements runs in the exact opposite direction: this time, the app proactively invokes models on its own initiative. Examples include long-document summarization, recognizing amounts and dates from receipt photos, or searching content using natural language within the app. These requirements correspond to Foundation Models (framework documentation).
The core interaction of this framework revolves around
LanguageModelSession. In code, you initialize a session,
pass in prompts and optional image attachments, and retrieve inference
results asynchronously. The underlying models support three sources,
exposing a unified invocation protocol where switching models requires
changing only a single line of configuration:
| Source | Characteristics | Cost |
|---|---|---|
| Apple on-device models | Runs on the phone, available offline, rebuilt in iOS 27, supports image inputs | Free, unlimited |
| Apple Cloud (PCC) | 32K context, more capable | Daily quota; requires entitlement application; free only for developers with under 2 million downloads in the first year (Details) |
| Your own models | Implements the same protocol and packaged in; Anthropic and Google have both released official packages (session 339) | Billed according to each provider’s API pricing |
On-device models do not require applying for any developer
entitlements; you can call them directly upon importing the module (entitlements
list). On macOS 27, Apple also includes the command-line tool
fm, allowing you to send requests directly to models in the
terminal to debug prompts without compiling the entire project.
When initializing LanguageModelSession, if you do not
explicitly specify model parameters, the system loads the on-device
model SystemLanguageModel.default by default. Multiple test
reports across developer communities confirm this default behavior (see
Create
with Swift and Artem
Novichkov’s post). All three model sources follow the same session
protocol, so switching models later only requires adjusting the
constructor parameters.
Which model you choose in a session affects only the app’s own internal logic and cannot affect the system’s Siri. This is also key to distinguishing the two systems: in Foundation Models, the app acts as the caller and can freely pick an appropriate model provider; while on the App Intents side, the app steps back into the tool role, waiting for the system to initiate calls.
When processing concrete business data, structured outputs save a
great deal of trouble. Previously, having a model extract fields often
required writing complex regular expressions to parse unstructured text.
Now, by adding the @Generable macro to a Swift struct, the
model directly generates data structures conforming to that type
definition. If a field type mismatches, the generation process halts
with an immediate error.
When dynamic data queries are needed, the app can register functions with the session, allowing the model to initiate tool calling during inference. For example, if you maintain a private local database, after registering a query function, whenever the model detects that the current context lacks necessary information, it pauses output and calls this function, continuing its reasoning after receiving the returned results. This eliminates the overhead of stuffing all data into prompts upfront, and the system even comes with two ready-made built-in Tools for text recognition and barcode recognition (session 241).
Some ideas seem very natural from a technical perspective, yet searching through public documentation reveals no entry points. In iOS’s architectural design, an app can serve as a tool for the system to invoke or as a client that calls models, but the role of the system-level agent—the global coordinator—remains squarely in Apple’s hands.
Many people initially wonder whether they can swap Siri’s model for their own. The public SDK provides no registration API that allows developers to mount an external model as Siri’s inference engine; the flexibility to swap models exists only within the app’s own local sessions. This can easily lead to misunderstandings: in the Japanese market, the system does support configuring the iPhone side button to launch third-party voice apps, but this is merely a system-level quick-launch shortcut that has nothing to do with Siri’s inference layer (Details).
Another common thought is having an app cross boundaries to read another app’s data, such as an expense tracker directly reading recent transactions from a banking app. On iOS, there is no channel for apps to invoke one another; all cross-app actions must be orchestrated centrally by Siri, and each app’s local data resides in an isolated sandbox (session 8011). An expense tracker attempting to bypass the system to fetch external data cannot work at the underlying level.
Even when user data distributed by the system is received via App Intents, developer agreements strictly prohibit uploading or transferring this information off-device (DPLA). Coupled with this are two App Review red lines: apps cannot dynamically download and execute code at runtime that alters their functional behavior (Review Guidelines 2.5.2); and if user data is indeed to be sent to third-party AI APIs, the app must explicitly inform the user and obtain consent beforehand.
Apple keeps agent dispatch authority firmly locked in its own hands, explaining its rationale in a public statement regarding the EU: opening global control interfaces to outsiders would be tantamount to allowing any virtual assistant to access users’ private data and control other apps (Original statement). In the open MCP ecosystem, both the tool-side server and the orchestration-side client are open to developers; in the iOS world, however, only Apple can occupy the orchestrator’s seat.
Wiring up the basic interfaces actually does not take much time. The official calendar demo project needs only three Swift structs to run the entire flow on a physical device (session 344); on the model-calling side, a few lines of code complete the session declaration and fetch a response. Where engineering time is truly consumed is tracking down runtime silent failures and dealing with model instability.
The biggest time sink when integrating with Siri is troubleshooting silent failures. This system has numerous implicit runtime rules; the Swift compiler checks only syntax and types, but if you violate these rules at runtime, the console neither crashes nor throws an error—the only symptom is that Siri simply gives no response to your app. One developer who repeatedly stumbled into these pitfalls distilled it into a single sentence: “Pass the compiler and fail one of those, and you get silence.” (Source).
Troubleshooting such issues is frustrating because the pitfall scenarios fall almost entirely outside the view of the console. For instance, declaring that an Intent must execute in the foreground while the user invokes voice from the lock screen; defining trigger phrases too narrowly so that slight rephrasings fail to match; forgetting to notify Spotlight to refresh its index after business data updates; or failing to distinguish between passing a null value versus omitting a parameter in an update API, leading to accidental loss of existing data. Because the console provides no stack traces or hints, every debugging effort requires going through a checklist item by item.
On the Foundation Models side, time is primarily spent accommodating model non-determinism. The on-device model’s context window is only 4096 tokens, where system prompts, tool function definitions, conversation history, and generated outputs must all share quota in this tight space; Apple officially recommends attaching no more than 5 tool functions per request (Managing the Context Window). Small on-device models occasionally fail to call tools or hallucinate numbers from thin air, and such failures likewise raise no exceptions at the code level: tests pass cleanly the first few times, but the next time the model wanders down an unexpected branch and returns an erroneous result, easily leading you to suspect local data corruption during debugging. Apple specifically provides an evaluation framework for this reason, and day-to-day development must rely on annotated datasets for systematic regression testing—relying solely on manual ad-hoc prompting makes it very hard to maintain a baseline of stability (session 241).
When planning your schedule, you can break down the work by scenario.
If your priority is gaining voice distribution through Siri, first
verify whether your core features align with the 12 domain templates; if
they fit, complete the action and entity declarations as early as
possible, write your data into Spotlight, and budget plenty of effort to
thoroughly test lock screen states and index synchronization. If your
goal is enhancing business processing capabilities within the app, start
with the free, offline on-device model, keep the number of tools per
invocation within 3, and use @Generable to safeguard
input/output contracts. The two paths are independent of each other and
can evolve separately. As for replacing the system voice assistant or
pulling data across apps, there are currently no public APIs, so you can
simply wait and observe in future releases.