← 所有文章

Foundation Models 智能体工作流:应用内LLM与工具链LLM

From the guide: Claude Code Comprehensive Guide

iOS 26 上的 Swift 应用有两个LLM在不同层面与之交互。一个是用户通过应用的LanguageModelSession运行的设备端模型。另一个是开发者通过Claude Code、Cursor 或 Codex CLI运行以编写应用本身的智能体。在智能体化的 Apple 开发中,混淆这两个LLM是一个反复出现的架构错误。它们不是同一个问题;它们不共享安全模型;它们不共享部署故事;对其中一个有效的模式对另一个则会主动失效。

运行时LLM是交付给用户的功能。工具链LLM是开发者手中的笔。运行时模型存在于用户的隐私预期、系统的可用性检查和 App Store 审核之后。工具链模型存在于开发者的API密钥、IDE 的文件系统权限以及开发者负责的代码审查之后。这两个技术栈很少相交,当它们相交时(开发者在开发期间用于操作应用领域的MCP服务器,运行时应用也可能将其暴露给最终用户进行自动化),信任边界发生移动,架构必须承认这一点。

本文阐述这种区别以及随之而来的路由问题:哪个LLM应该服务于哪种能力,每个LLM对用户负有什么义务。

TL;DR

  • 运行时LLM是 Foundation Models(SystemLanguageModel.default加上Tool协议)。推理在本地进行,模型随操作系统一同发布,应用代表用户运行调用。1
  • 工具链LLM是开发者所选择的任何工具:Claude Code中的Claude、Cursor 中的 GPT、用于 Swift 的 Codex CLI。推理在远程进行(Anthropic的基础设施或所配置的Claude提供商、OpenAI 等),模型部署在主机所在的位置,开发者驱动智能体。
  • 这两个LLM不共享安全性、部署、延迟预算或问责制。在某一层有意义的能力,在另一层往往是错误的形态。
  • 开发者在Claude Code会话中使用的同一个MCP服务器并不自动成为最终用户智能体自动化的正确接口。信任边界发生变化;曾经由开发者控制的工具变成了由用户控制(或系统控制)的工具。

两个技术栈,同一个词”LLM”

冲突发生在这样的对话中。有人说”我们应该给应用加一个LLM。”这究竟指的是用户调用的功能(给我写一份冥想总结、润色这份草稿、给这张照片分类),还是开发者接入到自身迭代循环中的工具(让Claude Code写迁移、让 Cursor 重构视图),从这句话本身并不清楚。两者都是LLM的添加。但它们不是同一个工程决策。

Foundation Models 是一个技术栈。模型位于SystemLanguageModel.default,具有固定的上下文窗口,运行在 Apple 芯片上,永远不离开设备,并受用户的 Apple Intelligence 资格门控。1应用开发者通过@Generable类型约束输入,通过Tool协议暴露应用能力,并发布在功能触发时调用模型的二进制文件。用户调用功能;操作系统提供模型;应用将两者拼接在一起。

Claude Code、Cursor、Codex CLI以及任何其他智能体化 IDE 构成了不同的技术栈。模型部署在宿主LLM提供商运行它的任何位置(Anthropic的服务器运行Claude、OpenAI 的服务器运行 GPT 等)。IDE 是宿主。MCP服务器是宿主模型可以调用的工具。开发者的机器拥有文件系统访问、shell 访问以及 IDE 选择暴露的任何其他权限。开发者调用智能体;智能体伸入开发者的文件系统;输出落入开发者的项目中。2

同样的词”LLM”,但作用范围截然不同。

两个技术栈分歧的六个维度

六个属性使分歧具体化:

