Foundation Models 端侧LLM:Tool 协议
Apple 在 WWDC 2025 上推出的端侧LLM契约引出了一个直接的路由问题:什么时候该用 LanguageModelSession,什么时候该用 AppIntent,什么时候该用 MCP,又什么时候三者都不该用。
iOS 26 在每台具备 Apple Intelligence 能力的设备上都搭载了一个 30 亿参数的语言模型。1 Apple 称这套框架为 Foundation Models。该框架是本地的。推理针对 Apple silicon 优化并在端侧运行;网络不在调用路径上。模型驻留于 SystemLanguageModel.default,您的应用获取一个 LanguageModelSession,而让该会话执行有用工作的类型化接口就是 Tool 协议。
Tool 协议是对应用开发者最重要的部分。没有它,端侧LLM不过是一个聊天补全端点,与您应用的数据、用户的数据或系统的其余部分都没有联系。有了它,模型就能调用类型化的 Swift 函数、获取类型化的结果,并在下一轮对话中基于答案进行推理。工具增强的端侧生成才是这套框架的真正能力。聊天界面只是演示。
TL;DR
- Foundation Models 在
SystemLanguageModel.default为每台符合 Apple Intelligence 条件的设备提供了一个 30 亿参数的LLM。模型是本地的;推理针对 Apple silicon 优化并在端侧运行;网络不在调用路径上。 - Tool 协议是模型与您应用之间的契约。一个工具声明类型化的
Arguments,返回类型化的Output,并在构造时绑定到LanguageModelSession。 Generable和Guide注解让模型能直接产出类型化的 Swift 值,而不仅仅是字符串。解码器是框架的一部分,不属于您的代码。- Foundation Models、App Intents 和 MCP 之间的路由规则是谁运行模型以及在哪里运行。Foundation Models = 您的应用在端侧运行模型。App Intents = Apple Intelligence 在端侧运行模型并路由到您的应用。MCP = 外部宿主在它选定的任何位置运行模型,并通过工具服务器接入您的应用。
这个框架到底提供了什么
三个原语支撑起整个框架:模型、会话和工具。2
SystemLanguageModel。 端侧基础模型的引用。默认实例绑定到用户的设备,在符合 Apple Intelligence 条件的硬件上可用,并暴露能力检查接口供应用在运行时读取以判断模型是否可用。框架支持通过 SystemLanguageModel(useCase:guardrails:)、自定义适配器和 GenerationOptions 进行配置,但您不能像在 OpenAI 或 Anthropic 上那样任意挑选云端模型 ID;Apple 随每个 OS 版本发布并更新端侧模型,框架交给您的就是当前安装的那个版本。
LanguageModelSession。 一个有状态对象,跨调用保留对话状态。会话在构造时接收系统提示词,随时间累积用户/助手轮次,并暴露用于生成响应的异步方法。会话创建轻量且可丢弃;每个任务创建一个,而非每个应用创建一个。冥想计时器为”总结我过去 7 天的练习”创建一个会话;菜谱应用为”把这道菜从四人份改成两人份”创建另一个会话。
Tool(协议)。 一个 Swift 协议,声明一个 name、一个 description、一个 Arguments 类型、一个 Output 类型和一个异步 call(arguments:) 函数。工具在构造时绑定到会话(LanguageModelSession(tools: [...], instructions: ...))。当模型判断需要某个工具时,它会发出一次结构化调用;框架解码参数、运行工具、编码结果,并在下一轮把结果送回会话。模型看不到 Swift;框架完成所有的编解码工作。
该协议的完整要求:name: String、description: String、一个遵循 ConvertibleFromGeneratedContent 的关联 Arguments 类型、一个遵循 PromptRepresentable 的关联 Output 类型,以及一个异步 call(arguments:) 方法。Arguments 结构体上的 @Generable 宏会自动生成 ConvertibleFromGeneratedContent 一致性;对于 Output,String 和 GeneratedContent 已经具备相应的一致性。Apple 文档中的示例返回 String 或 [String]。
Tool 协议的精简形态:
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 -> String {
let entries = try store.entries(
from: ISO8601DateFormatter().date(from: arguments.startDate) ?? .now,
to: ISO8601DateFormatter().date(from: arguments.endDate) ?? .now
)
let totalMl = entries.reduce(0) { $0 + $1.amountMl }
return "Found \(entries.count) entries totalling \(totalMl)ml."
}
}
模型看到的是一个工具描述和一个生成模式的参数形状。Swift 代码看到的是类型化输入和类型化输出。解码/编码边界是 Apple 拥有的部分。工具输出可以是 String 或 GeneratedContent 对象;上面的示例返回 String,因为下一轮的模型推理才是消费方。
Generable 与 Guide:无需解析器的类型化输出
让工具参数类型化的同一套注解系统也允许模型直接产出类型化的 Swift 值。3 一个 @Generable 结构体声明它的形态;框架会约束模型的输出与之匹配。
@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
)
调用返回一个 Response<PracticeSummary>,其 content 是类型化的 PracticeSummary。您的代码里没有 JSON 解析、没有”headline:”的字符串匹配、当模型返回畸形对象时也没有兜底逻辑。框架使用约束采样,让模型逐 token 的输出在结构上与模式对齐,因此结构上无效的输出不会越过边界。上面的会话没有传入工具,因为类型化输出和工具调用是相互独立的能力;一个会话可以为响应形态使用 @Generable,可以为信息接地使用工具,可以两者都用,也可以两者都不用。
Swift 类型化接口正是这套框架与云端LLM SDK 的差异所在。云端 SDK(OpenAI Structured Outputs、Anthropic 工具使用等)也支持约束采样,但开发者收到的类型化值是一个根据模式校验的 JSON 对象,再作为单独一步解码成 Codable 的 Swift 类型。Foundation Models 把这些步骤合并:@Generable 宏和框架的解码器直接返回一个类型化的 Swift 值,而每个字段的 @Guide 注解将意图带入生成约束。输出之所以是类型化的,是因为生成本身就是针对 Swift 模式进行的,而不是针对开发者在 Swift 中重建的 JSON 规范。
@Guide 注解是一种向模型传达逐字段意图而无需写入提示词的方式。生成的描述会成为生成约束的一部分。字段级别的指引让提示词保持简洁,让模式贴近数据。
路由问题的三种回答
Apple 现在提供了三种协议接口,让应用可以将自己的领域暴露给语言模型。它们路由到不同的运行者。
Foundation Models(LanguageModelSession)。 您的应用加载端侧模型并运行推理。会话能调用的工具就是您应用代码定义的工具。模型从不离开设备。用户不会通过 Siri 调用它;调用方是您应用的代码。这种用法发生在您应用内部:用LLM总结一周练习的冥想应用,把菜谱改成更少份数的菜谱应用,把”我午饭时喝了一杯”转成结构化条目的饮水追踪应用。
App Intents。 Apple Intelligence 代表用户运行一个LLM(Apple 的第一方代理),并把能力调用路由到您应用的 AppIntent 类型。您的应用不运行模型。您通过 App Intents 框架声明类型化动作,由 Apple 的系统栈根据用户请求、Spotlight 查询、Siri 输入或 Shortcuts 编排来决定何时调用它们。详见 App Intents 是 Apple 接入您应用的新 API。4
MCP。 一个外部宿主(Claude Desktop、Claude Code、Cursor、ChatGPT)运行开发者所选的任何模型。您的应用暴露一个服务器,宿主的模型可以调用它。模型在宿主选择运行的位置上运行;工具调用通过一条 JSON-RPC 传输跨越边界。详见 两个代理生态系统,一份购物清单 以及在 App Intents vs MCP 中的路由问题综述。5
路由决策归根结底是谁是代理。
┌──────────────────────────────────┐
│ 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)
总结用户一周练习的冥想应用使用 Foundation Models,因为应用本身想调用模型并在应用内呈现结果。同一应用的”记录一段 5 分钟会话”能力使用 App Intents,以便 Siri 调用。同一应用被 Claude Code 会话使用的”显示我最近的冥想日志条目”能力则使用 MCP。三种不同的运行者、三组不同的契约、底层共享同一个领域层。
推理预算:框架对您的要求
在端侧运行LLM不是免费的。Apple silicon 处理推理,但模型仍然有上下文窗口、token 预算和取决于设备的实际延迟。三个约束塑造您的设计方式:6
可用性按设备而定。 并非每台 iOS 26 设备都具备 Apple Intelligence。较旧的 iPhone、受限设备以及用户已禁用 Apple Intelligence 的设备会从 SystemLanguageModel.default.availability 返回不可用状态。未先检查可用性就调用 LanguageModelSession 的代码会在运行时抛出生成错误;正确的做法是提前根据可用性状态对 UI 进行分支处理,并在状态不可用时呈现一条不依赖LLM的路径。把模型当作功能开关,而不是默认保证。
延迟并非微不足道。 在 iPhone 16 Pro 硬件上,根据我们在 Return 上的测试,首 token 延迟在应用内交互中是可接受的;更长的生成和工具调用链则不会瞬时返回。适用于云端LLM流式输出的 UI 模式在这里同样适用;不要阻塞主线程,要做渐进式输出,要为用户在生成中途离开界面的情形做好设计。
上下文窗口比云端更小。 端侧模型的上下文窗口比 GPT-4 级别的云端模型更小。长文档需要总结或分块。冗长的对话历史需要修剪。返回大型结构化负载的工具输出应当返回一个引用(一个 ID、一个键),让下一轮按需重新获取,而不是把整个负载内联返回。
约束集合更接近为低端边缘运行时设计,而非为前沿云端模型设计。框架的便利性让事情更愉悦;底层的物理极限不会因此移动。
何时该选择 Foundation Models
框架最契合的场景是端侧、低摩擦生成本身就是产品的地方:
重新格式化与改写。 把用户的自由形式笔记转成结构化条目,润色一封草稿消息,总结一段捕获的转录。延迟容忍度中等;数据敏感性高;云端推理是杀鸡用牛刀。
对私有数据的本地综合。 健身应用把用户的训练历史变成”本周”摘要。理财应用解释用户的消费模式。日记应用挖掘一个季度条目中的主题。数据不应离开设备;答案应在应用内呈现;提示词是有界的。
应用内自动化的轻量工具调用。 应用允许用户说”显示周二的冥想日志”,并使用工具去取出底层记录,再格式化答案。代理是应用,工具是应用自己的数据层,模型是本地的。
符合类型的生成。 凡是应用本来需要手写 JSON 解析器或字符串模板的地方,@Generable 加 @Guide 都是更耐用的接口。
何时不该选择 Foundation Models
在以下几种常见情形下,框架并不是正确答案:
任何用户可能问 Siri 的事情。 “记录 250 毫升饮水”、“开始 5 分钟冥想”、“把香蕉加到我的清单”属于 App Intents。Apple Intelligence 是运行者;您的应用是目的地。Foundation Models 是用于应用内部的生成,而不是 Siri 路由的动作。如果同一能力被构建两次(App Intent + 带工具的 LanguageModelSession),App Intent 会胜出,因为用户调用的是 Siri,不是您的应用内界面。
任何应该由外部LLM代理驱动的事情。 一个 Claude Code 会话伸入您应用领域的场景应当通过 MCP。应用不运行LLM;宿主才运行;模型驻留在宿主放置它的位置。Foundation Models 无法服务外部代理。
对大型文档的繁重推理。 端侧模型很小。一份 200 页的合同、一段长代码库上下文,或对许多照片的多图推理属于云端推理(您自己的或厂商的),那里的上下文窗口和参数量与负载相匹配。超出框架边界的任务会产出具体错误:超出上下文窗口、防护栏违规、不支持的语言环境。要刻意暴露这些错误,而不是设计依赖模型处理边界外工作的流程。
跨设备和跨用户工作流。 端侧模型只能访问应用传入会话的内容。跨设备同步(计时器状态从 Watch 同步到 iPhone)、跨用户协作(共享清单、共享文档),以及任何受益于服务端协调的流程都需要服务器。模型不是网络原语。
我会在自己的技术栈中做哪些不同的设计
框架奖励一种特定的架构选择,而这个选择在第一遍构建时很容易做错。用户通过应用 UI调用的能力,应当被LLM作为工具消费,而不是作为重复的散文路径。
一个冥想应用可能添加一个由LLM总结的”周回顾”面板。最朴素的实现是一条提示词:”这是用户本周的条目,写一段话。”更好的实现定义一个 WeeklyEntries 工具,让模型在需要知道一周内容时调用,再加上通过 @Generable 输出的结构化 WeeklySummary。第一种实现脆弱(模型必须在每次调用时摄入一长串条目)、token 成本高,且产出非结构化的散文。第二种实现耐用(工具调用把”发生了什么”和”如何叙述”分离开)、低成本(模型只取它所需)、并且结构化(结果是一个类型化的 Swift 值)。
这个模式与 App Intents 和 MCP 干净地组合。同一个 WeeklyEntries 查询也是某个 AppIntent 参数解析器和一个 MCP 工具处理器的主体。一个 Swift 函数;三个接口。模型调用的与用户调用的是同一个函数。
另一项架构决策:工具描述是提示词的一部分。模型读取 Tool.description 来决定是否调用以及何时调用。把描述当作一份您期望未来贡献者会读到的文档字符串来对待;模型就是那个未来贡献者。
这个模式对 iOS 26+ 上的 Apple 技术栈意味着什么
三点要点。
-
端侧LLM是运行时特性,不是后端。 把它当作一个具有上下文窗口和端侧推理预算的系统框架来对待,而不是一个远程服务。架构决策包括可用性、延迟、上下文窗口纪律和结构化输出。
-
Tool 协议是接口。 没有工具,模型不过是一个与您领域无关的聊天补全端点。有了工具,模型就成为您应用数据之上的一层结构化查询层。
-
Foundation Models、App Intents 和 MCP 之间的路由规则是”谁运行模型”。 应用内部生成走 Foundation Models。Apple Intelligence 路由的能力走 App Intents。外部代理能力走 MCP。同一个 Swift 领域函数可以被三种接口共同调用。
三篇姊妹文更深入地探索 Foundation Models 框架:Foundation Models 用例 讲解工作负载契合度决策,自定义适配器 讲解在应用数据上微调端侧模型,代理式工作流 讲解应用内 vs 工具化LLM的分工。
完整的 Apple 生态集群:用于 Apple Intelligence 的类型化 App Intents;用于跨LLM代理的 MCP 服务器;两者之间的路由问题;用于锁屏状态机的 Live Activities;用于视觉层的 Liquid Glass 模式;用于跨设备覆盖的多平台发布。中心枢纽位于 Apple Ecosystem 系列。如需更广泛的 iOS 与 AI 代理上下文,请参阅 iOS Agent Development 指南。
常见问题
iOS 26 中的 Foundation Models 框架是什么?
Foundation Models 是 Apple 的框架,用于访问随 Apple Intelligence 合规设备在 iOS 26(以及 iPadOS 26、macOS 26、visionOS 26)一同发布的端侧语言模型。该框架暴露 SystemLanguageModel、LanguageModelSession 和 Tool 协议,使应用能够在无网络访问的情况下进行类型化的端侧LLM调用。
Tool 协议是如何工作的?
Tool 是一个 Swift 类型,声明一个 Arguments 结构体(用 @Generable 和 @Guide 注解)、一个异步 call(arguments:) 方法,以及一个供模型决定何时调用的名称和描述。工具在构造时绑定到 LanguageModelSession。当模型决定它需要某个工具时,框架解码参数、运行调用,并把类型化输出送回会话。
Foundation Models、App Intents 和 MCP 之间有什么区别?
Foundation Models 让您的应用在端侧运行LLM以进行应用内生成。App Intents 让 Apple Intelligence(系统代理)调用您应用的类型化能力。MCP 让外部LLM宿主(Claude、ChatGPT 等)通过 JSON-RPC 传输调用您应用的类型化工具。三种协议的不同在于谁运行模型。同一个 Swift 领域函数可以服务全部三种。
Foundation Models 能调用 MCP 工具吗?
不能。LanguageModelSession.tools 接受遵循 Apple 的 Tool 协议的实现,而不是 MCP 工具服务器。要想让两者打通,您需要写一个 Foundation Models 的 Tool,它的 call 方法去调用一个 MCP 客户端。Apple 没有提供内置适配器;这个桥需要在应用侧编写代码。
端侧模型对生产环境足够好吗?
对于该框架所设计的用例(重格式化、总结、对本地数据的结构化生成、轻量工具调用),是的。对于在大上下文上的前沿推理、规模化的多模态理解或跨文档推理,不是。端侧模型是一个 30 亿参数的模型,上下文窗口比云端LLM更小;选择适配它范围的工作负载。
参考资料
-
Apple Developer,“Apple Intelligence and machine learning” 以及 WWDC 2025 会议 “Meet the Foundation Models framework”。该框架的标志性数字(30 亿参数的端侧语言模型)来自 Apple 的 WWDC 2025 公告。 ↩
-
Apple Developer,“FoundationModels framework”。
SystemLanguageModel、LanguageModelSession、Tool、GeneratedContent及相关支撑类型。 ↩ -
Apple Developer,“Generating Swift data structures with guided generation” 以及
@Generable/@Guide宏参考。通过约束采样将类型受限生成作为一等公民能力。 ↩ -
作者在 App Intents 是 Apple 接入您应用的新 API 中的分析,2026 年 4 月 28 日。 ↩
-
作者在 两个代理生态系统,一份购物清单 中的分析(2026 年 4 月 29 日),以及 App Intents vs MCP:路由问题(2026 年 4 月 30 日)。 ↩
-
Apple Developer,“Adopting Apple Intelligence in your app” 和 “SystemLanguageModel” 中关于
availability模式的内容。Apple 的 WWDC 2025 会议涵盖了 Apple silicon 上的端侧推理路径以及按设备而定的可用性约束。 ↩