YouMind
Iniciar sesión

La interfaz de usuario generativa 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 la interfaz de usuario generativa (controlada, declarativa y abierta) y aprende a implementarlos usando AG-UI y CopilotKit para 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 lanzaba.

Eso terminó.

Las interfaces que se lanzarán 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.

La pila de protocolos

Tres protocolos. Cada uno hace un trabajo.

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

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

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

No escribes un analizador para nada de esto. CopilotKit es un cliente AG-UI y decodifica la transmisión por ti.

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

Pregúntale 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 de más control a más flexibilidad.

  • Controlado: Tú pre-construyes los componentes. El agente elige cuál renderizar.
  • Declarativo: El agente emite un esquema. Tu aplicación lo mapea a componentes.
  • Abierto: El agente escribe HTML sin procesar. Tu aplicación lo renderiza en un entorno aislado.
Shubham Saboo - inline image

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

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 la mayoría de los equipos comienzan. También es donde la mayoría se queda atascada.

Pre-construyes un componente de 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 con el runtime de CopilotKit. El runtime la anuncia al agente a través de AG-UI. Cuando el agente la llama, los argumentos se transmiten y tu componente se renderiza en línea. Sin herramienta Python que escribir, sin esquema que cablear, sin ruta de 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 como esa para presupuestos reales, planes de ahorro y pago de deudas.

Shubham Saboo - inline image

¿Quieres el hook básico primero? Está en 'use-generative-ui-examples.tsx' en el Generative UI Starter Project.

El impuesto de tokens

Cada componente que registras ocupa espacio en la ventana de contexto del agente antes de que el usuario haya dicho algo. Una descripción de herramienta típica con su esquema JSON consume 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 gráfico de dona 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 vuelven a renderizar sin una segunda llamada al LLM. Fija una métrica, el panel 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 panel 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 aún se renderiza 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 va más allá. El plan, cada búsqueda, cada escritura de archivo, todo se transmite como tarjetas en vivo. Para todo lo demás, el hook del frontend es toda la historia.

Shubham Saboo - inline image

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

Cuándo no: Tu base de código 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. Más allá de 15 herramientas, probablemente dos de ellas se lean como "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 aplicaciones de agentes en producción terminan necesitando.

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

A2UI es la especificación 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 muéstralos 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 completa 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 implementa 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 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 Generative UI Starter Project, cableadas y emparejadas. search_flights en 'a2ui_fixed_schema.py', el catálogo FlightCard en 'renderers.tsx'. Pide vuelos. Mira las tarjetas transmitirse en el 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 envía un evento de vuelta al agente a través de AG-UI. El agente decide qué renderizar a continuación. Cero manejadores de clic.

Las matemáticas de los tokens

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

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 conectar 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. Paneles, resultados, formularios, tarjetas, widgets.

Cuándo implementar 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. Coincide 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 maneja. Excalidraw es el ejemplo que se me quedó grabado. El agente obtiene el 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 del cliente desde cero es tedioso, por lo que CopilotKit incluye un MCPAppsMiddleware. Adjúntalo 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);

Inicia el MCP Apps Showcase y estarás reservando vuelos y hoteles dentro de la ventana de chat. Mismo middleware, servidores MCP reales. O ve más allá.

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 entorno aislado

El agente escribe HTML sin procesar. Tu aplicación lo renderiza dentro de un iframe aislado 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 el 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 se basa en la estética que fue más prominente 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 la inconsistencia de marca

Intenté usar Abierto como la UI principal para 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

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 extraño 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 implementar Abierto: Consultas únicas. Visualizaciones desechables. Experimentos en entorno aislado. Nunca como la 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 estrictas, o demasiado flexibles de una manera que el navegador rechaza. Configura el sandbox del iframe para permitir scripts y permitir formularios. Nada más. Nunca allow-same-origin.

Cómo elegir

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

¿El diseñador tiene mockups perfectos para este flujo? Controlado.

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

¿Visualización única 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 predeterminado.

Si ya estás implementando y no estás seguro de dónde aterrizaste, cuenta las herramientas de renderizado. Más allá de 15, estás en Controlado y la pared está cerca. Empieza a cablear A2UI esta semana.

Tres patrones. Tres apuestas.

Controlado apuesta por ti. Componentes pre-construidos, perfectos. Costoso más allá de 25 de ellos.

Declarativo apuesta por el esquema. El esquema es el contrato. El agente lo completa. Escala plano.

Abierto apuesta por el modelo. Sin catálogo, sin esquema, HTML sin procesar. Bueno para desechable. Frágil para cualquier cosa que se implemente 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 lo hace por defecto. Chocan contra la pared a los 25 componentes y recurren a Abierto porque se ve atractivo en las demostraciones. Ninguna fue una decisión. Ambas 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 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 implementar agentes en producción, AG-UI y los patrones que escalan. Sígueme @Saboo_Shubham_ para mantenerte al tanto.

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