属性 运行时LLM(Foundation Models) 工具链LLM(Claude Code、Cursor、Codex CLI)
推理运行位置 设备端(Apple 芯片) LLM提供商的基础设施
谁运行调用 应用,响应用户操作 开发者,在迭代循环中
谁负责 应用开发者(App Store 审核) 开发者(其提交、其代码审查)
模型接触什么 应用沙盒内的应用数据 开发者的文件系统、shell、MCP工具
信任边界 用户 → 应用 → 设备端模型 开发者 → IDE → 远程模型 + MCP服务器
滥用代价 隐私问题、应用崩溃、App Store 拒绝 糟糕的代码、安全泄露、构建中断

信任边界是承重的一行。运行时LLM在用户的隐私预期下运行于应用的沙盒内;工具链LLM在开发者的权限下运行于开发者的机器内。像让LLM运行一个 shell 命令这样的模式在工具链中是正常的(Claude Code通过其Bash工具不断这样做)3,但在运行时则是不可行的:Foundation Models 没有Bash工具,Tool协议是应用开发者编写并审查的强类型 Swift 函数。1

滥用代价那一行是搞错信任边界的后果。运行时LLM将用户数据外泄到服务器是隐私违规和指南拒绝。工具链LLM将开发者的源代码外泄给LLM提供商,根据开发者的合同,要么是预期行为,要么是泄露。两者都很重要;它们重要的原因不同。

介于两者之间的MCP服务器

观察边界移动的最清晰场景,是当一个MCP服务器同时被两个技术栈使用时。Get Bananas 发布了一个暴露购物清单操作的MCP服务器:读取条目、添加条目、标记完成。同一个服务器在两个地方运行。4

开发者的Claude Code会话中,迭代期间,MCP服务器是开发者智能体调用以操作开发者自己列表的工具。服务器针对 iCloud Drive 中的JSON文件运行。开发者将服务器接入其MCP主机配置;主机知道调用它;智能体作为更大开发任务的一部分读写购物条目。

最终用户智能体接口中(例如,外部Claude Desktop 用户指向共享列表),同一个MCP服务器有不同的义务。调用者不再是拥有完整文件系统信任的开发者 Blake;调用者是最终用户,其身份验证、授权和意图审查不是开发者的责任。在该接口变得安全之前,MCP服务器必须执行这些防护栏(或拒绝暴露自己)。

同一个JSON-RPC 方法add_item,通过本地 stdio 传输无身份验证地提供给开发者,是正确的形态。无身份验证地通过互联网可达的主机代表任意最终用户提供,则是数据完整性隐患。MCP服务器是同一份代码;周围的部署改变了一切。

这就是智能体化 Apple 开发中MCP服务器的路由规则。服务器是覆盖某个领域的强类型契约。它在技术栈中所处的位置(开发者工具与最终用户接口)是部署决策,而非协议决策。对部署进行代码审查;不要假设协议的宽松默认值就是部署的正确默认值。

设备端 Tool 协议不是MCP服务器

一个常见的混淆:Foundation Models 有Tool协议,MCP也有工具调用。它们是一样的吗?不是,而且这种区别对路由很重要。

Foundation Models 的Tool协议是应用开发者实现的 Swift API:1

struct WaterEntryLookup: Tool {
    let name = "lookup_water_entries"
    let description = "Look up water intake entries for a given date range."
    @Generable struct Arguments { ... }
    func call(arguments: Arguments) async throws -> String { ... }
}

工具运行在应用进程内。工具服务的模型是设备的SystemLanguageModel。参数和输出是 Swift 类型。开发者审查实现,App Store 审查应用。用户调用功能;应用的会话调用工具;本地模型使用结果。

MCP工具是MCP服务器暴露的JSON-RPC 方法,MCP服务器是宿主LLM(Claude、GPT 等)连接的独立进程:2

{
  "name": "add_item",
  "description": "Add an item to the shopping list.",
  "inputSchema": {"type": "object", "properties": {"name": {"type": "string"}}}
}

工具运行在智能体进程之外,使用开发者选择的任何语言,通过 stdio 或 Streamable HTTP 传输JSON。模型部署在宿主所在的位置。参数是根据 schema 验证的JSON。问责制由部署MCP服务器的人承担。

