YouMind
Iniciar sesión

La interfaz generativa (Generative UI) es el nuevo frontend

@Saboo_Shubham_
INGLÉS03 jun 2026
1.1M
1.2K
148
49
3.7K

TL;DR

Explora los tres patrones arquitectónicos de Generative UI —Controlado, Declarativo y Abierto— y aprende a implementarlos utilizando AG-UI y CopilotKit para crear aplicaciones escalables impulsadas por IA.

El frontend solía ser algo fijo. Los diseñadores lo dibujaban. Los ingenieros lo construían. Los usuarios recibían lo que se enviaba.

Eso terminó.

Las interfaces que se envían en 2026 son dibujadas en parte por el propio agente, en tiempo real, a partir de lo que el usuario realmente pidió. Pide una tabla, obtén una tabla. No un párrafo describiéndola.

La UI Generativa es la capa que permite a los agentes dejar de describir y empezar a mostrar. Han surgido tres patrones para construirla, y las diferencias entre ellos importan más de lo que la mayoría de los equipos creen.

Pero no hay una sola forma de construir esto. Hay tres. Y la mayoría de los equipos eligen una sin saber que eligieron.

El stack de protocolos

Tres protocolos. Cada uno hace un trabajo.

MCP conecta agentes con herramientas. A2A conecta agentes entre sí. AG-UI conecta agentes con usuarios.

AG-UI es la capa de streaming que transporta todo lo que verás a continuación: llamadas a herramientas, esquemas A2UI, eventos MCP App, deltas de estado. Funciona sobre SSE. El estado fluye en ambas direcciones en el mismo stream. El usuario edita, el agente ve. El agente muta, el usuario ve.

A2UI es el estándar de Google para que los agentes emitan UI como esquema. Se monta sobre AG-UI. CopilotKit lo implementa en producción.

No tienes que escribir un parser para nada de esto. CopilotKit es un cliente AG-UI y decodifica el stream por ti.

Los tres patrones que la mayoría de los equipos confunden

Pregúntales a diez desarrolladores qué es la UI Generativa. Obtendrás diez respuestas. La mayoría describe el patrón que su framework actual implementa.

Solo hay tres. El espectro va desde más control hasta más flexibilidad.

  • Controlado: Tú preconstruyes los componentes. El agente elige cuál renderizar.
  • Declarativo: El agente emite un esquema. Tu app lo mapea a componentes.
  • Abierto: El agente escribe HTML crudo. Tu app lo renderiza en un sandbox.
Shubham Saboo - inline image

Cada framework de UI Generativa en 2026 se ubica en algún punto de esta línea. Las diferencias son arquitectónicas, no cosméticas. Cada patrón rompe tu app de una manera diferente al escalar.

Probé diferentes stacks. La mayoría cubre bien un patrón. Me decidí por CopilotKit porque soporta los tres en el mismo runtime, montado sobre AG-UI. Ese es el stack sobre el que funciona todo lo que sigue.

Patrón 1: Controlado, el frontend es dueño de la UI

Shubham Saboo - inline image

Aquí es donde empiezan la mayoría de los equipos. También es donde la mayoría se queda atascada.

Pre-construyes un componente React. Lo vinculas a un nombre de herramienta. El agente elige esa herramienta y el componente se renderiza en línea en el chat con los argumentos del agente como props.

Un hook de frontend. Cero código de agente. Eso es todo.

typescript
1"use client";
2import { z } from "zod";
3import { useComponent } from "@copilotkit/react-core/v2";
4
5const expenseChartSchema = z.object({
6 title: z.string(),
7 data: z.array(z.object({ label: z.string(), value: z.number() })),
8});
9
10function ExpenseChart({ title, data }: z.infer<typeof expenseChartSchema>) {
11 return (
12 <section className="rounded-xl border p-4">
13 <h3 className="text-sm font-medium">{title}</h3>
14 <ul className="mt-2 grid gap-1">
15 {data.map((d) => (
16 <li key={d.label} className="flex justify-between text-sm">
17 <span>{d.label}</span>
18 <span>${d.value}</span>
19 </li>
20 ))}
21 </ul>
22 </section>
23 );
24}
25
26export function ExpensesCopilot() {
27 useComponent({
28 name: "showExpenseChart",
29 description: "Renderiza un desglose de gastos por categoría.",
30 parameters: expenseChartSchema,
31 render: ExpenseChart,
32 });
33
34 return null;
35}

El hook registra la herramienta en el runtime de CopilotKit. El runtime la anuncia al agente a través de AG-UI. Cuando el agente la llama, los argumentos llegan por streaming y tu componente se renderiza en línea. Sin herramienta Python que escribir, sin esquema que cablear, sin ruta API que añadir.

