Flujo de trabajo agéntico de Foundation Models: LLM en la app vs LLM de herramientas
Una app de Swift en iOS 26 tiene dos LLMs tocándola, en capas muy distintas. Una es el modelo en el dispositivo que el usuario ejecuta a través del LanguageModelSession de la app. La otra es el agente que el desarrollador ejecutó a través de Claude Code o Cursor o Codex CLI para escribir la app en primer lugar. Confundir esas dos LLMs es un error de arquitectura recurrente en el desarrollo agéntico para Apple. No son el mismo problema; no comparten un modelo de seguridad; no comparten una historia de despliegue; y los patrones que funcionan para una fallan activamente para la otra.
La LLM en runtime es una función entregada al usuario. La LLM de herramientas es un lápiz que sostiene el desarrollador. El modelo en runtime vive detrás de las expectativas de privacidad del usuario, las verificaciones de disponibilidad del sistema y la revisión de la App Store. El modelo de herramientas vive detrás de la clave API del desarrollador, los permisos del sistema de archivos del IDE y una revisión de código de la que el desarrollador es responsable. Los dos stacks rara vez se cruzan, y cuando lo hacen (un servidor MCP que el desarrollador usa para operar el dominio de la app durante el desarrollo y que la app en runtime también podría exponer para automatización del usuario final), la frontera de confianza se mueve y la arquitectura tiene que reconocerlo.
El post nombra esa distinción y la pregunta de enrutamiento que sigue: ¿qué LLM debería servir qué capacidad y qué le debe cada una al usuario?
TL;DR
- La LLM en runtime es Foundation Models (
SystemLanguageModel.defaultmás el protocoloTool). La inferencia es local, el modelo se incluye con el OS, la app ejecuta la llamada en nombre del usuario.1 - La LLM de herramientas es lo que el desarrollador haya elegido: Claude en Claude Code, GPT en Cursor, Codex CLI para Swift. La inferencia es remota (la infraestructura de Anthropic o el proveedor de Claude configurado, OpenAI, etc.), el modelo está donde el host lo haya puesto, el desarrollador maneja al agente.
- Las dos LLMs no comparten seguridad, despliegue, presupuestos de latencia ni rendición de cuentas. Una capacidad que tiene sentido en una capa con frecuencia tiene la forma equivocada en la otra.
- El mismo servidor MCP que el desarrollador usa durante una sesión de Claude Code no es automáticamente la superficie correcta para la automatización agéntica del usuario final. La frontera de confianza cambia; lo que era una herramienta controlada por el desarrollador se convierte en una herramienta controlada por el usuario (o por el sistema).
Dos stacks, la misma palabra “LLM”
La colisión sucede en conversaciones como esta. Alguien dice “deberíamos añadir una LLM a la app”. Si eso significa una función que el usuario invoca (escríbeme un resumen de meditación, pule este borrador, clasifica esta foto) o una herramienta que el desarrollador conecta a su propio bucle de iteración (que Claude Code escriba la migración, que Cursor refactorice la vista) no queda claro por la frase. Ambas son adiciones de LLM. Ninguna es la misma decisión de ingeniería.
Foundation Models es un stack. El modelo vive en SystemLanguageModel.default, tiene una ventana de contexto fija, corre en silicio de Apple, nunca sale del dispositivo y está limitado por la elegibilidad del usuario para Apple Intelligence.1 El desarrollador de la app limita las entradas a través de tipos @Generable, expone capacidades de la app a través del protocolo Tool y entrega un binario que llama al modelo cuando la función se activa. El usuario invoca la función; el OS proporciona el modelo; la app los une.
Claude Code, Cursor, Codex CLI y cualquier otro IDE agéntico forman un stack distinto. El modelo vive donde sea que el proveedor de LLM host lo ejecute (los servidores de Anthropic para Claude, los de OpenAI para GPT, etc.). El IDE es el host. Los servidores MCP son herramientas que el modelo del host puede llamar. La máquina del desarrollador tiene acceso al sistema de archivos, acceso al shell y cualquier otra cosa que el IDE haya elegido exponer. El desarrollador invoca al agente; el agente accede al sistema de archivos del desarrollador; la salida aterriza en el proyecto del desarrollador.2
La misma palabra “LLM”, radios de impacto muy distintos.
Seis ejes en los que los dos stacks divergen
Seis propiedades hacen concreta la divergencia:
| Propiedad | LLM en runtime (Foundation Models) | LLM de herramientas (Claude Code, Cursor, Codex CLI) |
|---|---|---|
| Dónde corre la inferencia | En el dispositivo (silicio de Apple) | En la infraestructura del proveedor de LLM |
| Quién ejecuta la llamada | La app, en respuesta a una acción del usuario | El desarrollador, durante el bucle de iteración |
| Quién rinde cuentas | El desarrollador de la app (revisión de la App Store) | El desarrollador (sus commits, su revisión de código) |
| Qué toca el modelo | Los datos de la app dentro del sandbox de la app | El sistema de archivos del desarrollador, el shell, las herramientas MCP |
| Frontera de confianza | Usuario → app → modelo en el dispositivo | Desarrollador → IDE → modelo remoto + servidores MCP |
| Costo del mal uso | Privacidad, fallo de la app, rechazo de la App Store | Código malo, fuga de seguridad, build roto |
La frontera de confianza es la fila que carga el peso. La LLM en runtime opera dentro del sandbox de la app bajo las expectativas de privacidad del usuario; la LLM de herramientas opera dentro de la máquina del desarrollador bajo la autoridad del desarrollador. Un patrón como deja que la LLM ejecute un comando del shell es normal en herramientas (Claude Code hace esto constantemente a través de su herramienta Bash)3 y un punto de partida imposible en runtime: Foundation Models no tiene una herramienta Bash, y el protocolo Tool es una función tipada de Swift que el desarrollador de la app escribió y revisa.1
La fila del costo del mal uso es la consecuencia de equivocarse con la frontera de confianza. Una LLM en runtime que exfiltra datos del usuario a un servidor es una violación de privacidad y un rechazo de las directrices. Una LLM de herramientas que exfiltra el código fuente del desarrollador a un proveedor de LLM es, dependiendo del contrato del desarrollador, comportamiento esperado o una fuga. Ambas importan; importan por razones distintas.
El servidor MCP que se sienta en medio
El lugar más claro donde se ve moverse la frontera es cuando un único servidor MCP es usado por ambos stacks. Get Bananas incluye un servidor MCP que expone operaciones de lista de compras: leer ítems, añadir ítems, marcar como completado. El mismo servidor corre en dos lugares.4
En la sesión de Claude Code del desarrollador durante la iteración, el servidor MCP es una herramienta que el agente del desarrollador llama para manipular la propia lista del desarrollador. El servidor corre contra un archivo JSON en iCloud Drive. El desarrollador conectó el servidor a la configuración de su host MCP; el host sabe que debe llamarlo; el agente lee/escribe ítems de compras como parte de tareas de desarrollo más grandes.
En una superficie de agente para usuario final (un usuario de Claude Desktop externo apuntando a una lista compartida, por ejemplo), el mismo servidor MCP tiene obligaciones distintas. Quien llama ya no es Blake-el-desarrollador con confianza completa del sistema de archivos; quien llama es un usuario final cuya autenticación, autorización y verificación de intenciones no son responsabilidad del desarrollador. El servidor MCP tiene que aplicar esas barreras (o negarse a exponerse) antes de que esa superficie sea segura.
El mismo método JSON-RPC, add_item, servido a un desarrollador a través de un transporte stdio local sin autenticación, tiene la forma correcta. Servido a un host accesible por internet en nombre de un usuario final arbitrario sin autenticación, es un peligro para la integridad de los datos. El servidor MCP es el mismo código; el despliegue circundante lo cambia todo.
Esa es la regla de enrutamiento para servidores MCP en el desarrollo agéntico para Apple. El servidor es un contrato tipado sobre un dominio. Dónde se sienta en el stack (herramienta de desarrollador vs superficie de usuario final) es una decisión de despliegue, no una decisión de protocolo. Revisa el despliegue como código; no asumas que los valores predeterminados permisivos del protocolo son los valores predeterminados correctos del despliegue.
El protocolo Tool en el dispositivo no es un servidor MCP
Una confusión común: Foundation Models tiene un protocolo Tool, y MCP tiene llamadas a herramientas. ¿Son lo mismo? No, y la diferencia importa para el enrutamiento.
El protocolo Tool de Foundation Models es una API de Swift que el desarrollador de la app implementa: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 { ... }
}
La herramienta corre dentro del proceso de la app. El modelo al que sirve la herramienta es el SystemLanguageModel del dispositivo. Los argumentos y las salidas son tipos de Swift. El desarrollador revisa la implementación, la App Store revisa la app. El usuario invoca una función; la sesión de la app llama a la herramienta; el modelo local usa el resultado.
Una herramienta MCP es un método JSON-RPC expuesto por un servidor MCP, que es un proceso separado al que la LLM host (Claude, GPT, etc.) se conecta:2
{
"name": "add_item",
"description": "Add an item to the shopping list.",
"inputSchema": {"type": "object", "properties": {"name": {"type": "string"}}}
}
La herramienta corre fuera del proceso del agente, en cualquier lenguaje que el desarrollador haya elegido, hablando JSON sobre stdio o Streamable HTTP. El modelo está donde sea que el host lo haya puesto. Los argumentos son JSON validados contra el esquema. La rendición de cuentas es de quien haya desplegado el servidor MCP.
Los dos protocolos resuelven problemas que se solapan con alcances distintos:
| Decisión | Tool de Foundation Models |
Herramienta MCP |
|---|---|---|
| Quien llama | El modelo de lenguaje en el dispositivo | Un agente externo (Claude, GPT, Cursor, etc.) |
| Dónde corre | Dentro del proceso de la app, en el dispositivo | Un proceso separado al que el host se conecta |
| Lenguaje del esquema | Tipos @Generable de Swift |
Esquema JSON |
| Postura de confianza | La app es dueña; postura de privacidad del usuario | El desarrollador o proveedor es dueño; autoridad del agente |
| Cadencia de actualización | Actualización de la app | Redespliegue del servidor |
La regla de enrutamiento es directa: si la capacidad sirve a las propias funciones de LLM de la app para usuarios finales, va en un Tool de Foundation Models. Si la capacidad sirve a un agente externo (desarrollador o usuario final) operando entre procesos, va en una herramienta MCP. Algunas apps necesitan ambas; la misma función de Swift puede respaldar ambos adaptadores, pero los adaptadores viven en capas distintas del stack y se entregan a través de ciclos de lanzamiento distintos.5
Los hooks son donde la LLM de herramientas se gana su lugar
El radio de impacto de la LLM de herramientas hace de los hooks la primitiva de seguridad que carga el peso. El sistema de hooks de Claude Code ejecuta scripts en eventos del ciclo de vida (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop).6 Un desarrollador de iOS que usa Claude Code configura hooks no porque el agente sea malicioso, sino porque la autoridad del agente es amplia: escritura en el sistema de archivos, ejecución de shell, commits de git, push.
Los patrones que se ganan su espacio de hook en el trabajo agéntico para Apple:
Un bloqueo PreToolUse en comandos Bash que coincidan con xcodebuild o xcrun sin aprobación explícita. Claude Code puede ejecutar builds, borrar simuladores, invocar pasos de firma o exportación, o mutar el estado generado del proyecto si se lo permites. El hook convierte “el agente ejecutó un build” en “el agente pidió ejecutar un build y obtuvo un sí”. Frenar al agente en acciones irreversibles es la compensación correcta para la confianza del desarrollador.
Un validador PostToolUse en cada llamada a la herramienta Edit o Write contra archivos .pbxproj. El archivo de proyecto de Xcode es editado por humanos pero tóxico para los agentes; una línea equivocada rompe silenciosamente el build para cada desarrollador del equipo. Un hook que ejecute plutil -lint (o una verificación estructural similar) en cada escritura de .pbxproj antes de hacer commit es la diferencia entre “el agente escribió la migración en cinco minutos” y “el agente escribió la migración y cuarenta y cinco minutos de git bisect”.
Un hook Stop que ejecute swift build (o el comando de build apropiado) antes de dejar que el agente declare una tarea como hecha. Los agentes están entrenados en cómo se ve “hecho” en una conversación. El hook hace que “hecho” signifique “el build aún compila”, que es la única definición que importa para entregar.
La LLM en runtime no necesita nada de esto. Foundation Models no tiene shell, ni git, ni archivo de proyecto, ni configuración de servidor MCP. El Tool en el dispositivo es cualquier función de Swift que el desarrollador de la app haya escrito; el usuario invoca una función; nada escapa del sandbox o los permisos de la app a menos que la propia implementación de Tool de la app lo haga.
La asimetría es el punto. La LLM de herramientas tiene más autoridad y necesita más barreras. La LLM en runtime tiene menos autoridad por construcción. Apple hizo el trabajo de hacer que la LLM en runtime sea segura; el desarrollador hace el trabajo de hacer que la LLM de herramientas sea segura.
Reglas de arquitectura
Tres reglas arquitectónicas se siguen de la distinción entre runtime y herramientas.
Elige la capa por capacidad, no por app. Una app de meditación podría usar Foundation Models para resúmenes dentro de la app (LLM en runtime, en el dispositivo, se incluye con la app) y exponer un servidor MCP que el desarrollador usa con Claude Code para importar en lote el historial de sesiones durante la iteración. Las dos LLMs sirven a trabajos distintos en capas distintas. Tratarlas como una sola decisión produce un peor resultado en ambas capas que tratarlas como dos.
Revisa como código el alcance de la LLM de herramientas. Una sesión de Claude Code con acceso completo al sistema de archivos y servidores MCP remotos es un entorno de desarrollo poderoso y una superficie de ataque generosa. La mitigación no es “confía en el agente”; la mitigación son hooks, permisos limitados y un desarrollador que lee el diff. El agente trabaja para ti; el agente no eres tú.
Entrega el conjunto de Tool de la LLM en runtime como una API estable. Las herramientas de Foundation Models son parte del contrato binario de tu app. Eliminar o renombrar una herramienta entre lanzamientos es un cambio de comportamiento para los usuarios que dependían de la función. Trata las definiciones de herramientas como elementos de UI, no como ayudantes internos.
Lo que construiría de manera distinta en mi stack
Dos patrones que las apps del cluster entregan o desearían entregar.
Construye primero la capa de dominio; deja que las herramientas en runtime y los servidores MCP de herramientas envuelvan las mismas funciones de Swift. El patrón de doble adaptador de App Intents vs MCP se extiende naturalmente a las herramientas de LLM en runtime. Un método de dominio logWater(amount:caller:) es envuelto por un AppIntent (superficie de Apple Intelligence), una herramienta MCP (superficie de agente externo) y un Tool de Foundation Models (superficie de LLM en runtime dentro de la app). Tres adaptadores de protocolo, una función de dominio, tres clases de quien llama (agente del sistema, agente externo, modelo en el dispositivo) con tres obligaciones distintas. La función no sabe quién la invocó; los adaptadores cargan las señales de confianza.
Trata los servidores MCP del agente como código, no como configuración. Un .mcp.json referenciado en un proyecto de iOS es una superficie de confianza con alcance y precedencia (cubierto en The Repo Shouldn’t Get to Vote on Its Own Trust). Claude Code resuelve el alcance del servidor MCP como local > proyecto > usuario, y los servidores con alcance de proyecto piden aprobación al desarrollador antes de ser usados. El agente lee la configuración y se conecta a los servidores que el desarrollador aprueba; el desarrollador revisa la configuración y los servidores. Añadir un servidor MCP a un proyecto es una revisión de código, no un ajuste de configuración.
Cuándo Foundation Models es lo correcto y cuándo lo es la LLM de herramientas
El árbol de decisiones al que convergen los posts del cluster:
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.
La decisión rara vez produce un empate. Cuando lo hace (la misma capacidad podría legítimamente servir tanto a usuarios finales como a desarrolladores), la respuesta son dos adaptadores, no una superficie compartida, porque las posturas de confianza y las cadencias de actualización son lo suficientemente distintas como para que una superficie que intente servir a ambos comprometa a ambos.
Lo que el patrón significa para apps que se entregan en iOS 26+
Tres conclusiones.
-
Dos LLMs, dos stacks. La LLM en runtime (Foundation Models, en el dispositivo) es el agente del usuario operando sobre sus datos dentro de tu app. La LLM de herramientas (Claude Code, Cursor, Codex CLI) es el agente del desarrollador operando sobre la máquina del desarrollador para construir la app. Comparten la palabra “LLM” y casi nada más.
-
La frontera de confianza es la arquitectura. Dónde corre el modelo, quién lo ejecuta y qué toca definen las obligaciones. Los patrones que encajan en una frontera fallan activamente en la otra.
-
Los servidores MCP cargan la frontera. El mismo servidor es una herramienta de desarrollador en un despliegue y una superficie de usuario final en otro. El protocolo no cambia; el despliegue sí, y el despliegue es la parte que necesita la atención de ingeniería.
El cluster completo del Ecosistema Apple: App Intents tipados para Apple Intelligence; servidores MCP para agentes entre LLMs; la pregunta de enrutamiento entre los dos; Foundation Models para la LLM en el dispositivo y el protocolo Tool, con casos de uso y adaptadores personalizados como hermanos de ajuste de carga de trabajo y especialización; Live Activities para la máquina de estados de la pantalla de bloqueo de iOS; el contrato del runtime de watchOS en Apple Watch; los internos de SwiftUI para el sustrato del framework; el modelo mental espacial de RealityKit para escenas de visionOS; la disciplina de esquema de SwiftData para persistencia; los patrones de Liquid Glass para la capa visual; el envío multiplataforma para alcance entre dispositivos. El hub está en la Serie del Ecosistema Apple. Para un contexto más amplio sobre iOS-con-agentes-de-IA, consulta la guía de Desarrollo de Agentes en iOS.
FAQ
¿Cuál es la diferencia entre Foundation Models y Claude Code desde el punto de vista de la arquitectura?
Foundation Models es una función en runtime: la LLM se incluye con iOS 26, corre en el dispositivo del usuario a través de SystemLanguageModel.default y se invoca cuando el LanguageModelSession de la app se activa. La app ejecuta la llamada en nombre del usuario. Claude Code es una herramienta de desarrollo: la LLM corre en la infraestructura de Anthropic (o el proveedor de Claude configurado), la máquina del desarrollador hospeda el IDE, y el agente tiene acceso al sistema de archivos del desarrollador, al shell y a los servidores MCP. El desarrollador maneja al agente; el agente ayuda a construir la app.
¿Debería el mismo servidor MCP servir tanto a mi agente como a mis usuarios finales?
Probablemente no. El mismo contrato JSON-RPC puede tener la forma correcta para ambos, pero los despliegues son distintos: stdio del lado del desarrollador sin autenticación es normal para una herramienta de desarrollador, y un peligro para una superficie de usuario final. El protocolo es reutilizable; el despliegue no. Si expones el mismo servidor a ambos, trátalo como dos despliegues detrás de un código base, no como una superficie para ambas audiencias.
¿Por qué la LLM de herramientas necesita hooks pero la LLM en runtime no?
La LLM de herramientas tiene acceso al sistema de archivos, acceso al shell, servidores MCP y autoridad arbitraria de ejecución de código en la máquina del desarrollador. La LLM en runtime (Foundation Models) tiene lo que sea que las implementaciones de Tool de la app expongan, dentro del sandbox de la app, sin shell. El radio de impacto es asimétrico. Los hooks le dan al desarrollador revisión previa a la ejecución y validación posterior a la ejecución sobre la autoridad amplia. La LLM en runtime no los necesita porque su autoridad está limitada por construcción.
¿Puede una sola función de dominio de Swift servir a casos de uso de LLM tanto en runtime como de herramientas?
Sí, y ese es el patrón correcto. El enfoque de doble adaptador (una función de Swift, varios envoltorios de protocolo) se extiende desde App Intents vs MCP para incluir herramientas de Foundation Models. La función no sabe quién la invocó; los adaptadores cargan el esquema, las señales de confianza y las obligaciones específicas del protocolo. Tres adaptadores, un método de dominio.
¿Dónde encajan en este panorama las LLMs alojadas en la nube (OpenAI, API directa de Anthropic)?
Las LLMs en la nube llamadas desde dentro de una app en runtime son una tercera categoría: LLM en runtime con inferencia fuera del dispositivo. Comparten la postura de confianza de Foundation Models de “la app ejecuta la llamada en nombre del usuario” pero pierden la historia de privacidad en el dispositivo y la historia de disponibilidad provista por el OS. El árbol de decisiones se extiende: las LLMs en runtime en la nube son apropiadas para capacidades que genuinamente exceden el sobre del modelo en el dispositivo (contexto grande, razonamiento de frontera, multimodal a escala) y aceptables según las expectativas de privacidad del usuario (con divulgación transparente). Foundation Models es el predeterminado cuando la carga de trabajo encaja; la nube es la escalada cuando no.
Referencias
-
Análisis del autor en Foundation Models On-Device LLM: The Tool Protocol, 30 de abril de 2026, que cubre
SystemLanguageModel,LanguageModelSession, el protocoloTool, los macros@Generable/@Guidey la generación restringida. ↩↩↩↩ -
Anthropic, “Model Context Protocol” y “MCP Specification: Tools (2025-06-18)”. Exposición de herramientas JSON-RPC, arquitectura host/servidor y los transportes stdio + Streamable HTTP. ↩↩
-
Anthropic, “Claude Code reference: Hooks”. Eventos del ciclo de vida PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop; la superficie de validación que envuelve la autoridad amplia de la LLM de herramientas. ↩
-
Análisis del autor en Two Agent Ecosystems, One Shopping List, 29 de abril de 2026. El patrón de un solo código base con múltiples despliegues. ↩
-
Análisis del autor en App Intents vs MCP: The Routing Question, 30 de abril de 2026. El patrón de doble adaptador (un método de dominio de Swift, dos envoltorios de protocolo) extendido en este post a un patrón de triple adaptador con Foundation Models como la tercera clase de quien llama. ↩
-
Anthropic, “Hooks reference”. Eventos del ciclo de vida, matchers, forma del comando y el rol de los hooks como validación previa a la ejecución contra la autoridad del agente. ↩