这两个协议以不同的范围解决重叠的问题:

决策 Foundation Models Tool MCP工具
调用者 设备端语言模型 外部智能体(Claude、GPT、Cursor 等)
运行位置 应用进程内,设备端 宿主连接的独立进程
Schema 语言 Swift @Generable类型 JSON Schema
信任姿态 应用拥有;用户的隐私姿态 开发者或厂商拥有;智能体的权限
更新节奏 应用更新 服务器重新部署

路由规则很直接:如果能力为最终用户服务于应用自身的LLM功能,它属于 Foundation Models 的Tool。如果能力服务于跨进程操作的外部智能体(开发者或最终用户),它属于MCP工具。某些应用两者都需要;同一个 Swift 函数可以支撑两个适配器,但适配器位于不同的技术栈层级,并通过不同的发布周期发布。5

钩子是工具链LLM赢得自己位置的地方

工具链LLM的作用范围使钩子成为承重的安全原语。Claude Code的钩子系统在生命周期事件(PreToolUsePostToolUseUserPromptSubmitSessionStartStop)上运行脚本。6使用Claude Code的 iOS 开发者设置钩子,并不是因为智能体有恶意,而是因为智能体的权限很广:文件系统写入、shell 执行、git 提交、推送。

在智能体化 Apple 工作中赢得钩子位置的模式:

对未经明确批准匹配xcodebuildxcrun的 Bash 命令使用PreToolUse阻塞。Claude Code可以运行构建、擦除模拟器、调用签名或导出步骤,或者在你允许的情况下修改生成的项目状态。钩子将”智能体运行了构建”变为”智能体请求运行构建并得到了同意。”在不可逆操作上让智能体放慢速度,是开发者建立信心的正确权衡。

对每个针对.pbxproj文件的 Edit 或 Write 工具调用使用PostToolUse验证器。 Xcode 项目文件由人编辑但对智能体有毒;一行错误就会悄无声息地破坏团队中每个开发者的构建。在每次.pbxproj写入提交前运行plutil -lint(或类似的结构检查)的钩子,是”智能体五分钟内完成迁移”和”智能体完成迁移加上四十五分钟 git bisect”之间的差别。

在让智能体宣布任务完成之前运行swift build(或相应的构建命令)的Stop钩子。智能体被训练知道对话中的”完成”是什么样子。钩子让”完成”意味着”构建仍可编译”,这是发布所需的唯一定义。

运行时LLM不需要这些。Foundation Models 没有 shell、没有 git、没有项目文件、没有MCP服务器配置。设备端的Tool只是应用开发者编写的 Swift 函数;用户调用功能;除非应用自己的Tool实现这样做,否则没有任何东西能逃出应用的沙盒或权限。

不对称就是关键。工具链LLM拥有更多权限,需要更多防护栏。运行时LLM在构造上权限更少。Apple 完成了让运行时LLM安全的工作;开发者完成让工具链LLM安全的工作。

架构规则

从运行时/工具链的区别中得出三条架构规则。

按能力选择层级,而不是按应用选择。冥想应用可能为应用内总结使用 Foundation Models(运行时LLM、设备端、随应用发布),同时暴露开发者在Claude Code中使用的MCP服务器,以在迭代期间批量导入会话历史。两个LLM在不同层级服务于不同的工作。将它们视为一个决策,会在两个层级上都产生比将它们视为两个决策更糟糕的结果。

对工具链LLM的影响范围进行代码审查。具有完整文件系统访问权限和远程MCP服务器的Claude Code会话是强大的开发环境,也是宽广的攻击面。缓解措施不是”信任智能体”;缓解措施是钩子、范围化权限以及阅读 diff 的开发者。智能体为你工作;智能体不是你。

将运行时LLM的Tool集合作为稳定的API发布。 Foundation Models 工具是你应用二进制契约的一部分。在版本之间删除或重命名工具,对依赖该功能的用户来说是行为变更。将工具定义视为 UI 启示,而不是内部辅助函数。

我会在自己的技术栈中如何不同地构建

集群的应用要么发布、要么希望发布的两个模式。

先构建领域层;让运行时工具和工具链MCP服务器包装相同的 Swift 函数。App Intents vs MCP中的双适配器模式自然延伸到运行时LLM工具。一个logWater(amount:caller:)领域方法被AppIntent(Apple Intelligence 接口)、MCP工具(外部智能体接口)和 Foundation Models Tool(应用内运行时LLM接口)包装。三个协议适配器,一个领域函数,三个调用者类别(系统智能体、外部智能体、设备端模型),具有三种不同的义务。函数不知道是哪个调用者调用了它;适配器携带信任信号。

将智能体的MCP服务器视为代码,而不是配置。 iOS 项目中引用的.mcp.json是范围和优先级信任接口(在The Repo Shouldn’t Get to Vote on Its Own Trust中讨论)。Claude Code将MCP服务器范围解析为本地 > 项目 > 用户,项目范围的服务器在使用前会提示开发者批准。智能体读取配置并连接到开发者批准的服务器;开发者审查配置和服务器。向项目添加MCP服务器是代码审查,而不是配置调整。

何时 Foundation Models 是正确的,何时工具链LLM是正确的

集群的文章趋于一致的决策树:

Is the capability a feature an end user invokes inside your app?
├── Yes → Runtime LLM (Foundation Models or cloud LLM behind an Apple Intelligence-aware surface)
│         Use the Tool protocol for app-internal tool calls.
│         Use App Intents for capabilities the system agent should reach.
└── No → It is part of the developer's iteration loop.
          ├── Is the capability local to one developer's machine? → Tooling LLM
          │     Use Claude Code, Cursor, or Codex CLI directly.
          │     Wrap shared utilities as MCP servers behind hooks.
          └── Is the capability shared across the team? → Tooling LLM with shared MCP servers
                Deploy the MCP server somewhere the team can reach.
                Code review the server like production code; gate dangerous tools behind explicit approval.

决策很少产生平局。当出现平局时(同样的能力可以合理地服务于最终用户和开发者),答案是两个适配器,而不是一个共享接口,因为信任姿态和更新节奏的差异足够大,一个试图同时服务两者的接口会在两者上都妥协。

这种模式对在 iOS 26+ 上发布的应用意味着什么

三个要点。

  1. 两个LLM,两个技术栈。运行时LLM(Foundation Models,设备端)是用户的智能体,在你的应用内对其数据进行操作。工具链LLM(Claude Code、Cursor、Codex CLI)是开发者的智能体,在开发者的机器上构建应用。它们共享”LLM”这个词,几乎没有别的共同点。

  2. 信任边界就是架构。模型在哪里运行、谁运行它以及它接触什么,定义了义务。适合一个边界的模式会主动失效于另一个边界。

  3. MCP服务器承载边界。同一个服务器在一个部署中是开发者工具,在另一个部署中是最终用户接口。协议不变;部署改变了,部署是需要工程关注的部分。

完整的 Apple 生态系统集群:用于 Apple Intelligence 的强类型App Intents;用于跨LLM智能体的MCP服务器;两者之间的路由问题;用于设备端LLM和 Tool 协议的Foundation Models,以及作为工作负载契合度和专业化兄弟篇的使用案例自定义适配器;用于 iOS 锁屏状态机的Live Activities;Apple Watch 上的watchOS 运行时契约;作为框架基础的SwiftUI 内部;用于 visionOS 场景的RealityKit 空间心智模型;用于持久化的SwiftData schema 纪律;用于视觉层的Liquid Glass 模式;用于跨设备覆盖的多平台发布。中心枢纽位于Apple Ecosystem Series。有关更广泛的 iOS 与 AI 智能体上下文,请参阅iOS Agent Development guide

FAQ