Tu sistema de diseño sigue al mando.

Ese gráfico de gastos no es un mockup. El AI Financial Coach Agent renderiza tarjetas exactamente como esa para presupuestos reales, planes de ahorro y pagos de deuda.

Shubham Saboo - inline image

¿Quieres primero el hook básico? Está en 'use-generative-ui-examples.tsx' en el Proyecto Inicial de UI Generativa.

El impuesto de tokens

Cada componente que registras se sienta en la ventana de contexto del agente antes de que el usuario haya dicho nada. Una descripción de herramienta típica con su esquema JSON ocupa alrededor de 400 tokens. 25 componentes son 10,000 tokens en cada turno. Pagas ese impuesto por solicitud.

El agente también elige el componente equivocado. Demasiados se parecen. El gráfico circular y el de anillo ambos "muestran proporciones". El agente adivina.

Cuándo añadir estado del lado del agente

El estado compartido es el único caso en el que vale la pena escribir una herramienta Python. El agente escribe en el estado de la sesión. Otras partes de la UI se suscriben y se re-renderizan sin una segunda llamada al LLM. Fija una métrica, el dashboard se actualiza. Añade una fila, la tabla se redibuja.

python
1from google.adk.agents import LlmAgent
2from google.adk.tools import ToolContext
3
4def pin_metric(tool_context: ToolContext, label: str, value: float) -> dict:
5 """Fija una métrica al dashboard del usuario."""
6 pinned = tool_context.state.get("pinnedMetrics", [])
7 tool_context.state["pinnedMetrics"] = pinned + [{"label": label, "value": value}]
8 return {"status": "pinned"}
9
10agent = LlmAgent(name="dashboard_agent", model="gemini-3.5-flash", tools=[pin_metric])

El frontend lee las métricas fijadas a través del hook de estado compartido de CopilotKit. El componente de chat sigue renderizándose en línea porque el mismo nombre de herramienta está cableado con el hook del frontend.

Fija una métrica en el chat. El panel se redibuja sin una segunda llamada al modelo. Ese es el AI Dashboard Canvas Agent.

Shubham Saboo - inline image

El AI Deep Research Agent lo lleva más lejos. El plan, cada búsqueda, cada escritura de archivo, todo fluye como tarjetas en vivo. Para todo lo demás, el hook del frontend es toda la historia.

Shubham Saboo - inline image

Cuándo usar Controlado: Diez flujos de alto valor o menos. La precisión del diseño importa. Sabes exactamente qué UIs necesitas.

Cuándo no usarlo: Tu código base crece linealmente con los casos de uso. 25 componentes significan 25 definiciones de herramientas en cada turno del agente.

Qué se rompe: El agente elige el componente equivocado. Dos descripciones de herramientas se superponen semánticamente. Pasadas 15 herramientas, probablemente dos de ellas dicen "muestra datos". Solución: reescribe las descripciones para nombrar la intención del usuario, no lo visual. "Usar cuando el usuario pida comparar proporciones de un todo" es mejor que "renderiza un gráfico circular".

Patrón 2: Declarativo (A2UI), el agente emite el esquema

Shubham Saboo - inline image

Este es el patrón que la mayoría de las apps de agente en producción terminan necesitando.

El agente emite un esquema JSON que describe la UI. Tu app tiene un catálogo de componentes que mapea nodos del esquema a React (o Svelte, Flutter, lo que sea). Una herramienta. Muchas UIs.

A2UI es el estándar. CopilotKit implementa el runtime. ADK ejecuta el agente. AG-UI es el cable.

La herramienta del agente devuelve tres operaciones en orden: crear una superficie, enviar el árbol de componentes, enviar los datos.

python
1def search_flights(flights: list[Flight]) -> dict[str, Any]:
2 """Busca vuelos y los muestra como tarjetas enriquecidas."""
3 return {
4 "a2ui_operations": [
5 {"type": "create_surface", "surfaceId": SURFACE_ID, "catalogId": CATALOG_ID},
6 {"type": "update_components", "surfaceId": SURFACE_ID, "components": FLIGHT_SCHEMA},
7 {"type": "update_data_model", "surfaceId": SURFACE_ID, "data": {"flights": flights}},
8 ]
9 }

Esta es la función real, no pseudocódigo. El middleware del runtime ve el contenedor a2ui_operations en el resultado de la herramienta y reenvía las superficies al frontend. ¿Añadir hoteles? Nuevo archivo de esquema. Una función más con un ID de superficie diferente. Cero trabajo extra en el frontend.

Esquema fijo vs esquema dinámico

El árbol de componentes anterior vive en flights.json. Tú lo escribiste. El agente solo rellena los datos. Eso es un esquema fijo.

