Back to blog
    Mastra + Vercel AI SDK + GGUF en Dispositivo: Un Stack de Agentes Móviles TypeScript Sin Costes de API
    mastravercel-ai-sdktypescriptreact-nativefine-tuningai-agentson-devicemobile

    Mastra + Vercel AI SDK + GGUF en Dispositivo: Un Stack de Agentes Móviles TypeScript Sin Costes de API

    Los desarrolladores móviles que prefieren TypeScript no tienen que usar frameworks de agentes Python. Mastra y el Vercel AI SDK más un modelo de 4B ajustado ejecutándose en el dispositivo a través de llama.cpp producen un stack completo de agentes con cero costes por token.

    EErtas Team·

    Actualizado 2026-05-10 — Refleja los lanzamientos de Mastra de principios de mayo que aterrizaron desde que se escribió esta guía. El lanzamiento del 1 de mayo añadió una nueva arquitectura ChannelProvider, un proveedor de Slack con OAuth, el adaptador @mastra/nestjs y un Google Drive WorkspaceFilesystem; el lanzamiento del 4 de mayo añadió autorización FGA basada en relaciones, flujos de trabajo programados basados en cron, y el nuevo @mastra/browser-viewer para automatización de navegador de extremo a extremo. Ninguno de estos cambia el patrón de modelo-ajustado-en-dispositivo de abajo — expanden la plataforma circundante.

    La mayoría del discurso sobre frameworks de agentes en 2026 todavía asume Python. LangGraph, CrewAI, AutoGen, Pydantic AI — las referencias canónicas todas viven en el ecosistema Python. Para los ingenieros de backend y los profesionales de ML, ese es un predeterminado sensato. Para los desarrolladores de aplicaciones móviles que envían React Native, Expo o aplicaciones híbridas Capacitor, es el lenguaje equivocado. Una base de código TypeScript no debería necesitar un sidecar Python para ejecutar un agente.

    El ecosistema TypeScript ahora tiene dos excelentes frameworks de agentes que resuelven esto. Mastra superó las 22,000 estrellas de GitHub y envió 1.0 en enero de 2026. El Vercel AI SDK ha sido el toolkit streaming-first de facto durante casi dos años y ahora respalda una fracción significativa de todas las aplicaciones LLM en producción escritas en TypeScript. Ambos funcionan limpiamente con modelos auto-hospedados, ambos están diseñados alrededor del despliegue edge-nativo, y ambos se combinan inusualmente bien con un modelo de 4B ajustado ejecutándose en el dispositivo.

    Esta guía recorre el stack completo de agentes móviles nativo de TypeScript: Mastra para orquestación, el Vercel AI SDK para inferencia, un modelo Qwen3-4B o Gemma 4 E4B entrenado por Ertas exportado como GGUF, y el Ertas Deployment CLI para enviarlo a una aplicación React Native. De extremo a extremo, el stack se ejecuta sin nunca llamar a una API hospedada después del paso inicial de entrenamiento.

    Los dos frameworks TypeScript, brevemente

    Mastra es la opción de nivel superior. Te da definiciones de agentes tipadas, flujos de trabajo declarativos, memoria durable, evaluaciones y primitivas RAG en un paquete con baterías incluidas. Las definiciones de herramientas son TypeScript idiomático con esquemas Zod. Los flujos de trabajo son DAGs basados en pasos que sobreviven a reinicios de proceso. La memoria y las evaluaciones se integran sin pegamento extra. Mastra es lo que alcanzas cuando quieres una plataforma completa de agentes con la forma del runtime JavaScript.

    El Vercel AI SDK es la opción de nivel inferior. Expone primitivas de streaming, salida estructurada vía Zod, y una abstracción genérica de proveedor sobre más de 90 proveedores de modelos — Anthropic, OpenAI, Google, Mistral, Cohere, además de runners auto-hospedados como Ollama y llama.cpp. El SDK también es a lo que Mastra llama para inferencia. Así que en la práctica no eliges uno u otro: Mastra te da la capa de orquestación, el Vercel AI SDK te da la capa de inferencia, y un modelo local ajustado te da la estructura de costes.

    La combinación es lo más cercano que TypeScript tiene a la historia de Pydantic AI más Ollama con la que los desarrolladores Python han estado construyendo todo el año — pero nativo del runtime que los desarrolladores móviles ya usan.

    Lo que estamos construyendo

    El agente de ejemplo es un planificador de entrenamientos para una aplicación de fitness React Native. El agente lee una solicitud en lenguaje natural, elige las herramientas correctas, y produce un plan validado. Tiene tres herramientas:

    • get_user_profile() devuelve la edad, peso e historial de entrenamiento del usuario
    • find_recent_workouts(limit: number) devuelve los últimos N entrenamientos como registros estructurados
    • propose_workout(focus: string, duration_min: number, difficulty: string) produce un plan de entrenamiento estructurado

    La salida es un objeto Zod WorkoutPlan. Mastra valida cada salida contra el esquema. Las llamadas a herramientas se validan contra sus esquemas de entrada. Todo el agente se ejecuta dentro del teléfono del usuario sin llamadas de red excepto telemetría opcional.

    Este es el tipo de agente que se vuelve caro rápidamente en una API frontier. Un usuario registrando dos entrenamientos al día genera de cuatro a seis llamadas al agente por sesión, multi-turno, con contexto no trivial. A 10,000 usuarios activos mensuales, estás gastando más en inferencia que en hosting.

    Paso 1: entrena el modelo en Studio

    Abre Ertas Studio y elige un modelo base. Para despliegue móvil amigable con TypeScript en 2026 las dos elecciones fuertes son Qwen3-4B-Instruct y Gemma 4 E4B. Ambos caben cómodamente en teléfonos modernos (unos 2,5 GB en Q4_K_M), ambos producen salidas estructuradas confiables después del fine-tuning, y ambos funcionan con el FFI móvil de llama.cpp. Qwen3 tiene una ligera ventaja en llamadas multi-paso a herramientas; Gemma 4 E4B tiene una ligera ventaja en matiz de seguimiento de instrucciones. Cualquiera es un buen punto de partida.

    Define los esquemas de herramientas en Data Craft. Studio lee las firmas de tus herramientas (pégalas como esquemas Zod, JSON Schema, o las propias firmas de funciones TypeScript) y usa la estructura como objetivo de entrenamiento. Para un planificador de entrenamientos, apunta a unos 500 ejemplos cubriendo llamadas de una sola herramienta, secuencias multi-herramienta, y rechazos (solicitudes fuera de alcance).

    Entrena con la configuración predeterminada de QLoRA para tool-calling: rango 32, tres épocas. La pérdida de validación típicamente se aplana alrededor de la época 2,5. En el nivel estándar de GPU la ejecución se completa en menos de una hora. La suite de evaluación de Studio reporta precisión de nombre de herramienta, precisión de nombre de parámetro y precisión de valor de parámetro. Los modelos listos para producción superan el 95% en las tres.

    Paso 2: exporta a GGUF y envía

    El pipeline de exportación de Studio produce un binario GGUF. Para un modelo de 4B en móvil, Q4_K_M es el predeterminado correcto — unos 2,5 GB en disco, alrededor de 3 GB de memoria de trabajo.

    Ejecuta el Ertas Deployment CLI contra tu proyecto React Native existente:

    ertas deploy mobile \
      --project ./my-fitness-app \
      --model ertas-workout-agent-4b.gguf \
      --framework react-native
    

    El CLI maneja tres cosas que históricamente han comido 20 a 40 horas de ingeniería de build de llama.cpp. Instala los enlaces FFI móviles (con el backend Metal en iOS y el backend OpenCL/Vulkan en Android). Registra el activo GGUF en el bundler para que el modelo se envíe dentro de la aplicación. Y monta un endpoint de inferencia estilo HTTP local dentro del proceso de la aplicación — típicamente alcanzable en un socket local del dispositivo — que refleja la forma de la API compatible con OpenAI que el Vercel AI SDK ya sabe cómo llamar.

    El mismo CLI admite Flutter, iOS Swift nativo y Android Kotlin nativo. La forma TypeScript del entregable es lo específico aquí.

    Paso 3: configura el Vercel AI SDK

    El Vercel AI SDK tiene un proveedor mantenido por la comunidad para Ollama y un proveedor genérico compatible con OpenAI que apunta a cualquier endpoint con forma de OpenAI. El Ertas Deployment CLI expone su endpoint en el dispositivo en forma compatible con OpenAI por defecto, así que lo conectas como cualquier otro proveedor:

    import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
    
    export const ertasLocal = createOpenAICompatible({
      name: "ertas-on-device",
      baseURL: "http://localhost:8080/v1",
      apiKey: "not-needed",
    });
    
    export const workoutModel = ertasLocal("ertas-workout-agent-4b");
    

    En desarrollo, apuntas baseURL a Ollama en tu portátil (puerto 11434). En producción en el dispositivo, el Ertas Deployment CLI expone el endpoint local en el puerto configurado (8080 por defecto) y la misma forma de llamada del SDK funciona sin modificación. Al SDK no le importa que la inferencia se esté ejecutando dentro de la aplicación en lugar de a través de la red — ve el mismo flujo de respuesta compatible con OpenAI de cualquier forma.

    Paso 4: define el agente Mastra

    Ahora conecta Mastra al modelo local y define el agente y las herramientas:

    import { Agent } from "@mastra/core/agent";
    import { createTool } from "@mastra/core/tools";
    import { z } from "zod";
    import { workoutModel } from "./ertas-local";
    
    const WorkoutPlan = z.object({
      focus: z.string(),
      duration_min: z.number(),
      difficulty: z.enum(["easy", "moderate", "hard"]),
      blocks: z.array(
        z.object({
          name: z.string(),
          sets: z.number(),
          reps: z.number(),
        }),
      ),
    });
    
    const getUserProfile = createTool({
      id: "get_user_profile",
      description: "Get the current user's age, weight, and training history.",
      inputSchema: z.object({}),
      outputSchema: z.object({
        age: z.number(),
        weight_kg: z.number(),
        history: z.array(z.string()),
      }),
      execute: async () => fitnessDb.getProfile(),
    });
    
    const findRecentWorkouts = createTool({
      id: "find_recent_workouts",
      description: "Return the user's most recent workouts.",
      inputSchema: z.object({ limit: z.number().default(5) }),
      outputSchema: z.array(
        z.object({ date: z.string(), name: z.string(), notes: z.string() }),
      ),
      execute: async ({ context }) => fitnessDb.recent(context.limit),
    });
    
    const proposeWorkout = createTool({
      id: "propose_workout",
      description: "Produce a structured workout plan for the user.",
      inputSchema: z.object({
        focus: z.string(),
        duration_min: z.number(),
        difficulty: z.enum(["easy", "moderate", "hard"]),
      }),
      outputSchema: WorkoutPlan,
      execute: async ({ context }) => planner.generate(context),
    });
    
    export const workoutAgent = new Agent({
      name: "workout-planner",
      instructions:
        "You plan workouts. Use the available tools to read the user's history before proposing a plan.",
      model: workoutModel,
      tools: { getUserProfile, findRecentWorkouts, proposeWorkout },
    });
    
    const result = await workoutAgent.generate(
      "Plan me a 45-minute moderate session focused on legs.",
      { output: WorkoutPlan },
    );
    
    console.log(result.object);
    

    Hay dos cosas que están pasando que el código no hace obvias. Primero, el agente lee el perfil del usuario y los entrenamientos recientes antes de proponer un plan porque el modelo ajustado fue entrenado en ejemplos que establecen ese patrón. Un modelo open-weight genérico frecuentemente saltaría la búsqueda de historial y propondría un plan genérico; el modelo entrenado usa las herramientas disponibles como están diseñadas. Segundo, la salida es validada contra WorkoutPlan por Mastra. Si el modelo emite un objeto inválido, el validador lo rechaza y Mastra expone un error tipado.

    El agente se ejecuta enteramente en el dispositivo. No hay llamadas a API en el camino de inferencia. Los datos del perfil del usuario nunca salen del teléfono. El único tráfico de red que el agente genera es cualquier telemetría a la que te suscribas.

    Por qué importa nativo de TypeScript para móvil

    Los equipos móviles que envían aplicaciones React Native o Expo tienen una ventaja significativa de productividad cuando la capa del agente está en el mismo lenguaje que la aplicación. Las definiciones de tipos fluyen de los esquemas Zod a través de Mastra a la UI de React Native sin ninguna generación de código entre lenguajes. Los errores lanzados en el agente surgen como excepciones tipadas en el árbol React. Las respuestas en streaming del Vercel AI SDK se conectan a los mismos hooks estilo useChat que los desarrolladores móviles ya están usando.

    La alternativa basada en Python requiere un servicio sidecar. O ejecutas un backend Python al que llama la aplicación React Native, o incrustas CPython en el binario móvil, o encuentras algún híbrido que divide el trabajo entre runtimes. Las tres opciones añaden complejidad de despliegue, tamaño de bundle y superficie de crash. Ninguna de ellas es necesaria si la capa del agente ya es TypeScript.

    La combinación de Mastra más el Vercel AI SDK encaja con el runtime en el que los desarrolladores móviles ya están. El Ertas Deployment CLI encaja con el mismo runtime. De extremo a extremo, estás enviando una sola aplicación TypeScript con un archivo de modelo junto a ella.

    El precipicio de costes agéntico, otra vez

    El caso económico es idéntico al que hacen los agentes en el dispositivo basados en Python, escalado para los patrones de uso móvil. Las llamadas a agentes en aplicaciones móviles tienden a ser de alta frecuencia y multi-turno — aplicaciones de fitness, de diario, de calendario, planificadores. El coste por llamada en una API frontier corre alrededor de $0,01 a $0,04 dependiendo de la longitud del contexto y la profundidad de la herramienta.

    Una curva de coste representativa de aplicación móvil en tasas típicas de uso:

    • 1,000 MAU a 4 llamadas/día promedio → aproximadamente $120/mes en inferencia
    • 10,000 MAU → aproximadamente $1,200/mes
    • 40,000 MAU → aproximadamente $4,800/mes
    • 100,000 MAU → aproximadamente $12,000/mes

    Estos números tienden a aterrizar más duro en equipos móviles que en equipos web porque la monetización móvil típicamente corre a través de suscripciones, no licencias por asiento. Tu economía unitaria empieza a romperse alrededor de la banda de 10,000 a 40,000 MAU — exactamente la banda donde estás intentando invertir en crecimiento, no retirarte de los costes de inferencia.

    En el dispositivo, la estructura de costes es fija. El coste marginal de una inferencia es electricidad. El coste fijo es el almacenamiento del modelo en el dispositivo, pagado una vez en la instalación. Pasar de 10,000 a 100,000 MAU no mueve la línea de inferencia.

    El precipicio de costes agéntico ha sido la fuerza dominante que da forma a la migración en el dispositivo. Los desarrolladores móviles TypeScript han estado esperando un stack de agentes que les permita responder a él sin renunciar al runtime.

    Lo que no tienes que renunciar

    Hay tres preocupaciones que los equipos móviles típicamente plantean cuando consideran un movimiento en el dispositivo, y el stack Mastra más Vercel AI SDK más modelo entrenado por Ertas aborda cada una.

    Streaming. Las primitivas de streaming del Vercel AI SDK funcionan de la misma forma contra un endpoint local de llama.cpp que contra una API hospedada. El renderizado token a token en tu UI de React Native no cambia.

    Salida estructurada. La validación Zod en el SDK y en Mastra se ejecuta sin cambios. El fine-tuning hace que la salida estructurada sea lo suficientemente confiable como para que la validación rara vez falle.

    Memoria y flujos de trabajo. Las primitivas de memoria y flujos de trabajo de Mastra no dependen de que el modelo se ejecute remotamente. El mismo almacén vectorial, las mismas definiciones de flujos de trabajo, el mismo arnés de evaluación funcionan contra un modelo local.

    Lo que sí renuncias es la capacidad de cambiar a un modelo frontier trivialmente. Una vez que has ajustado y enviado un modelo específico, cambiar a uno diferente significa otro fine-tune. En la práctica, este es el mismo compromiso que cada equipo que se ha movido a un modelo auto-hospedado ha aceptado, y es un compromiso que la mayoría de los equipos móviles tomará alegremente a cambio de una economía predecible.

    Yendo de prototipo a producción

    Un pipeline típico se ve así:

    1. Prototipo contra una API. Construye el agente Mastra contra Anthropic u OpenAI a través del Vercel AI SDK. Acierta con las herramientas, demuestra el valor.
    2. Cura un dataset. Unas pocas cientos de ejemplos de tu prototipo, validados en Data Craft contra tus esquemas Zod.
    3. Ajusta en Studio. Itera sobre el dataset hasta que las métricas de evaluación superen el 95%.
    4. Envía al dispositivo. Ejecuta el Ertas Deployment CLI contra tu proyecto React Native. Reemplaza el proveedor que apunta a la API en tu configuración del Vercel AI SDK con el proveedor local. Tu código de agente Mastra no cambia.
    5. Itera sobre trazas. Las trazas de producción se convierten en la siguiente ronda de datos de entrenamiento. Studio admite fine-tuning incremental desde trazas, así que el modelo mejora mientras los datos del usuario permanecen en el dispositivo.

    Los primeros tres pasos solían ser la parte difícil. Mastra y el Vercel AI SDK movieron la brecha de prototipo-a-producción de "semanas de código de streaming a medida" a "una tarde de definición de agentes." Studio cortó la brecha de dataset-a-fine-tune de meses-MLE a horas. El Ertas Deployment CLI cerró la última brecha — la que la mayoría de los desarrolladores TypeScript de aplicaciones nunca se molestaron en cruzar porque la ingeniería de build de llama.cpp era prohibitiva.

    Mastra más el Vercel AI SDK más un modelo entrenado por Ertas en el dispositivo es el stack de agentes que los desarrolladores móviles TypeScript han estado esperando. Sin sidecar Python. Sin factura por token. Sin precipicio de costes entre 10,000 y 100,000 usuarios.

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading