智能体直接在对话中渲染丰富的交互式组件——表格、图表、表单、差异对比——而不仅仅是文字。无需编写任何前端代码。
传统聊天机器人 UI 将一切内容都渲染为文本气泡。但智能体产生的是结构化数据——查询结果、验证报告、部署状态、对比差异。将这些内容全部渲染为 Markdown 是糟糕的体验。
Haira 的生成式 UI 允许工具以声明式方式控制其输出的呈现方式。数据库查询结果渲染为表格。验证结果渲染为状态卡片。部署流水线渲染为进度追踪器。所有内容都直接内嵌在对话中,无需编写任何前端代码。
工具使用 ui 模块返回 UI 组件。运行时对每个结果做两件事:
两条路径互不牺牲。用户看到精美的表格,智能体看到结构化数据。
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)
}只需一行代码即可为智能体启用 UI:
agent DataExplorer {
provider: OpenAI
tools: [query_database, search_data]
ui: ui
memory: conversation(max_turns: 30)
}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)
)每个 Haira 工作流都会自动获得一个 Web UI。定义工作流,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 }
}@webui 装饰器设置标题和描述。file 类型参数渲染为文件上传输入框。流式工作流(-> stream)会获得完整的聊天界面。
流式工作流获得最丰富的体验——实时 token 流输出、工具执行卡片以及内嵌 UI 组件:
@webhook("/chat")
workflow Chat(message: string, session_id: string) -> stream {
return Assistant.stream(message, session: session_id)
}
fn main() {
http.Server([Chat]).listen(8080)
}聊天 UI 通过 ARP 协议进行通信——通过 WebSocket 或 SSE 处理文本增量、工具生命周期事件以及富组件渲染。
针对特定领域的需求,只需将 TypeScript Web Components 放入 components/ 目录:
export class HairaGanttChart extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: "open" });
}
setProps(props) {
// Render your custom UI
}
}
export default {
tag: "haira-gantt-chart",
component: HairaGanttChart,
};自定义组件通过 CSS 自定义属性继承 Haira 的主题,并可以分发 haira-action 事件,这些事件将转化为聊天消息。编译器在构建时自动发现、打包并嵌入这些组件。
ui.* 函数返回有类型的数据无需独立的前端仓库。无需维护 API 客户端。无需安装组件库。一个 .haira 文件,一个二进制文件,完整 UI。