El esquema dinámico lo invierte: un LLM secundario escribe el árbol de componentes por turno a partir del contexto de la conversación. El mismo contenedor a2ui_operations al final. El showcase de Google ADK incluye ambos.

El catálogo es el contrato

Las definiciones listan los componentes que el agente puede emitir, con esquemas Zod para las props. Los renderizadores completan en React. Los errores tipográficos se convierten en errores de compilación en lugar de pantallas en blanco.

typescript
1const renderers: CatalogRenderers<TravelDefinitions> = {
2 FlightCard: ({ props }) => (
3 <article className="rounded-xl border p-4">
4 <header className="flex justify-between">
5 <span>{(props as any).airline}</span>
6 <span>{(props as any).price}</span>
7 </header>
8 <div className="text-sm text-muted-foreground">
9 {(props as any).origin} → {(props as any).destination} · {(props as any).departureTime}
10 </div>
11 </article>
12 ),
13};
14
15export const travelCatalog = createCatalog(travelDefinitions, renderers, {
16 catalogId: "copilotkit://travel-catalog",
17 includeBasicCatalog: true,
18});

Ambas mitades viven en el Proyecto Inicial de UI Generativa, cableadas y emparejadas. search_flights en 'a2ui_fixed_schema.py', el catálogo FlightCard en 'renderers.tsx'. Pide vuelos. Mira las tarjetas llegar por streaming al chat.

Shubham Saboo - inline image

Los botones y otros componentes interactivos llevan una acción en el esquema. El catálogo básico la conecta a onClick. El clic dispara un evento de vuelta al agente a través de AG-UI. El agente decide qué renderizar a continuación. Cero manejadores de clic.

El cálculo de tokens

50 tipos de tarjetas o 500, el agente ve una función. Los tokens por turno se mantienen planos a medida que tu librería de componentes crece.

Extensible a cualquier framework de renderizado porque es solo JSON. Cualquier agente que ya hable AG-UI puede manejar A2UI desde el día cero. No tocas el código del agente para cablear esto.

Compensación: El LLM es dueño del diseño. La salida varía de una ejecución a otra dentro de tu catálogo. Si estás enviando divulgaciones legales, superficies de marketing o cualquier cosa donde la ubicación exacta de los píxeles importe, este no es tu grupo.

Declarativo es el patrón construido para la larga cola. Dashboards, resultados, formularios, tarjetas, widgets.

Cuándo usar Declarativo: Tienes más casos de uso que tiempo para pre-construir. Te importa la economía de tokens más allá de la etapa de prototipo.

Qué se rompe: Construiste un FlightCard personalizado. Cada vuelo se renderiza como la tarjeta genérica del catálogo básico. Sin error en la consola. El CATALOG_ID en el agente y catalogId en createCatalog en el frontend no coinciden. El frontend no reconoce el catálogo al que apunta el agente, recurre al básico. Haz coincidir las cadenas exactamente en ambos lados.

Patrón 3: Abierto, sin catálogo, sin reglas

Shubham Saboo - inline image

El tercer patrón es el extremo opuesto. Sin catálogo. Sin esquema. Solo un lienzo en blanco.

Dos sub-patrones viven en este grupo.

MCP Apps

Un servidor MCP expone superficies de UI que el agente controla. Excalidraw es el ejemplo que se me quedó grabado. El agente obtiene control total del lienzo. Dibuja diagramas desde tu contexto. Es dueño de cada píxel en el tablero.

Shubham Saboo - inline image

Implementar el protocolo cliente desde cero es tedioso, así que CopilotKit incluye un MCPAppsMiddleware. Conéctalo a tu agente y apúntalo a cualquier servidor MCP Apps.

typescript
1const agent = new BuiltInAgent({
2 model: "openai/gpt-5.5",
3 prompt: "Eres un asistente útil.",
4}).use(
5 new MCPAppsMiddleware({
6 mcpServers: [{ type: "http", url: "https://mcp.excalidraw.com/mcp", serverId: "my-server" }],
7 }),
8);

Pon en marcha el MCP Apps Showcase y estarás reservando vuelos y hoteles dentro de la ventana de chat. El mismo middleware, servidores MCP reales. O ve más lejos.

El AI MCP App Builder permite al agente escribir una aplicación completamente nueva en un sandbox E2B, y luego la renderiza en vivo.

Shubham Saboo - inline image

0:45

HTML en sandbox

El agente escribe HTML crudo. Tu app lo renderiza dentro de un iframe con sandbox para que no pueda secuestrar la sesión.

El runtime registra una herramienta de renderizado HTML y la envía al agente a través de AG-UI. El agente la llama con el marcado que quiera. No hay una herramienta HTML que definir en el lado del agente. El runtime la inyecta.