从架构角度看,Foundation Models 和Claude Code之间的区别是什么?

Foundation Models 是一个运行时功能:LLM随 iOS 26 一同发布,通过SystemLanguageModel.default运行在用户的设备上,并在应用的LanguageModelSession触发时被调用。应用代表用户运行调用。Claude Code是一个开发工具:LLM运行在Anthropic的基础设施上(或所配置的Claude提供商),开发者的机器托管 IDE,智能体可以访问开发者的文件系统、shell 和MCP服务器。开发者驱动智能体;智能体帮助构建应用。

同一个MCP服务器应该同时服务于我的智能体和最终用户吗?

可能不应该。同一个JSON-RPC 契约对两者来说可能是正确的形态,但部署不同:开发者端无身份验证的 stdio 对开发者工具来说是正常的,但对最终用户接口来说是危险的。协议是可重用的;部署不是。如果你确实将同一个服务器暴露给两者,请将其视为一个代码库后面的两个部署,而不是同时服务两个受众的一个接口。

为什么工具链LLM需要钩子,而运行时LLM不需要?

工具链LLM在开发者的机器上拥有文件系统访问、shell 访问、MCP服务器和任意代码执行权限。运行时LLM(Foundation Models)只拥有应用的Tool实现所暴露的内容,在应用的沙盒内,没有 shell。作用范围是不对称的。钩子为开发者提供对广泛权限的预执行审查和后执行验证。运行时LLM不需要钩子,因为它的权限在构造上就受到约束。

单个 Swift 领域函数能否同时服务于运行时和工具链LLM的使用案例?

可以,而且这是正确的模式。双适配器方法(一个 Swift 函数,多个协议包装器)从App Intents vs MCP扩展到包括 Foundation Models 工具。函数不知道是哪个调用者调用了它;适配器携带 schema、信任信号和协议特定的义务。三个适配器,一个领域方法。

托管的云LLM(OpenAI、Anthropic API直接调用)在这幅图景中处于什么位置?

在运行时从应用内调用的云LLM是第三类:具有设备外推理的运行时LLM。它们与 Foundation Models 共享”应用代表用户运行调用”的信任姿态,但失去了设备端隐私故事和操作系统提供的可用性故事。决策树扩展为:云运行时LLM适合于真正超出设备端模型范围的能力(大上下文、前沿推理、规模化多模态),并且对用户的隐私预期可接受(带有透明披露)。当工作负载契合时,Foundation Models 是默认选择;当不契合时,云是升级选项。

References


  1. 作者在Foundation Models On-Device LLM: The Tool Protocol中的分析,2026 年 4 月 30 日,涵盖SystemLanguageModelLanguageModelSessionTool协议、@Generable / @Guide宏以及受约束的生成。 

  2. Anthropic,“Model Context Protocol”“MCP Specification: Tools (2025-06-18)”。JSON-RPC 工具暴露、宿主/服务器架构以及 stdio + Streamable HTTP 传输。 

  3. Anthropic,“Claude Code reference: Hooks”。PreToolUse、PostToolUse、UserPromptSubmit、SessionStart、Stop 生命周期事件;包装工具链LLM广泛权限的验证接口。 

  4. 作者在Two Agent Ecosystems, One Shopping List中的分析,2026 年 4 月 29 日。单一代码库、多部署模式。 

  5. 作者在App Intents vs MCP: The Routing Question中的分析,2026 年 4 月 30 日。双适配器模式(一个 Swift 领域方法,两个协议包装器)在本文中扩展为以 Foundation Models 作为第三调用者类别的三适配器模式。 

  6. Anthropic,“Hooks reference”。生命周期事件、匹配器、命令形态以及钩子作为针对智能体权限的预执行验证的角色。 

相关文章

MCP服务器是新的攻击面

50个MCP漏洞,60天内30个CVE,其中13个严重。工具使用协议是无人审计的攻击面——这里是分类与修复方案。

1 分钟阅读