本篇文章简要介绍 基于 CopilotKit 生成式UI框架
主要用于解决 llm agent 响应结果的可视化展示问题
llm 产出如果不加以修饰绘制,用户看到的就只是普通文本,尤其对于一些数据类文本,缺少可视化能力
再丰富一些,可能会输出markdown格式 进行一定规则的渲染,能力依然有限,不如前端组件渲染丰富
CopilotKit 框架 基于AG-UI 协议,将前端展示组件库直接绑定到agent,作为tool 供agent 调使用,直接产生可视化展示结果
Generative UI
Render your agent’s state, progress, outputs, and tool calls with custom UI components in real-time. Bridges the gap between AI agents and user interfaces.
生成式UI就是丰富agent 响应结果的动态UI, 可以让agent 生成可交互式界面 按照可生成范围大小可以分成三类
- 生成式UI 全控式,agent 只能在注册的指定几个组件范围内根据用户指令判断是否要使用,不能自定义组件
- 生成式UI 声明式,agent 可以在注册的一堆组件(相当于给agent一个组件库)中选取组件使用,也可以组装几个组件形成固定布局并进行注册,触发后直接根据数据渲染组件即可,也是不能自定义组件
- 生成式UI 开放式,agent 不注册任何组件,可以直接连接外部组件的mcp协议,实现组件的动态加载和使用,跨出了指定组件库的束缚,对于指定场景需求可以直接调用更复杂精细的匹配度更高的组件
下面CopilotKit 框架会按开放程度依次介绍
AG-UI 协议
AG-UI is an open, lightweight, event-based protocol that standardizes how AI agents connect to user-facing applications.
AG-UI is designed to be the general-purpose, bi-directional connection between a user-facing application and any agentic backend.
Built for simplicity and flexibility, it standardizes how agent state, UI intents, and user interactions flow between your model/agent runtime and user-facing frontend applications—to allow application developers to ship reliable, debuggable, user‑friendly agentic features fast while focusing on application needs and avoiding complex ad-hoc wiring.
AG-UI协议定义了agent直接和用户界面之间的通信协议,是三大开源代理协议之一,实现了agent 和应用页面之间实时,多模态,可交互用户体验
打破了现有前后开发模式(前端等待数据返回后,再进行渲染,用户再感知交互)
AG-UI协议 出现的必要性
虽然代理只是软件,但它们展现出的特性使得传统的 REST/GraphQL API 难以为其提供服务:
代理运行时间长,并会流式传输中间工作——通常跨越多个会话。
代理具有非确定性,并且能够以非确定性的方式控制应用程序 UI。—>结果是不可预测的,需要前端进行实时渲染,需要自行选择渲染组件
代理同时混合结构化和非结构化 I/O(例如,文本和语音,以及工具调用和状态更新)。
代理需要用户交互式组合:例如,它们可能会调用子代理,而且通常是递归调用。
等等
它是一种基于事件的协议,它支持代理前端和后端之间的动态通信。它构建于 Web 的基础协议(HTTP、WebSocket)之上,作为一个专为代理时代设计的抽象层——弥合了传统客户端-服务器架构与 AI 代理的动态、有状态特性之间的差距
详见
区别其他协议
| Layer | Protocol / Example | Purpose |
|---|---|---|
| Agent ⇔ User Interaction | AG-UI (Agent-User Interaction Protocol) | The open, event-based standard that connects agents to user-facing applications — enabling real-time, multimodal, interactive experiences. |
| Agent ⇔ Tools & Data | MCP (Model Context Protocol) | Open standard (originated by Anthropic) that lets agents securely connect to external systems — tools, workflows, and data sources. |
| Agent ⇔ Agent | A2A (Agent to Agent) | Open standard (originated by Google) which defines how agents coordinate and share work across distributed agentic systems. |
区别 A2UI
A2UI is a generative UI specification - allowing agents to deliver UI widgets, where AG-UI is the Agent↔User Interaction protocol - which connects an agentic frontend to any agentic backend
A2UI, MCP-UI, and Open-JSON-UI are all generative UI specifications. Generative UIs allow agents to respond to users not only with text but also with dynamic UI components.
| Specification | Origin / Maintainer | Purpose |
|---|---|---|
| A2UI | A declarative, LLM-friendly Generative UI spec. JSONL-based and streaming, designed for platform-agnostic rendering. | |
| Open-JSON-UI | OpenAI | An open standardization of OpenAI’s internal declarative Generative UI schema. |
| MCP-UI | Microsoft + Shopify | A fully open, iframe-based Generative UI standard extending MCP for user-facing experiences. |
AG-UI is not a generative UI specification — it’s a User Interaction protocol that provides the bi-directional runtime connection between the agent and the application.
AG-UI natively supports all of the above generative UI specs and allows developers to define their own custom generative UI standards as well.
A2UI 是与agent进行交互的组件库的存在形式和定义规范
A2UI 是一种生成式 UI 规范 - 允许代理交付 UI 小部件,
AG-UI 是代理↔用户交互协议 - 它将代理前端连接到任何代理后端
CopilotKit 框架
一个可以链接多种前端框架和多种agent框架的生成式UI框架,利用AG-UI协议,实现agent和前端页面之间的实时通信渲染🔗
CopilotKit 中的生成式 UI 是一组基元,可让代理决定屏幕上显示的内容
从渲染您构建的特定应用程序组件,到根据目录组合布局,再到嵌入 MCP 服务器提供的沙盒 UI。
generative ui
| 应用场景 | 方案 | 说明 |
|---|---|---|
| 让 Agent 渲染你已构建好的特定应用组件 | Components as Tools(组件即工具) | 将应用组件注册为前端工具;Agent 调用它时,CopilotKit 会内联渲染,并支持类型化的输入参数。 |
| 为 Agent 现有后端工具调用自定义 CopilotKit 渲染卡片样式 | Tool Call Rendering(工具调用渲染) | 将 Agent 已有的后端工具调用映射到自定义 UI 卡片,展示实时状态、参数和结果。 |
| 随 Agent 状态变化更新 UI(进度、草稿、仪表盘等) | State Rendering(状态渲染) | 订阅 Agent 的流式状态,在值到达时重新渲染 UI。 |
| 在对话中展示模型的思考链 | Reasoning(推理过程) | 将模型的推理 token 作为一等消息类型内联渲染(默认卡片,或完全自定义)。 |
| 让 Agent 从你定义的组件目录中组合布局 | A2UI:场景已知用 Fixed Schema(固定模式),场景未知用 Dynamic Schema(动态模式) | 基于 Agent 输出的声明式 Schema 渲染 UI,通过你注册的组件目录进行组合。两种风格:Dynamic Schema(LLM 生成 Schema)和 Fixed Schema(你编写 Schema,Agent 提供数据)。 |
| 在对话中嵌入第三方 MCP 托管的 UI | MCP Apps(MCP 应用) | 嵌入 MCP 服务器随其工具一同提供的 UI,在沙盒 iframe 中渲染,无需前端渲染器。 |
These primitives sit along a spectrum from author-controlled to agent-invented. Same frontend application, same runtime, same AG-UI protocol — the choice is per-feature, not per-product.
- Controlled — you wrote the component; the agent only picks which one to render and what data to pass. Highest - predictability, highest engineering cost per capability. Components as Tools, Tool Call Rendering, State Rendering, Reasoning.
- Declarative — the agent emits a structured spec; the frontend composes from a catalog you registered. Creativity inside a guardrail. A2UI (Dynamic and Fixed Schema).
- Open-Ended — the UI is invented elsewhere (an MCP server) and you sandbox it. Highest expressive range, hardest to guarantee accessibility / brand / security. MCP Apps.
这些基本组件涵盖了从作者控制到代理创建的各个层面。相同的前端应用程序、相同的运行时环境、相同的 AG-UI 协议——选择是针对特定功能,而非针对特定产品。
受控型——您编写组件;代理仅负责选择要渲染的组件以及要传递的数据。可预测性最高,但每个功能的工程成本也最高。组件即工具、工具调用渲染、状态渲染、推理。
声明式——代理生成结构化的规范;前端根据您注册的目录进行组合。在一定的框架内进行创新。A2UI(动态和固定模式)。
开放式——用户界面在其他地方(MCP 服务器)创建,并由您进行沙盒化。表达范围最广,但最难保证可访问性/品牌/安全性。MCP 应用程序。
hooks
| Hook | 使用场景 |
|---|---|
| useFrontendTool | 给 Agent 提供一个客户端工具调用(在浏览器中运行逻辑),可选支持内联 UI。 |
| useRenderTool | 按名称(类型化)渲染特定工具调用的 UI,无需定义工具的处理函数。 |
| useDefaultRenderTool | 为没有特定渲染器的任意工具调用提供一个通用的通配渲染器。 |
| useComponent | 将一个 React 组件注册为命名工具渲染器(以组件优先的生成式 UI 方式)。 |
| useHumanInTheLoop | 在工具调用时暂停 Agent,等待用户批准、编辑或提供输入。 |
| useInterrupt | 处理 Agent 发起的中断,在用户响应后恢复执行。 |
| useRenderToolCall | 获取工具调用的渲染函数,用于驱动你自己的自定义聊天界面(无头模式)。 |
多agent 切换
AG-UI:协议桥
CopilotKit 不会是一个代理框架中。运行时通过 AG-UI 与代理进行通信,AG-UI 是一种开放的事件驱动协议,可标准化代理与应用程序的通信方式:
事件驱动 — 16 种标准化事件类型(文本增量、工具调用、状态快照和增量、运行生命周期)从代理通过运行时流到前端。
双向——用户发送输入,代理响应,代理暂停以进行人机交互输入,前端公开代理可以调用的前端工具。
与传输无关——SSE、WebSockets、webhooks,无论您的堆栈喜欢什么。
与框架无关——每个受支持的集成都会附带一个精简的 AG-UI 适配器。使用一行运行时配置切换后端。
“代理的未来不是一家公司或一个平台,而是一个通过协议连接的代理生态系统。”
因为合约是一个协议,而不是 SDK 锁定,所以您可以交换代理层,而无需重写前端,并行运行多个代理后端,并与任何 AG-UI 兼容的内容集成:MCP 服务器、A2UI 组件、Oracle / Google / AWS 代理平台。
后端启动多服务
1 | # 本脚本主要练习 |
前端注册多个agent
1 | import { HttpAgent } from "@ag-ui/client"; |
前端指定agent
1 | import { CopilotChat } from "@copilotkit/react-core/v2"; |
前端调用CopilotKit agent
1 | import { StrictMode } from "react"; |
Controlled Generative UI 全控式
什么是受控生成式用户界面?
生成式用户界面是一种模式,在这种模式下,智能体会使用完全交互式的界面进行响应,而不仅仅是文本,受控生成式用户界面是最严格的形式:智能体只能渲染你明确注册过的组件。
其工作原理如下:
每个已注册的成分都作为一个工具被呈现出来,具有以下功能:
一个稳定的名字
一个格式化的输入模式
一个已映射的 React 组件
该代理不会生成随机的用户界面。它会将结构化数据传递给你已经构建的组件,而这些组件的定义是在前端阶段完成的,并且在运行时被注册到相应的位置。
优点
- 实施起来非常简单:只需注册一个组件即可。
- 视觉效果非常精致,因为所有渲染出的表面都是您亲手创作的。
- 强大的安全性保障:该模型只能调用那些具有有效参数的注册工具。
- 非常适合那些需要稳定性能的、高流量或关键任务型的用户界面场景。
缺点
- 随着新功能的不断增加,前端开发的工作量也在逐步上升:每一种模式都需要相应的组件来支持。
- 相比声明式或开放式生成式 UI,其表达自由度要低一些。
1 | import { z } from "zod" |
useComponent 注册组件
Tool-based Generative UI is the simplest form of Generative UI: you register a React component with useComponent, and CopilotKit exposes it to the agent as a tool. When the agent calls the tool, CopilotKit renders your component inline in the chat, passing the tool’s arguments straight through as typed props.
Unlike tool rendering, which wraps a real backend tool in a custom UI, tool-based GenUI is the component. There is no handler, no user interaction, no server-side execution. The agent decides when to show it, populates the data, and CopilotKit paints it.
Deccontrolled Generative UI 声明式
什么是声明式生成式 UI?
声明式生成式 UI 让你定义一组 UI 构建块,由 Agent 将它们组合成界面。它从组件目录中选择组件,将它们排列成 Schema,并绑定运行时数据来填充最终结果。
它由三个部分协同工作:
- 组件目录:你的应用支持的 UI 基元,分为两部分:
- 定义(Definitions):对每个组件的名称、属性和用途的平台无关描述。
- 渲染器(Renderers):将定义转化为实际 UI 的平台特定实现(例如 React 组件)。
- Schema:关于使用哪些组件、如何嵌套以及它们之间关系的结构化描述。
- 数据绑定(Data bindings):运行时填充 Schema 的真实值,例如航班详情、指标或记录。
一个有用的心智模型是乐高积木:目录是装着积木的盒子,Schema 是积木拼接的方式,数据绑定在运行时填充最终细节。Agent 动态组装界面,而你的应用始终掌控一致性、安全性和渲染质量。
为什么使用声明式生成式 UI?
全控式生成式 UI 适用于流量最高、可预测性最重要的场景。但在长尾场景中(内部工具、边缘情况、多样化的用户目标),手动编写每个布局无法扩展。这正是声明式生成式 UI 的价值所在:Agent 从一组固定的构建块中组装 UI,在不牺牲安全性和一致性的前提下获得适应性。
优点
- 受约束的灵活性:Agent 在不超出你的组件体系的前提下适配界面。
- 自带组件:由你定义基元,Agent 决定如何组合它们。
- 每个场景工作量更少:只需定义一次目录,即可在各处复用。
- 原生跨平台:同一套 Schema 可在 Web、移动端、Slack 和短信中渲染。
- 比开放式生成式 UI 更省 Token:Agent 使用固定词汇表工作,无需生成任意代码。
缺点
- 像素级控制较弱:无法对最终界面进行精确微调。
- 可预测性较低:Agent 在相似场景下可能以不同方式组装组件。
- 更容易出错:Schema 和数据绑定可能以细微方式失败,需要验证和恢复逻辑。
- 需要前期设计:组件目录、Schema 格式和渲染器契约需要仔细定义。
开启a2ui 组件 进行组件组装渲染
通过启动A2UI可以将声明好的一系列组件打包 成一个组件库 供agent 使用
agent 可以根据prompt 和问题响应自行利用组件进行组装,生成对应的UI界面1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import { serve } from "@hono/node-server";
import {
CopilotRuntime,
createCopilotEndpoint,
} from "@copilotkit/runtime/v2";
import { LangGraphHttpAgent } from "@copilotkit/runtime/langgraph";
const langGraphAgent = new LangGraphHttpAgent({ url: "http://localhost:8004" });
const runtime = new CopilotRuntime({
agents: { default: langGraphAgent },
a2ui: { injectA2UITool: true }, // 启动A2UI 组件 进行组件组装渲染
});
const app = createCopilotEndpoint({
runtime,
basePath: "/api/copilotkit",
});
serve({ fetch: app.fetch, port: 4004 }, () => {
console.log("\u2713 CopilotKit API server running at http://localhost:4004");
});
当启用 A2UI 后,CopilotKit 会自动添加生成结构化 A2UI 输出所需的后端逻辑——您无需手动实现这一流程。
在底层,这一操作是通过两层工具调用来实现的:
当代理决定生成 A2UI 时,会触发一个外部工具调用。这样就能将与 A2UI 相关的逻辑与其他代理行为分离开来。
一个内部工具调用包含了结构化的 A2UI 负载。中间件会拦截这些参数,以实现流处理功能。
生成的输出结果也被记录在了代理的历史记录中,作为工具调用的结果之一。
dynamic schema UI
前端需要引入组件库 frontend/src/catalog 组件声明 + 组件实现 + 导出
A component definition is the contract for a primitive in your catalog:
- a name the agent can reference (like Card, Row, or Text)
- a schema for its props
- and the React component that draws it in your app’s styles
1 | // frontend/src/catalog/definitions.ts |
1 | // frontend/src/catalog/renderers.tsx |
注册
1 | import { StrictMode } from "react"; |
fixed schema UI
固定模式(Fixed Schema)声明式生成式 UI
使用固定模式时,你需要提前设计好 A2UI 组件树——布局、嵌套结构和数据绑定都已预先定义。Agent 的唯一工作就是填充运行时数据。这让你可以最大程度地控制最终 UI,同时仍由 Agent 来决定何时展示以及展示哪些数据。
当你需要为特定场景(例如航班卡片轮播)保持一致、精致的布局,且不需要 Agent 即兴发挥结构时,这种方式非常适用。
构建固定模式最简单的方式是使用 https://a2ui-editor.ag-ui.com/ 编辑器。打开 Composer(组合器)并指定以下提示词。
将ui schema 注册到后端agent 上
1 | from copilotkit import a2ui |
Dynamic vs Fixed: When to use which
| Fixed Schema | Dynamic Schema | |
|---|---|---|
| Layout | Predefined, identical every time 预先定义好的,每次都是相同的 | Agent-generated, varies per request由代理生成,随每个请求而不同 |
| Agent’s role | Fills in data only 仅填充数据 | Chooses components and layout 选择了组件和布局方式 |
| Consistency 一致性 | Maximum最大值 | Varies 各不相同 |
| Flexibility 灵活性 | Minimal — new layouts require code changes 非常少——新的布局需要修改代码 | High — agent adapts to the request 高——代理人能够适应该请求 |
| Best for | Polished, known surfaces (flight cards, invoices) 经过精心处理的、易于识别的表面(如飞行卡片、发票) | Long-tail, exploratory, or internal surfaces 长尾的、探索性的或内部表面 |
在实践中,许多应用程序同时使用两种方案:对于高流量且需要注重品牌形象的页面,使用固定的模式;而对于其他所有页面,则使用动态的模式。
声明式生成式用户界面允许智能体从一系列构建模块中组合出各种界面——这种方式比受控式界面更加灵活,也比自由式界面更加稳定。
A2UI 规范包含了三个核心要素:组件目录(包含组件的定义和渲染方式)、架构设计(组件之间的布局方式),以及数据绑定(运行时的值的传递方式)。
动态模式允许代理实时生成布局——这对于需要长尾布局和探索性界面的情况非常有用。
固定式的架构提供了预定义的布局,代理程序可以将数据填充到这些布局中——这种方式适用于需要呈现精美外观且流量较大的场景。
这两种方法可以在同一个代理中同时存在。
Open Generative UI 开放式
开放式的生成 UI 是最灵活的模式:该工具并不局限于一组预先注册好的组件,也不依赖于固定的或动态生成的声明式架构。
这种灵活性源自 MCP 应用程序。代理可以从 MCP 服务器上获取应用程序工具,并在这些工具符合用户需求时将其打开使用。
你的前端部分充当了主机角色。它无需提前手动编写所有可能的用户界面界面;相反,它只需将聊天运行时与兼容的外部应用程序连接起来即可。
为什么使用开放式用户界面
当用户的请求范围过于广泛,无法用固定的组件库来涵盖时,开放式用户界面就非常有用。
优点
- 极其灵活:该代理能够引导用户体验更丰富的应用程序功能,而不仅仅是简单的内嵌小部件。
- 降低前端耦合度:通过连接到 MCP 服务器,宿主应用程序可以获得新的功能。
- 非常适合用于白板演示、设计工作、计划制定等需要使用工具来完成的任务。
缺点 - 与那些需要手动配置或声明式的方法相比,这种方式对最终的用户界面控制较少。
- 质量取决于所连接的 MCP 应用程序,以及代理程序选择这些应用程序的精准程度。
- 这需要更强的信任机制、权限管理,以及更严格的集成规范。
MCP 应用程序规范
MCP 应用程序是模型上下文协议的扩展,它使得 MCP 服务器能够向支持的设备提供交互式用户界面。
这种架构由三部分组成:
服务器:提供工具和用户界面资源。
HOST:将用户界面嵌入到沙盒中的 iframe 中,并负责代理双方的通信过程
视图:在 iframe 内部运行的应用程序。
一个重要的设计原则是渐进式增强:如果host支持 MCP 应用程序,那么工具会呈现丰富的用户界面;否则,它仍然可以作为普通的 MCP 工具使用,仅提供文本输出。
CopilotKit 负责托管工作——你只需要将其指向一个 MCP 服务器的 URL 地址即可。
the official repository of MCP App examples.
注意:开放生成的用户界面是不可预测的
因为代理在每次请求时都会从零开始生成用户界面,所以结果可能不会完全符合你的预期。你可能需要多次调整提示语,直到得到你想要的效果。
这是完全开放式的生成式用户界面所面临的核心权衡之一:虽然可以获得最大的灵活性,但必须牺牲一致性和可预测性。对于那些需要始终保持可靠性的用户界面来说,采用控制性或声明式的方法更为合适。
1 | import { LangGraphHttpAgent } from "@copilotkit/runtime/langgraph"; |
全栈状态共享
在后端agent 服务中,使用AgentState 声明状态值,和更新tool
1 | from __future__ import annotations |
使用useAgent 可以实时在前端获取后端agent中注册的状态数据
使用useFrontendTool 可以给后端agent 注册tool 进行页面操作
1 | import { useState } from "react"; |




































































































































































)














