La instrucción del lado del agente está haciendo trabajo real:

python
1canvas_agent = LlmAgent(
2 name="canvas_agent",
3 model="gemini-3.5-flash",
4 instruction=(
5 "Eres un asistente de visualización. Cuando el usuario pida ver, "
6 "dibujar o visualizar algo, genera una UI HTML interactiva. "
7 "Usa solo clases de Tailwind. Sin fuentes externas. Limítate a colores "
8 "neutros a menos que el usuario nombre uno."
9 ),
10)

Sin esas reglas de estilo, el modelo recurre a la estética que sea más ruidosa en sus datos de entrenamiento esa semana. Con ellas, obtienes algo cercano a tu marca la mayor parte del tiempo. No siempre.

El problema de inconsistencia de marca

Intenté usar el patrón Abierto como UI principal de un agente. Lo retiré en una semana.

"Neo-brutalista" el martes. "Clon de iOS 4" el miércoles. Las reglas de estilo en el prompt empujan al agente hacia tu marca. No lo garantizan. La marca seguía cambiando. El producto se sentía poco serio.

Shubham Saboo - inline image

El patrón Abierto no es inútil. Está mal aplicado.

La decisión correcta para una cosa: interacciones desechables donde al usuario no le importa cómo se ve la interfaz y nunca la volverá a ver. "Muéstrame cómo funcionan los electrones." "Dame un gráfico de barras raro de mis últimas 10 consultas." "Visualiza esta respuesta de API." El tipo de cosas que ves en los resúmenes de Google AI.

Cuándo usar Abierto: Consultas de una sola vez. Visualizaciones desechables. Experimentos en sandbox. Nunca como superficie principal.

Qué se rompe: El iframe se renderiza. Los botones no hacen clic. Los formularios no se envían. Las banderas del sandbox son demasiado restrictivas, o demasiado permisivas de una manera que el navegador rechaza. Configura el sandbox del iframe para permitir scripts y permitir formularios. Nada más. Nunca permitas el mismo origen.

Cómo elegir

Ejecuta el árbol de decisiones antes de escribir código.

¿El diseñador tiene mockups pixel-perfect para este flujo? Controlado.

¿Docenas de tipos de tarjetas o widgets para enviar? Declarativo.

¿Visualización de una sola vez y desechable que el usuario nunca verá dos veces? Abierto.

¿No puedes decidirte? Opta por Declarativo. Mejora a Controlado para los 3 flujos principales. Nunca Abierto como opción predeterminada.

Si ya estás enviando y no estás seguro de dónde caíste, cuenta las herramientas de renderizado. Pasadas 15, estás en Controlado y el muro está cerca. Empieza a cablear A2UI esta semana.

Tres patrones. Tres apuestas.

Controlado apuesta por ti. Componentes pre-construidos, pixel-perfect. Caro más allá de 25 de ellos.

Declarativo apuesta por el esquema. El esquema es el contrato. El agente lo rellena. Escala de forma plana.

Abierto apuesta por el modelo. Sin catálogo, sin esquema, HTML crudo. Bueno para lo desechable. Frágil para cualquier cosa que se envíe dos veces.

El error no es elegir el patrón equivocado. Es no saber que elegiste uno.

La mayoría de los equipos optan por Controlado porque el framework opta por Controlado. Chocan contra el muro en 25 componentes y recurren a Abierto porque se ve convincente en las demostraciones. Ninguno fue una decisión. Ambos fueron deriva.

Elige a propósito. Empareja el patrón con el problema. Controlado para los flujos que necesitan ser exactos. Declarativo para la larga cola. Abierto para lo desechable.

Plantillas de Agentes de UI Generativa de Código Abierto

La referencia para los tres patrones vive en la nueva sección Generative UI Agents de awesome-llm-apps. Clona lo que necesites. Elimina lo que no.

Publicaré más sobre cómo enviar agentes a producción, AG-UI y los patrones que escalan. Sígueme @Saboo_Shubham_ para mantenerte al día.

Guardar con un clic

Lee artículos virales en profundidad con IA en YouMind

Guarda la fuente, haz preguntas concretas, resume el argumento y convierte un artículo viral en notas reutilizables en un único espacio de trabajo con IA.

Explora YouMind
Para creadores

Convierte tu Markdown en un artículo de 𝕏 impecable

Cuando publicas tus propios textos largos, dar formato en 𝕏 a imágenes, tablas y bloques de código es un fastidio. YouMind convierte un borrador completo en Markdown en un artículo de 𝕏 impecable y listo para publicar.

Prueba Markdown a 𝕏

Más patrones por descifrar

Artículos virales recientes

Explorar más artículos virales