Skip to content
Característica del Lenguaje

UI Generativa

Agentes que renderizan componentes ricos e interactivos en línea — tablas, gráficos, formularios, diffs — no solo texto. Sin necesidad de código de frontend.

Integrado
11 Componentes
Extensible Personalizado

Más Allá del Texto

Las interfaces de chatbot tradicionales renderizan todo como burbujas de texto. Pero los agentes producen datos estructurados — resultados de consultas, informes de validación, estado de despliegue, diffs de comparación. Renderizar todo eso como markdown es una experiencia deficiente.

La UI Generativa de Haira permite que las herramientas controlen de forma declarativa cómo aparece su salida. Una consulta de base de datos se renderiza como tabla. Un resultado de validación se renderiza como tarjeta de estado. Un pipeline de despliegue se renderiza como rastreador de progreso. Todo en línea en el chat, sin escribir código de frontend.

Cómo Funciona

Las herramientas devuelven componentes de UI usando el módulo ui. El runtime hace dos cosas con cada resultado:

Para el Usuario
Componente Rico
Transmitido al frontend mediante el protocolo ARP y renderizado como una tabla, tarjeta, gráfico o formulario interactivo.
Para el Agente
Resumen en Texto
Una representación textual compacta se envía al LLM para que pueda razonar sobre los datos y decidir los siguientes pasos.

Ninguna ruta se sacrifica. El usuario ve una tabla elegante, el agente ve datos estructurados.

Ejemplo — Herramienta con Salida de UI
haira
import "ui"

tool query_database(query: string) -> any {
    """Executes a SQL query and displays results."""
    rows, err = postgres.query(db, query)
    if err != nil {
        return ui.status_card("error", "Query Failed", conv.to_string(err))
    }
    return ui.table("Query Results", headers, rows)
}

Habilita la UI en un agente con una sola línea:

haira
agent DataExplorer {
    provider: OpenAI
    tools: [query_database, search_data]
    ui: ui
    memory: conversation(max_turns: 30)
}

11 Componentes Integrados

status-card
Tarjetas de resultado de éxito, error y advertencia con secciones desplegables
table
Tablas de datos con búsqueda, desplazamiento, pestañas y encabezados fijos
code-block
Código con resaltado de sintaxis, botón de copiar y múltiples pestañas
diff
Comparación lado a lado antes/después con resaltado de sintaxis
key-value
Listas de propiedades con valores estilizados para mostrar metadatos
progress
Rastreador de pipeline de varios pasos con estado por paso
chart
Visualizaciones de datos de línea, barra, circular, área y dispersión
form
Formularios interactivos con campos de texto, selección, casillas y área de texto
confirm
Diálogos de confirmación sí/no para acciones destructivas
choices
Selectores de opciones por botón o lista para la selección del usuario
product-cards
Cuadrículas de tarjetas con imagen para e-commerce y catálogos
Uso
haira
import "ui"

ui.status_card("success", "Deploy Complete", "All 3 services updated")
ui.table("Results", ["Name", "Email"], [["Alice", "a@co"], ["Bob", "b@co"]])
ui.key_value("Server Info", {"Region": "us-east-1", "Status": "healthy"})
ui.chart("bar", "Revenue", ["Q1", "Q2", "Q3", "Q4"], [dataset])
ui.confirm("Delete this record?", "Yes, delete", "Cancel")
ui.group(
    ui.status_card("success", "Query Complete", "42 rows"),
    ui.table("Results", headers, rows)
)

UI Web Autogenerada

Todo workflow de Haira obtiene automáticamente una UI web. Define un workflow, Haira genera el formulario:

haira
@webui(title: "File Summarizer", description: "Upload a file and get an AI summary")
@post("/summarize")
workflow Summarize(document: file, context: string) -> { summary: string } {
    content, err = io.read_file(document)
    if err != nil { return { summary: "Failed to read file." } }
    reply, err = Summarizer.ask("Summarize: ${content}")
    if err != nil { return { summary: "AI error." } }
    return { summary: reply }
}

El decorador @webui establece el título y la descripción. Los parámetros file se renderizan como entradas de subida. Los workflows de streaming (-> stream) obtienen una interfaz de chat completa.

UI de Chat en Streaming

Los workflows de streaming obtienen la experiencia más rica — streaming de tokens en tiempo real, tarjetas de ejecución de herramientas y componentes de UI en línea:

haira
@webhook("/chat")
workflow Chat(message: string, session_id: string) -> stream {
    return Assistant.stream(message, session: session_id)
}

fn main() {
    http.Server([Chat]).listen(8080)
}

La UI de chat se comunica mediante el protocolo ARP — gestionando deltas de texto, eventos del ciclo de vida de herramientas y renderizado de componentes ricos mediante WebSocket o SSE.

Componentes Personalizados

Para necesidades específicas del dominio, coloca Componentes Web de TypeScript en un directorio components/:

components/gantt-chart.ts
typescript
export class HairaGanttChart extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: "open" });
  }
  setProps(props) {
    // Render your custom UI
  }
}

export default {
  tag: "haira-gantt-chart",
  component: HairaGanttChart,
};

Los componentes personalizados heredan el tema de Haira mediante propiedades personalizadas de CSS y pueden despachar eventos haira-action que se convierten en mensajes de chat. El compilador los descubre, empaqueta e incrusta en tiempo de compilación.

El Pipeline

1
Herramientas
Devuelven datos tipados mediante funciones ui.*
2
Runtime
Emite mensajes ARP mediante WebSocket o SSE
3
Frontend
Renderiza el componente correspondiente en línea en el chat

Sin repositorio de frontend separado. Sin cliente de API que mantener. Sin biblioteca de componentes que instalar. Un archivo .haira, un binario, UI completa.

Released under the Apache-2.0 License.