Foundation Models On-Device LLM : le Tool Protocol
Genre : frontier-essay. Ce billet identifie le contrat de LLM on-device qu’Apple a livré à la WWDC 2025 et examine la question du routage : quand LanguageModelSession est-il la bonne réponse, quand l’est AppIntent, quand l’est MCP, et quand aucune des trois solutions ne convient.
iOS 26 livre un modèle de langage de 3 milliards de paramètres sur chaque appareil compatible Apple Intelligence.1 Apple appelle ce framework Foundation Models. Le framework est local. L’inférence est optimisée pour Apple silicon et s’exécute on-device ; le réseau n’intervient pas dans l’appel. Le modèle se trouve à SystemLanguageModel.default, votre app obtient une LanguageModelSession, et la surface typée qui permet à cette session de faire un travail utile est le protocole Tool.
Le protocole Tool est ce qui compte pour les développeurs d’applications. Sans lui, le LLM on-device n’est qu’un endpoint de complétion de chat sans connexion aux données de votre app, aux données de votre utilisateur ou au reste du système. Avec lui, le modèle peut appeler des fonctions Swift typées, recevoir des résultats typés en retour et raisonner sur la réponse au tour suivant. La génération on-device augmentée par des outils est la véritable capacité du framework. La surface de chat n’est que la démo.
TL;DR
- Foundation Models donne à chaque appareil éligible à Apple Intelligence un LLM de 3 milliards de paramètres à
SystemLanguageModel.default. Le modèle est local ; l’inférence est optimisée pour Apple silicon et s’exécute on-device ; le réseau est hors du chemin d’appel. - Le protocole Tool est le contrat entre le modèle et votre app. Un outil déclare des
Argumentstypés, retourne unOutputtypé et est lié à uneLanguageModelSessionau moment de la construction. - Les annotations
GenerableetGuidepermettent au modèle de produire directement des valeurs Swift typées, et non plus seulement des chaînes. Le décodeur fait partie du framework, pas de votre code. - La règle de routage entre Foundation Models, App Intents et MCP est qui exécute le modèle et où. Foundation Models = votre app exécute le modèle on-device. App Intents = Apple Intelligence exécute le modèle on-device et route vers votre app. MCP = un hôte externe exécute le modèle où il le souhaite et accède à votre app via un serveur d’outils.
Ce que le framework fournit réellement
Trois primitives portent le framework : le modèle, la session et l’outil.2
SystemLanguageModel. Une référence au modèle de fondation on-device. L’instance par défaut est liée à l’appareil de l’utilisateur, disponible sur le matériel éligible à Apple Intelligence, et expose des vérifications de capacité que l’app lit à l’exécution pour décider si le modèle est disponible. Le framework prend en charge la configuration via SystemLanguageModel(useCase:guardrails:), des adaptateurs personnalisés et GenerationOptions, mais vous ne choisissez pas d’identifiants de modèle cloud arbitraires comme vous le feriez avec OpenAI ou Anthropic ; Apple livre et met à jour le modèle on-device à chaque version d’OS, et le framework vous remet la version actuellement installée.
LanguageModelSession. Un objet à état qui conserve l’état conversationnel entre les appels. La session reçoit un prompt système à la construction, accumule les tours utilisateur/assistant au fil du temps et expose des méthodes asynchrones pour générer des réponses. Les sessions sont légères à créer et jetables ; vous en créez une par tâche, pas une par app. Une app de minuteur de méditation crée une session pour « résume mes 7 derniers jours de pratique » ; une app de recettes crée une session différente pour « convertis cette recette pour deux personnes au lieu de quatre ».
Tool (le protocole). Un protocole Swift qui déclare un type Arguments, un type Output et une fonction asynchrone call(arguments:). Les outils sont liés à une session à la construction (LanguageModelSession(tools: [...], instructions: ...)). Quand le modèle décide qu’il a besoin d’un outil, il émet un appel structuré ; le framework décode les arguments, exécute l’outil, encode le résultat et le réinjecte dans la session pour le tour suivant. Le modèle ne voit pas Swift ; le framework s’occupe du marshalling.
La forme du protocole Tool, condensée :
import FoundationModels
struct WaterEntryLookup: Tool {
let name = "lookup_water_entries"
let description = "Look up water intake entries for a given date range."
@Generable
struct Arguments {
@Guide(description: "Start date in ISO-8601 format")
let startDate: String
@Guide(description: "End date in ISO-8601 format")
let endDate: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
let entries = try store.entries(
from: ISO8601DateFormatter().date(from: arguments.startDate) ?? .now,
to: ISO8601DateFormatter().date(from: arguments.endDate) ?? .now
)
return ToolOutput(GeneratedContent(properties: [
"count": entries.count,
"total_ml": entries.reduce(0) { $0 + $1.amountMl }
]))
}
}
Le modèle voit une description d’outil et un schéma d’arguments en forme de JSON. Le code Swift voit une entrée typée et une sortie typée. La frontière de décodage/encodage est la partie qui appartient à Apple.
Generable et Guide : sortie typée sans parser
Le même système d’annotations qui rend les arguments d’outils typés permet aussi au modèle de produire directement des valeurs Swift typées.3 Une struct @Generable déclare sa forme ; le framework contraint la sortie du modèle à correspondre.
@Generable
struct PracticeSummary {
@Guide(description: "Single-sentence headline summarizing the user's week")
let headline: String
@Guide(description: "Total practice duration this week in minutes")
let totalMinutes: Int
@Guide(description: "Three short observations as bullet points")
let observations: [String]
}
let session = LanguageModelSession(instructions: "You are a meditation coach.")
let summary = try await session.respond(
to: "Summarize this week of practice given the entries.",
generating: PracticeSummary.self
)
Le modèle retourne une valeur PracticeSummary. Pas d’analyse JSON dans votre code, pas de correspondance de chaînes pour « headline: », pas de repli quand le modèle a renvoyé un objet malformé. Le framework utilise le décodage contraint pour maintenir la sortie token par token du modèle structurellement alignée avec le schéma, de sorte qu’aucune sortie structurellement invalide ne franchit la frontière.
La surface typée Swift est ce qui distingue le framework des SDKs de LLM cloud. Les SDKs cloud (OpenAI Structured Outputs, l’utilisation d’outils chez Anthropic, et d’autres) prennent aussi en charge le décodage contraint, mais la valeur typée que le développeur reçoit est un objet JSON validé contre un schéma, puis décodé en un type Swift Codable dans une étape distincte. Foundation Models fusionne ces étapes : la macro @Generable et le décodeur du framework produisent une valeur Swift typée comme retour direct, les annotations @Guide au niveau du champ portant l’intention dans la contrainte de génération. La sortie est typée parce que la génération a été typée contre le schéma Swift, pas contre une spécification JSON que le développeur aurait reconstruite en Swift.
Les annotations @Guide permettent de communiquer l’intention au niveau du champ au modèle sans l’écrire dans le prompt. La description générée fait partie de la contrainte de génération. Les guides au niveau du champ gardent le prompt propre et le schéma proche des données.
La question du routage, vue sous trois angles
Apple propose désormais trois surfaces de protocole qu’une app peut utiliser pour exposer son domaine à un modèle de langage. Elles routent vers des exécutants différents.
Foundation Models (LanguageModelSession). Votre app charge le modèle on-device et exécute l’inférence. Les outils que la session peut appeler sont des outils définis par le code de votre app. Le modèle ne quitte jamais l’appareil. L’utilisateur ne déclenche pas cela via Siri ; c’est le code de votre app qui le fait. Le cas d’usage se situe à l’intérieur de votre app : une app de méditation qui utilise le LLM pour résumer une semaine, une app de recettes qui adapte une recette à moins de portions, un suiveur d’hydratation qui transforme « j’ai bu un verre au déjeuner » en entrée structurée.
App Intents. Apple Intelligence exécute un LLM pour le compte de l’utilisateur (l’agent first-party d’Apple) et route les appels de capacité vers les types AppIntent de votre app. Votre app n’exécute pas le modèle. Vous déclarez des actions typées via le framework App Intents, et la pile système d’Apple décide quand les invoquer en fonction d’une requête utilisateur, d’une recherche Spotlight, d’une entrée Siri ou d’une orchestration via Shortcuts. Détaillé dans App Intents Are Apple’s New API to Your App.4
MCP. Un hôte externe (Claude Desktop, Claude Code, Cursor, ChatGPT) exécute le modèle choisi par le développeur. Votre app expose un serveur que le modèle de l’hôte peut appeler. Le modèle s’exécute là où l’hôte l’exécute ; les appels d’outils transitent par un transport JSON-RPC. Détaillé dans Two Agent Ecosystems, One Shopping List et la synthèse de la question du routage dans App Intents vs MCP.5
La décision de routage se résume à qui est l’agent.
┌──────────────────────────────────┐
│ Who is the language model? │
└────┬─────────────┬─────────────┬──┘
│ │ │
┌────────┴────┐ ┌──────┴──────┐ ┌────┴──────┐
│ Your app's │ │ Apple │ │ External │
│ own use of │ │ Intelligence│ │ host's │
│ LLM │ │ agent │ │ agent │
└──────┬──────┘ └──────┬──────┘ └────┬──────┘
│ │ │
▼ ▼ ▼
Foundation Models App Intents MCP
+ Tool protocol + AppEntity + tools/list
(on-device, your (system runs (host runs
app runs model) the model) the model)
Une app de méditation qui résume la semaine de l’utilisateur utilise Foundation Models parce que l’app elle-même veut appeler le modèle et présenter un résultat à l’intérieur de l’app. La capacité « enregistrer une session de 5 minutes » de la même app utilise App Intents pour que Siri puisse l’invoquer. La capacité « montre-moi mes dernières entrées de journal de méditation » de la même app, utilisée par une session Claude Code, passe par MCP. Trois exécutants différents, trois obligations différentes, une seule couche de domaine partagée en dessous.
Budgets d’inférence : ce que le framework attend de vous
Exécuter un LLM on-device n’est pas gratuit. Apple silicon gère l’inférence, mais le modèle a toujours une fenêtre de contexte, un budget de tokens et une latence de bout en bout qui dépend de l’appareil. Trois contraintes façonnent votre conception avec le framework :6
La disponibilité dépend de l’appareil. Tous les appareils iOS 26 n’ont pas Apple Intelligence. Les iPhone plus anciens, les appareils verrouillés et les appareils sur lesquels l’utilisateur a désactivé Apple Intelligence retournent un état non disponible depuis SystemLanguageModel.default.availability. Un code qui appelle LanguageModelSession sans vérifier la disponibilité fait remonter une erreur de génération à l’exécution ; le bon pattern consiste à brancher l’UI sur l’état de disponibilité en amont et à proposer un parcours sans LLM quand l’état n’est pas disponible. Traitez le modèle comme un feature flag, pas comme une garantie.
La latence n’est pas négligeable. La latence du premier token sur l’iPhone 16 Pro est utilisable pour des interactions intra-app ; les générations plus longues et les chaînes d’appels d’outils ne sont pas instantanées. Les patterns d’UI qui fonctionnent pour le streaming de LLM cloud fonctionnent ici aussi ; ne bloquez pas le main thread, affichez une sortie progressive et concevez pour le cas où l’utilisateur quitte la vue en cours de génération.
Les fenêtres de contexte sont plus petites que dans le cloud. Le modèle on-device a une fenêtre de contexte plus petite que les modèles cloud de classe GPT-4. Les longs documents nécessitent un résumé ou un découpage en morceaux. L’historique de conversation long doit être tronqué. Les sorties d’outils qui retournent de gros payloads structurés devraient retourner une référence (un identifiant, une clé) que le tour suivant peut récupérer à la demande, et non l’intégralité du payload en ligne.
L’ensemble des contraintes est similaire à celui d’un runtime edge bas de gamme, pas à celui d’un modèle cloud frontier. Les commodités du framework rendent l’expérience plus agréable ; les limites physiques sous-jacentes ne bougent pas.
Quand recourir à Foundation Models
Les meilleurs cas d’usage du framework sont ceux où la génération on-device et sans friction est le produit lui-même :
Reformatage et réécriture. Transformer une note libre de l’utilisateur en entrée structurée, peaufiner un brouillon de message, résumer une transcription capturée. La tolérance à la latence est modérée ; la sensibilité des données est élevée ; l’inférence cloud est superflue.
Synthèse locale sur des données privées. Une app de fitness qui transforme l’historique d’entraînement de l’utilisateur en résumé « cette semaine ». Une app de finance qui explique le pattern de dépenses d’un utilisateur. Une app de journal qui fait émerger des thèmes sur un trimestre d’entrées. Les données ne devraient pas quitter l’appareil ; la réponse devrait apparaître dans l’app ; le prompt est borné.
Appels d’outils légers pour l’automatisation interne à l’app. Une app qui permet à l’utilisateur de dire « montre-moi le journal de méditation de mardi » et qui utilise un outil pour récupérer les enregistrements sous-jacents, puis met en forme la réponse. L’agent est l’app, l’outil est la couche de données de l’app, le modèle est local.
Génération conforme à un type. Partout où l’app aurait sinon écrit à la main un parser JSON ou un template de chaîne, @Generable plus @Guide constituent une surface plus durable.
Quand ne pas recourir à Foundation Models
Le framework n’est pas la bonne réponse pour plusieurs cas courants :
Tout ce que l’utilisateur pourrait demander à Siri. « Enregistre 250 ml d’eau », « Démarre une méditation de 5 minutes », « Ajoute des bananes à ma liste » relèvent d’App Intents. Apple Intelligence est l’exécutant ; votre app est la destination. Foundation Models concerne la génération à l’intérieur de l’app, pas les actions routées par Siri. Si vous construisez la même capacité deux fois (App Intent + LanguageModelSession avec un outil), c’est l’App Intent qui gagne parce que l’utilisateur invoque Siri, pas votre écran intra-app.
Tout ce qu’un agent LLM externe devrait piloter. Une session Claude Code qui accède au domaine de votre app passe par MCP. L’app n’exécute pas le LLM ; c’est l’hôte qui le fait ; le modèle vit là où l’hôte l’a placé. Foundation Models ne peut pas servir des agents externes.
Raisonnement intensif sur de gros documents. Le modèle on-device est petit. Un contrat de 200 pages, un long contexte de base de code ou un raisonnement multi-images sur de nombreuses photos relèvent de l’inférence cloud (la vôtre ou celle d’un fournisseur), où la fenêtre de contexte et le nombre de paramètres correspondent à la charge de travail. Les tâches qui dépassent l’enveloppe du framework produisent des erreurs concrètes : fenêtre de contexte dépassée, violations de garde-fous, locales non supportées. Faites remonter ces erreurs délibérément plutôt que de concevoir des flux qui dépendent du fait que le modèle gère du travail hors enveloppe.
Workflows multi-appareils et multi-utilisateurs. Le modèle on-device n’a accès qu’à ce que l’app passe dans la session. La synchronisation multi-appareils (état du minuteur de la Watch vers l’iPhone), la collaboration multi-utilisateurs (listes partagées, documents partagés) et tout flux qui bénéficie d’une coordination côté serveur nécessitent un serveur. Le modèle n’est pas une primitive réseau.
Ce que je construirais différemment dans ma stack
Le framework récompense un choix d’architecture précis qu’il est facile de manquer au premier passage. Les capacités que l’utilisateur invoque via l’UI de l’app et que le LLM devrait consommer comme outils, et non comme des chemins de prose dupliqués.
Une app de méditation pourrait ajouter un panneau « bilan hebdomadaire » résumé par LLM. La construction naïve consiste en un seul prompt : « Voici les entrées de l’utilisateur cette semaine, écris un paragraphe ». La meilleure construction définit un outil WeeklyEntries que le modèle peut appeler quand il a besoin de savoir ce qui s’est passé dans la semaine, plus une sortie structurée WeeklySummary via @Generable. La première construction est fragile (le modèle doit ingérer une longue liste d’entrées à chaque appel), coûteuse en tokens et produit de la prose non structurée. La seconde est durable (l’appel d’outil sépare « ce qui s’est passé » de « comment en parler »), peu coûteuse (le modèle ne récupère que ce dont il a besoin) et structurée (le résultat est une valeur Swift typée).
Le pattern se compose proprement avec App Intents et MCP. La même requête WeeklyEntries sert aussi de corps à un résolveur de paramètres AppIntent et à un gestionnaire d’outils MCP. Une seule fonction Swift ; trois surfaces. Le modèle appelle la même fonction que l’utilisateur appelle.
L’autre décision d’architecture : les descriptions d’outils font partie du prompt. Le modèle lit Tool.description pour décider s’il doit appeler et quand. Traitez la description comme une docstring que vous attendez réellement qu’un futur contributeur lise ; le modèle est ce futur contributeur.
Ce que ce pattern signifie pour la stack Apple sur iOS 26+
Trois enseignements.
-
Le LLM on-device est une fonctionnalité d’exécution, pas un backend. Traitez-le comme un framework système avec une fenêtre de contexte et un budget d’inférence on-device, pas comme un service distant. Les décisions d’architecture portent sur la disponibilité, la latence, la discipline de fenêtre de contexte et la sortie structurée.
-
Le protocole Tool est la surface. Sans outils, le modèle est un endpoint de complétion de chat sans connexion à votre domaine. Avec des outils, le modèle devient une couche de requête structurée sur les données de votre app.
-
La règle de routage entre Foundation Models, App Intents et MCP est « qui exécute le modèle ». La génération intra-app va à Foundation Models. Les capacités routées par Apple Intelligence vont à App Intents. Les capacités d’agents externes vont à MCP. La même fonction de domaine Swift peut être appelée par les trois surfaces.
L’ensemble du cluster Apple Ecosystem : App Intents typés pour Apple Intelligence ; serveurs MCP pour les agents inter-LLM ; la question du routage entre les deux ; les Live Activities pour la machine à états du Lock Screen ; les patterns Liquid Glass pour la couche visuelle ; le shipping multi-plateformes pour la portée multi-appareils. Le hub se trouve dans la Apple Ecosystem Series. Pour un contexte plus large sur iOS avec des agents IA, consultez le iOS Agent Development guide.
FAQ
Qu’est-ce que le framework Foundation Models dans iOS 26 ?
Foundation Models est le framework d’Apple pour accéder au modèle de langage on-device livré avec les appareils éligibles à Apple Intelligence sous iOS 26 (et iPadOS 26, macOS 26, visionOS 26). Le framework expose SystemLanguageModel, LanguageModelSession et le protocole Tool afin que les apps puissent exécuter des appels LLM typés et on-device sans accès réseau.
Comment fonctionne le protocole Tool ?
Un Tool est un type Swift qui déclare une struct Arguments (annotée avec @Generable et @Guide), une méthode asynchrone call(arguments:) et un nom + une description que le modèle utilise pour décider quand appeler. Les outils sont liés à une LanguageModelSession à la construction. Quand le modèle décide qu’il a besoin d’un outil, le framework décode les arguments, exécute l’appel et réinjecte la sortie typée dans la session.
Quelle est la différence entre Foundation Models, App Intents et MCP ?
Foundation Models permet à votre app d’exécuter le LLM on-device pour de la génération intra-app. App Intents permet à Apple Intelligence (l’agent système) d’appeler les capacités typées de votre app. MCP permet à des hôtes LLM externes (Claude, ChatGPT, etc.) d’appeler les outils typés de votre app via un transport JSON-RPC. Les trois protocoles diffèrent par qui exécute le modèle. La même fonction de domaine Swift peut servir les trois.
Foundation Models peut-il appeler des outils MCP ?
Non. LanguageModelSession.tools accepte des conformeurs au protocole Tool d’Apple, pas des serveurs d’outils MCP. Pour faire le pont entre les deux, vous écririez un Tool Foundation Models dont la méthode call invoque un client MCP. Apple n’a pas livré d’adaptateur intégré ; le pont serait du code côté app.
Le modèle on-device est-il assez bon pour la production ?
Pour les cas d’usage auxquels le framework est destiné (reformatage, synthèse, génération structurée sur des données locales, appels d’outils légers), oui. Pour du raisonnement frontier sur de grands contextes, de la compréhension multimodale à grande échelle ou du raisonnement inter-documents, non. Le modèle on-device est un modèle de 3 milliards de paramètres avec une fenêtre de contexte plus petite que les LLMs cloud ; choisissez des charges de travail qui rentrent dans l’enveloppe.
Références
-
Apple Developer, “Apple Intelligence and machine learning” et la session WWDC 2025 “Meet the Foundation Models framework”. Le chiffre phare du framework (un modèle de langage on-device de 3 milliards de paramètres) provient de l’annonce d’Apple à la WWDC 2025. ↩
-
Apple Developer, “FoundationModels framework”.
SystemLanguageModel,LanguageModelSession,Tool,ToolOutputet les types associés. ↩ -
Apple Developer, “Generating Swift data structures with guided generation” et la référence des macros
@Generable/@Guide. Génération contrainte par le type comme capacité de premier ordre via le décodage contraint. ↩ -
Analyse de l’auteur dans App Intents Are Apple’s New API to Your App, 28 avril 2026. ↩
-
Analyse de l’auteur dans Two Agent Ecosystems, One Shopping List, 29 avril 2026, et App Intents vs MCP: The Routing Question, 30 avril 2026. ↩
-
Apple Developer, “Adopting Apple Intelligence in your app” et “SystemLanguageModel” pour les patterns d’
availability. Les sessions WWDC 2025 d’Apple couvrent le chemin d’inférence on-device sur Apple silicon et les contraintes de disponibilité par appareil. ↩