news 2026/9/13 2:51:06

在 CopilotKit 中实现开放生成式 UI(Open-Ended Generative UI):以 CrewAI Conversational Flows 集成为例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 CopilotKit 中实现开放生成式 UI(Open-Ended Generative UI):以 CrewAI Conversational Flows 集成为例

在 CopilotKit 中实现开放生成式 UI(Open-Ended Generative UI):以 CrewAI Conversational Flows 集成为例

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

开放生成式 UI(Open-Ended Generative UI)是 CopilotKit 生成式 UI 能力中自由度最高的一种形态:Agent 不再局限于预定义的工具渲染器,而是直接以 HTML + CSS 编写界面,再由前端把这段"代理编写的网页"挂载进沙箱 iframe 中运行。本文以仓库中 CrewAI Conversational Flows 集成的 QA 文档 open-gen-ui.md 为骨架,结合演示源码、运行时路由与 Playwright 端到端测试,完整梳理"最小化开放生成式 UI"的启用方式、运行链路、安全模型与自动化验证手段。读完本文,你将能够在自己的 CopilotKit 应用中用几行配置复刻这一能力,并理解其底层原理。

从 QA 检查清单看核心验收标准

该 QA 文档是全仓库自动化验证体系的组成部分,它以检查清单的形式规定了开放生成式 UI 最小演示必须通过的验收标准:

  1. 导航到/demos/open-gen-ui页面;
  2. 点击"3D axis visualization (model airplane)"建议(suggestion pill);
  3. 验证 Agent 流式产出open-generative-uiactivity,并且沙箱 iframe 渲染出可视化内容;
  4. 验证沙箱 UI自动运行动画,无需任何用户交互

四条标准恰好对应开放生成式 UI 的四个关键特征:零预定义工具的聊天入口Agent 生成的 HTML/CSS 走 activity 通道回传沙箱 iframe 渲染、以及自运行(self-running)可视化。仓库中同时存在"最小化(minimal)"与"进阶(advanced)"两个 demo 目录,本文主线聚焦 QA 文档对应的 minimal 版本,最后补充 advanced 版本的能力延伸。

运行链路:从建议 pill 到沙箱 iframe

结合演示源码 page.tsx、运行时路由 route.ts 和测试注释,整条链路可以归纳为:

  1. 用户点击建议 pill(或输入提示词),CopilotChat把消息发给 Agent;
  2. Agent 端流式返回一个generateSandboxedUi工具调用,内含 LLM 自主编写的csshtmlinitialHeightplaceholderMessages
  3. 运行时中间件(Runtime Middleware)监听该工具调用,把它转换为open-generative-uiactivity 事件;
  4. 前端内置的OpenGenerativeUIActivityRenderer接收该事件,将 HTML + CSS 组合进srcdoc,挂载到<iframe sandbox="allow-scripts">中;
  5. 由于该活动渲染器由CopilotKitProvider自动注册,页面无需注册任何自定义工具渲染器。

正如 page.tsx 注释所述:"No custom sandbox functions, no custom tools — just chat",这是该形态与声明式生成式 UI(依赖前端预先注册的工具渲染器)最本质的区别:界面结构由 Agent 当场编写,前端只负责安全地执行它

最小化前端:一个 Provider 配置就够

/demos/open-gen-ui的页面代码极为精简,完整的前端配置如下:

// src/app/demos/open-gen-ui/page.tsx(节选) "use client"; import React from "react"; import { CopilotKit } from "@copilotkit/react-core/v2"; import { VISUALIZATION_DESIGN_SKILL } from "./design-skill"; import { Chat } from "./chat"; export default function OpenGenUiDemo() { return ( <CopilotKit runtimeUrl="/api/copilotkit-ogui" agent="open-gen-ui" openGenerativeUI={{ designSkill: VISUALIZATION_DESIGN_SKILL }} > <div className="flex justify-center items-center h-screen w-full"> <div className="h-full w-full max-w-4xl flex flex-col p-3"> <Chat /> </div> </div> </CopilotKit> ); }

