三个界面:人类、Apple Intelligence、智能体
在iOS 26+上,iOS应用中每一个有意义的能力如今最多可以从三个界面被调用。同一个记录一杯水的Swift函数,既可以由用户点击按钮触发,也可以由Apple Intelligence路由Siri请求触发,还可以由外部智能体(Claude Code、Cursor、ChatGPT)调用MCP工具来触发。三种不同的调用者,三种不同的义务,三种不同的渲染界面。能力相同;界面不同。
很多iOS架构错误,都源于针对一个界面进行设计,然后强行把这个能力套到其他界面上。UI流程渗入Siri响应;对开发者而言正确的智能体工具,对终端用户却成了隐患;端侧LLM功能假定具备云端级别的上下文。该系列文章一直在分别探讨这些界面。本文是综合篇:三个界面、它们的差异、路由规则,以及一个应用的领域层应该是什么样子,才能在不损害任何一个界面的前提下服务于全部三个界面。
思维模型如下:挑选一个领域能力。问哪些界面应该能够调用它。问哪些界面能够调用它。问每个界面需要从该能力获得什么,以及该能力反过来欠界面什么。答案塑造了架构。
TL;DR
- 三个界面:人类(SwiftUI视图、点击、手势、屏幕)、Apple Intelligence(App Intents、Siri、Shortcuts、Spotlight)、智能体(MCP服务器、外部LLM宿主)。
- 每个界面有不同的义务:信任态势、延迟预算、渲染位置、持久化语义、错误处理、无障碍要求。
- 正确的架构是位于这些界面之下的领域层。每个界面都是同一组Swift函数之上的薄适配器;函数接受一个类型化的
Caller参数,以便在不了解界面协议细节的前提下,就跨界面规则(限流、审计、确认)进行分支处理。 - 并非所有能力都需要服务于全部三个界面。决定哪个界面正是设计层面的判断。把能力对不应该拥有它的界面隐藏起来,与把它暴露给应该拥有它的界面同样,都是产品决策。
界面一:人类
人类界面就是屏幕。用户看着应用,点击、滚动、拖拽、滑动、键入。框架是SwiftUI(或UIKit,或对某些工作负载在visionOS上是RealityKit)。渲染发生在用户的设备上、应用进程中,依据用户选择的配色方案、动态字号和无障碍设置。1
人类界面对一项能力的需求:
- 可见的承担物。一个按钮、一个列表行、一个滑动手势、一个上下文菜单。该能力必须能够通过应用的导航被发现,并且与UI的其他部分风格一致。
- 实时反馈。每次交互都需要立即可见的响应。一个触发长时间运行操作的按钮必须显示进度指示器、启用/禁用状态、动画。
- 无障碍。VoiceOver标签、动态字号支持、对比度、运动控制替代方案。人类界面是无障碍要求最严苛的界面,因为用户直接与渲染交互。
- 错误可见性。错误会出现在用户视图中。保存失败显示警告;网络超时显示重试;权限被拒绝显示设置链接。
人类界面反过来欠该能力的:
- 明确无歧义的用户意图。用户点击了某个特定按钮;能力清楚地知道请求的是什么。中间没有推理层。
- 紧凑的延迟预算。一次点击如果用了几百毫秒以上才出现可见响应,就会让人感觉坏掉了。该能力要么足够快,要么需要被设计成立即显示进度。
- 不存在外部权威。用户在应用里;最宽泛意义上,用户就是智能体(人类是驱动操作的人)。没有第三方LLM,没有系统智能体,只有用户的双手。
人类界面是这三者中存在时间最长的。自iOS 7以来平台积累的所有iOS框架、设计模式和无障碍规则,都是为这个界面服务的。另外两个界面太新,模式还在沉淀。
界面二:Apple Intelligence
Apple Intelligence界面就是系统智能体。Siri、Shortcuts、Spotlight、系统建议栈。用户说话、在Spotlight中输入,或在Shortcuts中链接一个动作;系统通过App Intents框架路由请求,找到匹配的AppIntent,解析参数,运行该intent的perform()体。框架是App Intents。2
Apple Intelligence界面对一项能力的需求:
- 类型化的schema。
AppIntent类型声明@Parameter属性;AppEntity类型为系统可以谈论的事物提供持久身份;AppEnum类型命名封闭的选项集合。系统在安装时读取该schema。 - 跨应用进程存活的身份。用户昨天通过Siri记录的一项喝水条目,今天应该能够通过Siri被引用。
AppEntity模型让系统获得一种跨会话谈论对象的稳定方式。 - 静默的错误处理。错误不会出现在用户视图中;它们出现在Siri响应、Shortcuts输出或Spotlight结果里。系统期望的错误格式是结构化的(Apple的
AppIntentError加上符合LocalizedError的throws),不是视觉化的。 - 重试下的幂等性。系统可以在Shortcut链中或部分失败后重新调用一个intent。会修改状态的能力需要在重复调用下保持安全,或者明确呈现”已完成”的语义。
Apple Intelligence界面反过来欠该能力的:
- 用户的真实身份。系统知道用户是谁,已通过OS对其进行身份验证,并在其上下文中运行该intent。该能力不需要在OS提供的内容之外再去验证身份。
- 系统级渲染。intent返回的结果会被系统格式化到适当的外壳中(锁屏横幅、Siri响应卡片、Shortcuts输出)。应用不控制响应的呈现方式。
- 无需你的代码运行的可发现性。App Intents可以在你的应用未运行时被调用。系统读取schema,主动呈现该能力。
信任态势:Apple Intelligence是Apple的第一方智能体。用户没有配置它;系统配置了它。用户信任OS;OS信任你的应用通过审核所交付的App Intents schema。信任链是OS → 应用。App Intents确实支持requestConfirmation(...)和前台模式确认,因此需要”你确定吗?”的能力在技术上可以放在那里;真正的判断不是平台限制,而是产品判断:高风险确认是该放在Siri对话回合内,还是放在应用自己的屏幕上。任何不可逆的操作(账号删除、破坏性批量编辑、支付)通常放在人类界面更安全,即便App Intents可以请求确认。3
界面三:智能体
智能体界面是所有其他想要操作应用领域的LLM驱动系统。Claude Desktop、Claude Code、Cursor、ChatGPT桌面应用、Codex CLI、自定义智能体框架。框架是Model Context Protocol:一个MCP服务器通过JSON-RPC的tools/call方法暴露应用的领域;宿主LLM在会话开始时发现工具,并按名称用JSON负载调用它们。4
智能体界面对一项能力的需求:
- 一份JSON-RPC契约。工具名称、描述、
inputSchema、可选的outputSchema。智能体读取描述以决定是否调用;它遵循schema来格式化参数。 - 一份有用的描述。模型基于工具的描述来决定何时使用该工具。把描述当作docstring来对待,你期望它被另一个开发者(模型)阅读。模糊的描述会导致工具选择错误。
- 两种形态的错误。工具执行错误以内容块加上
isError: true的形式返回到模型读取的工具结果中。协议级错误(请求格式错误、工具缺失、传输失败)以标准的JSON-RPCerror响应返回,由宿主处理。前者由工具作者负责;后者由协议负责。 - 无状态或显式有状态的语义。MCP在协议层是有状态的(会话生命周期、Streamable HTTP中的会话ID),但持久的领域身份是服务器端的责任,不是协议层的保证。如果同一个标识符在跨会话时应当意味着同一件事,那么必须由服务器来强制执行。
智能体界面反过来欠该能力的:
- 宿主的身份验证,而不是用户的。信任来自部署该MCP服务器的人。开发者本地的stdio:开发者自己的文件系统权限。可通过互联网访问的HTTP:服务器强制执行的任何身份验证。该能力必须假定身份声明就是服务器给它的那个。
- 可变的延迟容忍度。宿主可以等待比人类界面或Apple Intelligence界面更久。一次耗时三十秒的工具调用在智能体界面是可以接受的,在其他界面则不可接受。
- 没有渲染界面。结果是模型解释的文本或结构化数据。没有外壳,没有UI,没有系统格式化。
信任态势:MCP服务器是开发者关于谁可以调用它的契约。同一个服务器的两次部署(开发用的本地stdio,面向终端用户的互联网HTTP)有非常不同的信任态势,需要非常不同的防护机制。协议是相同的;部署才是架构。详见App Intents vs MCP: 路由问题和LLM住在你的应用里 vs 住在你的工具链里。5
三个界面分歧的六个维度
把三个界面拉进一张对比表,可以让架构决策变得具体:
| 维度 | 人类 | Apple Intelligence | 智能体 |
|---|---|---|---|
| 调用者身份 | 用户(应用内,由OS认证) | 用户(由OS解析的系统级) | 宿主的身份声明(由服务器强制执行) |
| 延迟预算 | 数百毫秒 | 数秒(Siri对话回合) | 数秒到数十秒 |
| 渲染 | 应用的SwiftUI视图 | 系统外壳(横幅、Siri卡片、Shortcuts) | 模型解释的内容块 |
| 可发现性 | 应用的导航 | 安装时读取的App Intent schema | 会话开始时返回的工具列表 |
| 持久化语义 | 应用管理的状态 | 跨会话的AppEntity身份 |
服务器管理;非协议层 |
| 错误格式 | 警告、横幅、视图状态 | AppIntentError + LocalizedError抛出 |
工具执行:内容 + isError;协议:JSON-RPC error |
分歧会复合。一个为人类界面设计的能力假定紧凑的延迟、丰富的渲染、应用管理的错误。强行把它套进Apple Intelligence会失去渲染控制权,并增加由OS中介的身份。强行把它套进智能体界面会完全失去渲染,并将信任边界转移给部署服务器的人。该能力需要被重塑,而不仅仅是重新包裹。
架构规则:界面之下的领域层
跨三个界面都能存活下来的模式是位于它们之下的领域层。领域层就是普通的Swift函数:类型化的输入、类型化的输出、不假设任何协议。每个界面都是领域之上的薄适配器。同一个logWater(amount:caller:)函数支撑了SwiftUI按钮、App Intent的perform()和MCP工具的处理程序。
下面是个示意(真正的生产代码会让WaterEntry遵循AppEntity以作为App Intent的返回值,把domain作为依赖注入而不是顶层引用,并在intent上添加必需的static var title):
// Domain layer (the actual capability)
func logWater(amount: Measurement<UnitVolume>, at: Date, caller: Caller) throws -> WaterEntry {
try guards.requireWritePermission(caller)
let entry = WaterEntry(amount: amount, timestamp: at)
try store.insert(entry)
return entry
}
// Adapter A: human surface (SwiftUI button)
Button("Log 250ml") {
Task {
let entry = try await domain.logWater(
amount: .init(value: 250, unit: .milliliters),
at: .now,
caller: .human
)
// Update view state, show confirmation animation, etc.
}
}
// Adapter B: Apple Intelligence surface (AppIntent)
struct LogWaterIntent: AppIntent {
static var title: LocalizedStringResource = "Log Water"
@Parameter(title: "Amount") var amount: Measurement<UnitVolume>
func perform() async throws -> some IntentResult & ReturnsValue<WaterEntry> {
let entry = try domain.logWater(amount: amount, at: .now, caller: .siri)
return .result(value: entry) // WaterEntry conforms to AppEntity
}
}
// Adapter C: agent surface (MCP tool handler)
let entry = try domain.logWater(
amount: .init(value: ml, unit: .milliliters),
at: .now,
caller: .mcp(host: hostName)
)
return .text("Logged \(entry.amount) at \(entry.timestamp)")
三个调用者。一个领域函数。领域函数接受一个Caller参数,这样它就可以按界面强制执行不同规则(限流、审计日志、确认要求),而不需要每个界面去重新实现这些规则。适配器很笨;领域很聪明。
这种形态推广了App Intents vs MCP中的双适配器模式;把人类界面作为第三类调用者加进来是顺理成章的扩展。在应用内使用的Foundation Models端侧LLM,坐落在人类界面上(用户调用了一个恰好会调用模型的应用内功能);运行时LLM不是第四个界面,而是执行已经属于人类界面的能力的一种方式。6
并非每个能力都需要服务于全部三个界面
平等暴露不是目标。不同的能力属于不同的界面。
通常需要要求前台人类在场的能力。照片拍摄、生物识别认证、敏感个人信息录入、支付确认、账号删除。人类必须看着屏幕、必须同意、必须认证。Apple Intelligence技术上可以把应用拉到前台并请求确认;智能体界面没有等同的在场保证。产品判断是这些能力应该作为前台UI运行,需要明确刻意的行动,而不是作为一次安静的Siri或后台工具调用。
应当存在于人类+Apple Intelligence界面的能力。大多数面向用户的操作。记录喝水、开始一次冥想、向列表添加一项、让我看看周二的条目。用户可能点击按钮,也可能说”嘿Siri”。两个界面都有效;两个都应该到达同一个领域函数。
应当存在于全部三个界面的能力。跨进程集成。一个在用户的iPhone和导入食谱的Claude Code会话之间共享的购物清单。人类界面承担日常使用;Apple Intelligence界面承担Siri/Spotlight覆盖;智能体界面承担由开发者或用户驱动的外部工作流。
只应当存在于智能体界面的能力。没有终端用户审核流程的开发者或管理员批量导入,与外部系统的集成,没有Siri或应用内表达的智能体编排工作流。在一次性回填期间从开发者的CSV批量导入500条历史条目。终端用户的文件导入往往有人类界面流程(Shortcuts可以传递文件;应用内的导入器可以分块显示进度);只属于智能体的情形是那种确实没有位置安放在另外两个界面中任何一个的工作流。
决策即设计。列出某个能力不服务的界面,与列出它服务的界面同样重要。
我会以何种不同方式构建
该系列的应用要么已经交付、要么希望自己曾经交付的两个模式。
让Caller成为领域层的一等类型。每个公开的领域函数都接受一个Caller参数。该类型编码了哪个界面发起了调用(.human、.siri、.mcp(host:))。领域逻辑根据它在确认提示、限流、审计日志、敏感操作门控之间分支。替代方案(每个界面重新实现规则)会漂移;集中化的版本保持一致。
把界面覆盖当作显式的清单。添加一项能力时,设计文档会列出该能力应当暴露给三个界面中的哪几个,以及哪些应当拒绝。拒绝清单不是默认值;它是经过深思熟虑的选择。已拒绝:Apple Intelligence界面,因为该能力要求用户注意力证明,而Siri无法提供。理由被记录下来;后续审计能捕捉漂移。
该模式对iOS 26+上交付应用的意义
三点要义。
-
三个界面,三种信任态势。人类、Apple Intelligence、智能体。每个都有其他界面没有的义务。为一个界面设计并强行套进其他界面,会在每个界面上都产生糟糕的架构。
-
领域在下;适配器在上。每个能力一个Swift函数;每个界面一个薄适配器;函数接受一个
Caller参数,这样它就可以在一处强制执行界面特定的规则。 -
并非每个能力都服务于全部三个界面。对不应该拥有某个能力的界面隐藏它,与暴露它同样是一项设计决策。拒绝清单的位置是挣来的。
完整的Apple生态系列:面向Apple Intelligence界面的类型化App Intents;面向智能体界面的MCP服务器;它们之间的路由问题;用于人类界面内端侧LLM功能的Foundation Models;运行时LLM与工具链LLM的区分;用于iOS锁屏状态机的Live Activities;Apple Watch上的watchOS运行时契约;作为人类界面底层基质的SwiftUI内部机制;用于visionOS场景的RealityKit空间思维模型;用于跨界面持久化的SwiftData schema纪律;用于人类视觉层的Liquid Glass模式;用于跨设备覆盖的多平台交付。中心枢纽在Apple生态系列。要获得更广泛的iOS与AI智能体上下文,请参阅iOS Agent Development guide。
FAQ
iOS应用的三个界面是什么?
人类界面(SwiftUI视图、点击、手势、屏幕)、Apple Intelligence界面(App Intents、Siri、Shortcuts、Spotlight)、智能体界面(暴露给Claude Code、Cursor、ChatGPT等外部LLM宿主的MCP服务器)。每个界面都有自己的调用者身份、延迟预算、渲染位置、持久化语义和信任态势。一个想要服务多个界面的能力应该坐落在领域层之上,在其上是每个界面的薄适配器。
是否每个能力都应当暴露给全部三个界面?
不是。某些能力被正确地限定在一个或两个界面上。照片拍摄、生物识别认证和敏感操作确认通常最适合作为前台的人类界面流程,因为信任信号(用户注意力、刻意行动)在那里最可靠地存在。当不存在终端用户审核流程时,由开发者驱动的批量操作只属于智能体界面。设计判断是某项能力服务于哪些界面,以及拒绝哪些界面。
Apple Intelligence界面与智能体界面的区别是什么?
Apple Intelligence是Apple的第一方智能体:用户调用Siri、Shortcuts或Spotlight;系统通过App Intents路由。信任来自OS。智能体界面是所有其他LLM宿主:开发者运行Claude Code或Cursor,终端用户运行Claude Desktop或ChatGPT。信任来自部署MCP服务器的人。App Intents是前者的协议界面;MCP是后者的协议界面。
端侧的Foundation Models LLM适合放在哪里?
放在人类界面之内。当用户调用一个会调用Foundation Models的应用内功能时,运行时LLM是一项人类界面能力的实现,而不是第四个界面。运行时LLM自身没有Siri或外部宿主调用者。Foundation Models工具是端侧模型读写应用领域状态的方式;驱动调用的是用户。
领域层模式如何简化多界面代码?
通过把规则集中起来。一个Swift函数接受一个Caller参数,在一处强制执行界面特定的行为(确认提示、限流、审计日志)。每个界面都是一个薄适配器(SwiftUI绑定、AppIntent.perform、MCP处理程序),把界面的协议翻译给领域函数。界面之间的漂移变得不可能,因为只有一个真相来源。
参考资料
-
作者分析,见What SwiftUI Is Made Of,2026年4月30日,涵盖值类型化的视图树、result-builder DSL以及人类界面之下的基质。 ↩
-
作者分析,见App Intents Are Apple’s New API to Your App,2026年4月28日,涵盖
AppIntent、AppEntity、AppEnum,以及让Apple Intelligence操作应用的类型化schema模型。 ↩ -
Apple Developer,“App Intents framework”。用于声明Apple Intelligence、Siri、Shortcuts和Spotlight可以路由的intents、entities、parameters和queries的界面。可发现性是安装时加更新;捐赠和索引会把intents呈现到Spotlight搜索和Siri建议中。 ↩
-
Anthropic,“Model Context Protocol”和“MCP Specification: Tools (2025-06-18)”。JSON-RPC工具暴露、宿主/服务器架构、stdio + Streamable HTTP传输,以及
inputSchema/ 可选的outputSchema。 ↩ -
作者分析,见App Intents vs MCP: The Routing Question,2026年4月30日,以及When the LLM Lives in Your App vs in Your Tooling,2026年5月1日。关于信任态势的”部署而非协议”框架,以及运行时/工具链LLM的区分。 ↩
-
作者分析,见Foundation Models On-Device LLM: The Tool Protocol,2026年4月30日。端侧LLM作为支撑人类界面能力的运行时特性;
Tool协议作为应用内模型与应用领域之间的桥梁。 ↩