三个关键配置项:

  • runtimeUrl="/api/copilotkit-ogui":指向一个专用运行时路由。该 demo 刻意把开放生成式 UI 与默认运行时隔离,原因见下一节。
  • agent="open-gen-ui":指定要连接的 Agent 标识,必须与运行时路由中注册的 Agent 名称一致。
  • openGenerativeUI={{ designSkill: VISUALIZATION_DESIGN_SKILL }}:向 LLM 注入"视觉设计技能"提示词。把openGenerativeUI传给CopilotKit的同时,也激活了内置的OpenGenerativeUIActivityRenderer

聊天本体更简单,chat.tsx 只做两件事:调用useOpenGenUISuggestions()注入建议 pill,然后渲染一个普通的CopilotChat

import { CopilotChat } from "@copilotkit/react-core/v2"; import { useOpenGenUISuggestions } from "./suggestions"; export function Chat() { useOpenGenUISuggestions(); return <CopilotChat agentId="open-gen-ui" className="flex-1 rounded-2xl" />; }

专用运行时路由:开放生成式 UI 的隔离策略

前端指向的/api/copilotkit-ogui是一个独立于默认运行时的路由。源码 route.ts 给出了明确的隔离理由:

因为openGenerativeUI运行时标志会在探测(probe)响应上全局置位openGenerativeUIEnabled: true,否则会影响默认运行时上每个 demo 各自的工具注册。

也就是说,开放生成式 UI 是一个运行时级全局开关,打开后会对所有经由该路由的 Agent 生效;为了不干扰同仓库其他 demo 的工具注册,仓库将其隔离到独立路由。核心配置如下:

// src/app/api/copilotkit-ogui/route.ts(节选) const AGENT_URL = process.env.AGENT_URL || "http://localhost:8000"; function createAgent() { return new HttpAgent({ url: `${AGENT_URL}/conversational_flows/frontend-tools`, }); } const agents: Record<string, AbstractAgent> = { "open-gen-ui": createAgent(), "open-gen-ui-advanced": createAgent(), }; export const POST = async (req: NextRequest) => { const copilotHandler = createCopilotRuntimeHandler({ runtime: new CopilotRuntime({ agents, openGenerativeUI: { agents: ["open-gen-ui", "open-gen-ui-advanced"], }, }), basePath: "/api/copilotkit-ogui", mode: "single-route", }); return await copilotHandler(req); };

值得注意的细节:

  • Agent 通过HttpAgent(来自@ag-ui/client)桥接到后端的 CrewAI 服务端点/conversational_flows/frontend-tools,默认地址http://localhost:8000,可用环境变量AGENT_URL覆盖;
  • openGenerativeUI: { agents: [...] }明确声明哪些 Agent 启用开放生成式 UI,这是运行时中间件把generateSandboxedUi流转换为open-generative-uiactivity 的触发条件;
  • mode: "single-route"表示该路由采用单路由处理模式。

建议 pill:可预测的入口设计

chat.tsx 调用的useOpenGenUISuggestions()定义在 suggestions.ts,提供了四个 QA 文档中点名的基础建议:

标题(title)消息(message)
3D axis visualization3D axis visualization (model airplane)
How a neural network worksHow a neural network works
Quicksort visualizationQuicksort visualization
Fourier: square wave from sinesFourier: square wave from sines

建议的实现通过useConfigureSuggestions注入,available: "always"表示建议常驻。源码注释揭示了一个工程细节:message字符串同时充当 aimock 夹具(fixture)的确定性匹配键。在自动化测试中,夹具数据d5-all.json会先于通用兜底夹具加载,因此"first-match-wins"的顺序能让每个 pill 点击命中稳定的generateSandboxedUi工具调用,而不会落入对"hi"的通用兜底回复。这意味着pill 文案的修改必须同步维护夹具键,否则测试会退化。

designSkill:用提示词约束 Agent 的"网页设计品味"

QA 文档强调的可视化必须"自动动画",其保障机制之一是 design-skill.ts 中定义的VISUALIZATION_DESIGN_SKILL。这段提示词替换了默认的 shadcn 风格设计技能,作为generateSandboxedUi工具的 Agent 上下文注入,对输出提出了硬性约束,其中与本 QA 场景强相关的要点包括:

  • 渲染方式:几何内容优先使用内联 SVG 或<canvas>,禁止用大量<div>拼形状;建议 600×400 内容区、16-24px 边距,用viewBox+preserveAspectRatio保证缩放;
  • 动画方式:优先 CSS@keyframes+transition而非 JSsetInterval;循环动画用animation-iteration-count: infinite;必须用 JS 时使用requestAnimationFrame;用animation-delay错开相关元素;
  • 教学性:每个坐标轴要有标签、每个色系要有图例、要有文字标注(如 "Input layer"、"Forward pass")、顶部要有标题与副标题;
  • 调色板:规定了语义化配色(主强调色 indigo#6366f1、成功色 emerald#10b981、警示色 amber#f59e0b、错误色 rose#ef4444、中性 slate#64748b等);
  • 自运行约束:本 minimal 场景没有宿主侧沙箱函数,明确禁止fetchXHRlocalStoragecookie以及Websandbox.connection.remote调用,场景必须自行循环或自动推进——这正是 QA 第 4 条"自动动画、无需交互"的提示词层保证;
  • 输出契约:按顺序产出initialHeight(典型 480-560)、2-3 行placeholderMessages、完整的csshtml
  • 可访问性:文本对比度 ≥ 4.5:1,不单靠颜色区分序列。

从代码结构可以推断,这套"设计技能"机制是开放生成式 UI 控制输出质量的主要杠杆:不写死界面,但通过提示词约束界面的结构与风格

沙箱渲染与安全模型

QA 第 3 条要求验证"沙箱 iframe 渲染出可视化",其安全实现细节在测试注释中交代得最清楚:

  • 渲染器把 Agent 编写的 HTML + CSS 组合进srcdoc属性(测试优先断言srcdoc非空,src作为回退);
  • iframe 只授予sandbox="allow-scripts"不授予allow-same-origin。由于沙箱 iframe 处于 null origin,宿主页面无法通过contentFrame()直接窥探 iframe 内部 DOM——测试因此只断言"宿主成功填入了 iframe",而不检查内部 HTML 的具体正确性;
  • 这样既允许 Agent 产出的脚本在 iframe 内运行(实现自运行动画),又切断了脚本触达宿主页面 DOM 与存储的路径,构成了"不可信内容在可信边界内执行"的隔离模型。

自动化验证:Playwright 端到端测试

QA 文档的验收标准由 open-gen-ui.spec.ts 自动化落实。测试文件开头的注释明确标注了对应的 QA 参考、演示源码与 aimock 夹具路径,形成"QA 文档 → 演示源码 → 夹具 → e2e 测试"的完整可追溯链。

测试覆盖两个层次:

1. 页面加载与 pill 可见性——断言聊天输入框可见,并逐一断言四个建议 pill 可见(pill 标题与suggestions.ts逐字对齐):

const expected = [ "3D axis visualization", "How a neural network works", "Quicksort visualization", "Fourier: square wave from sines", ];

2. 点击 pill → iframe 挂载——测试辅助函数assertPillRendersIframe点击 pill 后,等待iframe[sandbox*="allow-scripts"]出现,再用轮询断言srcdoc(首选)或src存在且非空。四个 pill(Fourier、3D axis、Neural network、Quicksort)各有一条独立用例,整套用例超时上限为 120 秒。

这里还有两个工程细节值得借鉴:

  • 断言粒度刻意保守:"Renders something" 只意味着宿主成功填充了 iframe,内部 HTML 是否正确不属于本测试范围——因为 Agent 生成的 HTML 每次运行都可能不同,无法做 DOM 级快照断言;
  • aimock 优先级:夹具d5-all.jsonfeature-parity.json之前加载,其 first-match-wins 顺序会优先命中与 pillmessage精确匹配的高优先级条目,从而稳定产出generateSandboxedUi工具调用。

能力延伸:sandboxFunctions 让沙箱 UI 调用宿主能力

QA 文档针对的是 minimal 形态(无宿主侧函数),但同目录的兄弟文档与源码展示了同一条管线的进阶能力,可作为理解完整能力边界的参照。进阶 demo open-gen-ui-advanced/page.tsx 通过向CopilotKit传入openGenerativeUI={{ sandboxFunctions: [...] }},把宿主函数"桥接"进 Agent 生成的 iframe。

以 sandbox-functions.ts 中的evaluateExpression为例,宿主函数遵循"名称 + 描述 + Zod 参数 Schema + handler"的结构:

{ name: "evaluateExpression", description: "Safely evaluate a basic arithmetic expression on the host page and return the numeric result.", parameters: z.object({ expression: z.string().describe("An arithmetic expression, e.g. '12 * (3 + 4.5)'"), }), handler: async ({ expression }: { expression: string }) => { if (!/^[\d+\-*/().\s]+$/.test(expression)) { return { ok: false, error: "Unsupported characters in expression." }; } // ... return { ok: true, value }; }, }

这些函数的名称、描述与 Zod 派生 JSON Schema 会注入 Agent 上下文,使其在编写 HTML/JS 时知道有哪些可用的"桥";生成的 iframe 内脚本通过Websandbox.connection.remote.<name>(args)调用,处理器运行在宿主页面,返回值回传给 iframe 内的调用方。进阶 e2e 测试 open-gen-ui-advanced.spec.ts 甚至驱动 iframe 内按钮,验证宿主日志(带[open-gen-ui/advanced]前缀)与 iframe 输出元素,形成完整的"iframe → 宿主 → iframe"往返验证。

实践要点与注意事项

综合 QA 文档、源码与测试,在 CopilotKit 中落地开放生成式 UI 时有几个值得注意的工程要点:

  1. 运行时开关是全局的openGenerativeUI会在探测响应上全局置位,与多个 demo 共享一个运行时路由时,应像本仓库一样为开放生成式 UI 单独开辟路由;
  2. 前端与运行时必须同时开启:前端CopilotKitopenGenerativeUI(激活内置活动渲染器),运行时CopilotRuntimeopenGenerativeUI.agents(激活流转换中间件),两者缺一不可;
  3. Agent 标识要一致:前端agent/CopilotChatagentId与运行时路由中注册的 Agent 名称(及openGenerativeUI.agents列表)必须对齐;
  4. 设计技能是输出质量的抓手:需要特定风格(教育可视化、数据看板、计算器等)时,通过openGenerativeUI.designSkill覆盖默认设计技能,用提示词约束结构、动画、配色与自运行行为;
  5. 自动化验证的边界:由于 Agent 输出不可枚举,e2e 断言应聚焦"iframes 挂载 + 非空 srcdoc"这类管线级结果;需要确定性输入时,可借助 aimock 夹具让建议文案命中稳定的工具调用。

QA 文档四行检查清单背后,是"前端最小配置 + 运行时全局标志 + 提示词约束输出 + 沙箱隔离执行 + e2e 自动化验收"一整套工程闭环。参考本仓库的 minimal 与 advanced 两个 demo 及其测试,可以在自己的 CopilotKit 应用中快速复现并安全地扩展这一能力。

【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 2:49:46

The Castle题解:Flood Fill、位掩码与拆墙优先级全解析

最近集中刷《信息学奥赛一本通》的搜索专题&#xff0c;做到 1250 The Castle 这题时&#xff0c;我忍不住给这题盖了个“狠”字。第一眼看上去就是个标准 Flood Fill 连通块计数题&#xff0c;把房间数和最大房间求出来就算完&#xff0c;结果第三问在输出拆墙方案时&#xff…

作者头像 李华
网站建设 2026/9/13 2:49:42

Python构建智能膳食分析系统:技术实现与应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 2:49:33

深度学习车牌识别系统实战:从YOLO检测到LPRNet字符识别

简介&#xff1a;基于深度学习的车牌识别Python项目&#xff0c;专为课程设计与项目实战打造&#xff0c;面向希望掌握计算机视觉与深度学习完整流程的开发者。系统覆盖车牌定位、字符分割、字符识别全流程&#xff0c;结合OpenCV高斯模糊与Sobel算子增强特征&#xff0c;借助T…

作者头像 李华
网站建设 2026/9/13 2:47:04

四川土壤类型Shp数据处理全流程:从文件结构到空间布点

简介&#xff1a;四川土壤类型空间分布标准矢量数据以shapefile格式组织&#xff0c;面向GIS、土壤与农业生态领域的研究者、规划人员和高校师生&#xff0c;用于土壤类型空间查询、专题制图和区域分析。数据依据1:400万中国土壤图编制&#xff0c;采用三位数字编码标识土类和亚…

作者头像 李华