基于 CopilotKit 与 Mastra 构建 AI 画布应用:AG-UI Canvas Starter 实战指南
基于 CopilotKit 与 Mastra 构建 AI 画布应用AG-UI Canvas Starter 实战指南【免费下载链接】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/CopilotKitCopilotKit 与 Mastra 共同打造了一个以 AG-UI 协议为桥梁的 AI 画布应用模板前端基于 Next.js 与 CopilotKit 渲染可视化卡片网格后端由 Mastra Agent 统一调度工具、记忆与 LLM通过共享状态实现 AI 与 UI 的双向实时同步。阅读本文后你将掌握该模板的完整架构、启动流程、四类交互卡片的字段设计、多步计划与 Human-in-the-Loop 机制并能够基于仓库源码扩展新的卡片类型与前端动作。说明本文所引文件均位于仓库examples/canvas/mastra目录下文中的相对路径以仓库根目录为起点。项目概览Mastra Agent 驱动的交互式画布该模板解决的核心问题是如何让大模型 Agent 真正动手操作一块由结构化数据组成的可视化画布而不是停留在聊天框里输出文字。它提供了一套可直接运行的 Next.js 应用画布上每张卡片由真实数据驱动AI 可以创建、修改、删除卡片用户也可以直接在画布上编辑——两边的修改会通过共享状态实时同步这也是模板中 Bidirectional synchronization 的核心含义。模板的核心能力详见 README包括可视化画布界面无拖拽的响应式网格布局卡片随内容自适应排布四类卡片Project文本 下拉 日期 清单、Entity文本 下拉 多选标签、Note富文本内容区、Chart基于百分比 0-100 的条形指标实时 AI 同步AI Agent 与 UI 画布之间的双向状态同步多步计划AI 可创建并逐步执行计划画布上有可视化进度追踪人工介入HITL需要澄清时 Agent 会智能中断并向用户询问JSON 视图一键在可视化画布与原始 JSON 状态之间切换响应式设计桌面端使用侧边栏聊天移动端自动切换为弹出式聊天Mastra 集成基于 Mastra Agent 框架构建内置记忆Memory管理。从仓库结构看本模板examples/canvas/mastra与同目录下的gemini、langgraph-python、llamaindex、pydantic-ai等变体属于同一系列它们共用同一种画布 Agent 后端的架构思路只是后端 Agent 框架各不相同。环境准备与快速启动前置条件Node.js 18以下任一包管理器pnpm推荐、npm、yarn、bun。注意仓库默认忽略 lock 文件package-lock.json、yarn.lock、pnpm-lock.yaml、bun.lock以避免不同包管理器之间产生冲突。每位开发者应使用自己偏好的包管理器生成自己的 lock 文件并将其从.gitignore中移除。三步启动第一步配置 OpenAI API Key。模板的 Agent 默认使用openai(gpt-4o-mini)见 src/mastra/agents/index.ts当然你可以换成 Mastra 支持的任何模型# 可以使用 Mastra 支持的任何模型 echo OPENAI_API_KEYyour-key-here .env第二步用你偏好的包管理器安装依赖# 使用 pnpm推荐 pnpm install # 使用 npm npm install # 使用 yarn yarn install # 使用 bun bun install第三步启动开发服务器# 使用 pnpm pnpm dev # 使用 npm npm run dev # 使用 yarn yarn dev # 使用 bun bun run dev该命令会并发启动 UI 与 Agent 服务器。从 package.json 的脚本定义可以看到dev实际执行的是next dev --turbopack由于 Agent 直接运行在 Next.js 进程内单进程架构因此不需要单独拉起 Agent 服务这也是 README 中 This will start both the UI and agent servers concurrently 的实现基础。可用脚本一览脚本作用实现命令dev以开发模式同时启动 UI 与 Mastra Agentnext dev --turbopackdev:agent仅启动 Mastra Agent 开发服务器mastra devdev:debug以调试日志级别启动LOG_LEVELdebugLOG_LEVELdebug npm run devbuild构建生产版本next buildstart启动生产服务器next startlint运行 ESLint 代码检查next lint其中dev:debug的设置会被 src/mastra/index.ts 读取const LOG_LEVEL (process.env.LOG_LEVEL as LogLevel) || info进而传递给ConsoleLogger实现更详细的 Mastra 日志输出。开始使用画布应用启动后可以这样与画布互动创建卡片点击 New Item 按钮或直接让 AI 创建。例如Create a new project创建一个新项目Add an entity and a note添加一个实体和一条笔记Create a chart with sample metrics创建一个带示例指标的图表编辑卡片点击任意字段直接编辑或让 AI 来做。例如Set the project field1 to Q1 Planning把项目的 field1 设为 Q1 PlanningAdd a checklist item Review budget添加清单项 Review budgetUpdate the chart metrics更新图表指标执行计划给 AI 下达多步指令例如 Create 3 projects with different priorities and add 2 checklist items to each创建 3 个不同优先级的项目并给每个添加 2 个清单项。AI 会先生成计划再逐步执行并显示可视化进度。查看 JSON使用底部的按钮在可视化画布与 JSON 视图之间切换。前端动作是如何暴露给 Agent 的当你对 AI 说出 Create a new project 时背后是 src/app/page.tsx 中一系列useCopilotAction注册的前端动作在起作用例如createItem、deleteItem、setProjectField1、addProjectChecklistItem、setChartField1Value等。以createItem为例useCopilotAction({ name: createItem, description: Create a new item., available: remote, parameters: [ { name: type, type: string, required: true, description: One of: project, entity, note, chart. }, { name: name, type: string, required: false, description: Optional item name. }, ], handler: ({ type, name }) { /* 通过 setState 更新共享状态 */ }, });这些动作统一设置available: remote即作为远程工具暴露给 Agent 调用。为了让 Agent 更准确地操作字段模板还通过useCopilotAdditionalInstructions注入了一份权威的 FIELD SCHEMA字段 schema 与工具使用提示内容包括project.data 的field1文本、field2可选值为Option A | Option B | Option C空串表示未设置、field3YYYY-MM-DD日期、field4ChecklistItem[]元素结构为{id, text, done, proposed}entity.data 的field1文本、field2下拉、field3已选标签是field3_options的子集、field3_options可用标签note.data 的field1textarea 内容chart.data 的field1Array{id, label, value}value 取[0,100]或空串。同时指令中还约定了当用户要求添加几个时最多创建 2 个并停止工具执行后要重新读取最新状态做校验如果用户明确要求随机/模拟数据可以直接生成并写入。这些提示显著提升了 Agent 调用工具的稳定性。架构总览README 用两张 Mermaid 图清晰地描述了架构这里分别展开。组件拓扑前端由page.tsx中的 Canvas UI、useCopilotAction注册的前端动作、useCoAgent状态管理和CopilotChat组成后端全部集成在 Next.js 进程内包括 CopilotKit Runtimeroute.ts、Mastra Agentagents/index.ts、TypeScript 工具tools/index.ts、Zod SchemaAgentState以及 LLM 模型。数据流时序整个链路的关键在于Agent 与 UI 共享同一份状态用户直接编辑画布同样会通过useCoAgent的setState回流到共享状态从而实现双向同步。前端实现细节Next.js CopilotKit画布管理page.tsx通过useCoAgentAgentState接入名为sample_agent的 Agent并传入initialState定义在 src/lib/canvas/state.ts。页面还维护了一个cachedStateRef当 CopilotKit 尚未同步到非空状态时回退到本地缓存避免 UI 闪空。page.tsx中内置了updateItem、updateItemData、deleteItem、toggleTag、addItem等本地更新函数全部通过setState以不可变方式修改共享状态。特别值得注意的是addItem在planStatus in_progress计划执行中时会对同类型卡片去重——这是为了避免多步计划重复创建同类型卡片。前端动作清单从 page.tsx 中可以完整列出模板注册的前端动作它们遵循set[Type]Field[Number]的命名模式全局setGlobalTitle、setGlobalDescription通用条目setItemName、setItemSubtitleOrDescription、createItem、deleteItemProject 卡片setProjectField1文本、setProjectField2下拉、setProjectField3日期支持自然语言日期并归一化为YYYY-MM-DD、clearProjectField3、addProjectChecklistItem、setProjectChecklistItem、removeProjectChecklistItemEntity 卡片setEntityField1、setEntityField2、addEntityField3、removeEntityField3Note 卡片setNoteField1、appendNoteField1支持换行前缀、clearNoteField1Chart 卡片addChartField1、setChartField1Label、setChartField1Value数值会被夹取到 0-100、clearChartField1Value、removeChartField1。卡片渲染与纯函数更新每种卡片的渲染逻辑集中在 src/components/canvas/CardRenderer.tsxNotereact-textarea-autosize自动增高文本框Chart每条指标由标签输入框 Progress进度条 数值输入框组成数值min0 max100空值用表示Project文本框、下拉Option A/B/C、typedate日期选择器与清单checkbox 文本 删除按钮的组合Entity文本框、下拉与标签胶囊基于field3_options渲染可切换的标签按钮。而字段变更逻辑被提取为纯函数位于 src/lib/canvas/updates.ts如projectAddField4Item新清单项 id 为(field4_id 1)补零成 3 位、projectSetField4ItemDone、chartAddField1Metricvalue 会被Math.max(0, Math.min(100, value))夹取、chartSetField1Value等。这种UI 调用纯函数 → 纯函数返回新数据 → setState的模式让前端逻辑易于测试和复用。布局与主题页面使用CopilotKitCSSProperties设置主题色--copilot-kit-primary-color: #2563eb蓝色并依据useMediaQuery((min-width: 768px))判断桌面端渲染侧边栏CopilotChat移动端渲染CopilotPopup。计划进度面板显示planSteps中每步的状态pending/in_progress/completed/blocked/failed并用旋转的Loader2表示当前步骤。全局样式在 src/app/globals.css组件样式基于 Tailwind CSS 与 shadcn/ui相关组件位于 src/components/ui。应用根组件layout.tsx用CopilotKit runtimeUrl/api/copilotkit agentsample_agent包裹把运行时地址与默认 Agent 注入整个应用。后端实现细节Mastra AgentCopilotKit Runtime 与 AG-UI 集成src/app/api/copilotkit/route.ts 是前后端接线的核心import { CopilotRuntime, ExperimentalEmptyAdapter, copilotRuntimeNextJSAppRouterEndpoint } from copilotkit/runtime; import { MastraAgent } from ag-ui/mastra; import { mastra } from /mastra; const serviceAdapter new ExperimentalEmptyAdapter(); export const POST async (req: NextRequest) { const agents MastraAgent.getLocalAgents({ mastra }); const runtime new CopilotRuntime({ agents }); const { handleRequest } copilotRuntimeNextJSAppRouterEndpoint({ runtime, serviceAdapter, endpoint: /api/copilotkit, }); return handleRequest(req); };MastraAgent.getLocalAgents({ mastra })基于ag-ui/mastra包把 Mastra 实例中的 Agent 暴露为 AG-UI 可调用的远程 Agent。模板还特意在启动时打印可用 Agent 列表console.log([CopilotKit] Available agents:, ...)用于排查 agent not found 问题。注释中也提到这里可以替换成任何 Service Adapter 以获得多 Agent 支持。Agent 定义与记忆配置src/mastra/agents/index.ts 中定义了canvasAgent名称sample_agent模型openai(gpt-4o-mini)可替换为 Mastra 支持的其他模型工具setPlan、updatePlanProgress、completePlan指令You are a helpful assistant managing a canvas of items. Prefer shared state over chat history.优先使用共享状态而非聊天历史记忆Memory开启workingMemoryschema 为AgentState。README 中有一句容易被误解的表述——Memory Configuration: Disabled working memory to prevent stale cached state。从源码看实际代码是开启enabled: true了 working memory 并绑定AgentStateschema。可以推断README 中 Disabled working memory 指的是禁用与 UI 状态无关的通用对话记忆/缓存语义即不要让记忆机制缓存一份与前端不同的陈旧状态而不是关闭 Memory 本身源码中 working memory 恰好承载共享的AgentState。排查状态不同步问题时应检查记忆配置是否会让 Agent 依赖过期的缓存状态。AgentState 的 Zod SchemaAgentState是前后端共享状态的契约export const AgentState z.object({ items: z.array(z.object({ id: z.string().optional() }).passthrough()).default([]), globalTitle: z.string().default(), globalDescription: z.string().default(), lastAction: z.string().default(), itemsCreated: z.number().int().default(0), planSteps: z.array(z.object({ title: z.string(), status: z.enum([pending, in_progress, completed, blocked, failed]), note: z.string().optional(), })).default([]), currentStepIndex: z.number().int().default(-1), planStatus: z.string().default(), });关键细节items使用.passthrough()的宽松对象而不是z.any()——源码注释明确说明这是为了保证能生成合法的 OpenAI 工具 JSON Schema同时为数组元素定义结构。前端 src/lib/canvas/types.ts 中的AgentState、Item、PlanStep等 TypeScript 类型与此 schema 一一对应。Mastra 实例与存储src/mastra/index.ts 创建了 Mastra 实例export const mastra new Mastra({ agents: { sample_agent: canvasAgent }, storage: new LibSQLStore({ url: :memory: }), logger: new ConsoleLogger({ level: LOG_LEVEL }), });存储使用LibSQLStore且为内存模式:memory:意味着重启后对话/状态记录不会持久化生产环境可按需替换为文件或远程 LibSQL 连接。计划执行工具src/mastra/tools/index.ts 通过createTool定义了三个 TypeScript 工具它们与前端planSteps/planStatus/currentStepIndex状态联动支撑多步计划的执行与可视化进度工具id输入输出行为setPlanset_plansteps: string[]步骤标题列表{ initialized: true, steps }初始化计划重置进度并把状态置为in_progressupdatePlanProgressupdate_plan_progressstep_index非负整数、statuspending/in_progress/completed/blocked/failed、可选note{ updated: true, index, status, note }更新单个步骤的状态并可附加说明completePlancomplete_plan无{ completed: true }将计划标记为完成这三个工具本身是纯标记类工具返回字面量真正的状态写入发生在 Agent 依据其返回值更新AgentState时前端则通过useCoAgentStateRender监听plan-final-summary节点在planStatus为completed/failed时渲染折叠的总结面板显示每步完成/失败状态。这套设计把计划的业务语义交给 Agent 框架把计划的视觉表达交给 CopilotKit职责清晰。卡片字段 Schema 与状态模型四种卡片的数据结构在 types.ts 中统一定义前端与 Agent 侧保持一致卡片类型字段说明Projectfield1(text)、field2(select)、field3(date)、field4(checklist)field4为ChecklistItem[]元素{id, text, done, proposed}field4_id是清单项自增计数器Entityfield1(text)、field2(select)、field3(tags)、field3_options(available tags)field3是已选标签string[]必须为field3_options的子集Notefield1(textarea content)可选的富文本内容Chartfield1(array of metrics)每条指标为{id, label, value}value为 0-100 或空串field1_id为指标自增计数器Item的通用结构为{ id, type, name可编辑标题, subtitle标题下的副标题, data }。defaultDataFor(type)在 state.ts 中实现为每种卡片生成默认数据其中 Entity 的默认标签选项是[Tag 1, Tag 2, Tag 3]。共享状态AgentState除items外还包含globalTitle、globalDescription画布全局标题与描述、lastAction最近一次操作记录如created:0001/deleted:0001/not_found:0001、itemsCreated已创建条目计数用于生成 4 位补零 id、planSteps、currentStepIndex与planStatus。自定义与扩展指南添加新卡片类型在 src/lib/canvas/types.ts 中定义数据 schema把新类型加入CardType联合类型在 src/components/canvas/CardRenderer.tsx 中编写渲染逻辑更新 src/mastra/agents/index.ts 中 Agent 的指令告知 AI 新卡片的字段语义在 src/app/page.tsx 中添加对应的前端动作遵循set[Type]Field[Number]命名模式并同步更新useCopilotAdditionalInstructions注入的 FIELD SCHEMA 与工具提示。修改现有卡片字段定义位于 Agent 的指令instructions中UI 组件位于CardRenderer.tsx字段变更的纯函数位于 src/lib/canvas/updates.ts前端动作遵循set[Type]Field[Number]模式例如setProjectField1、setChartField1Value。配置 AgentAgent 定义src/mastra/agents/index.ts工具定义src/mastra/tools/index.ts记忆设置可在 Agent 配置中调整更换模型只需修改model属性例如改为其他 OpenAI 模型或 Mastra 支持的任何模型。样式调整全局样式src/app/globals.css组件样式使用 Tailwind CSS shadcn/ui 组件src/components/ui主题色通过 CSS 自定义属性--copilot-kit-primary-color修改页面中默认值为#2563eb。排障指南Agent 连接问题如果看到 Im having trouble connecting to my tools请依次检查.env中的 OpenAI API Key 是否正确设置Agent 是否在 src/mastra/index.ts 中正确注册key 为sample_agent服务器是否成功启动检查终端输出route.ts会打印[CopilotKit] Available agents:列表。状态同步问题如果画布与 AI 显示的内容不同步打开浏览器控制台检查报错确认所有前端动作都已正确注册在page.tsx中均有对应的useCopilotAction确认 Agent 的记忆配置不会缓存陈旧状态牢记上文对 working memory 的分析它承载的是共享AgentState而非一份独立的过期副本。开启调试日志npm run dev:debug这会设置LOG_LEVELdebug让 Mastra 输出更详细的日志。常见问题速查Agent not found检查sample_agent是否已注册在 src/mastra/index.ts 中工具执行错误确保 src/mastra/tools/index.ts 中的工具 schema 与前端期望一致尤其是planSteps的状态枚举值TypeScript 错误运行npm run build检查类型问题。小结这个 Starter 展示了 CopilotKit 与 Mastra 组合下的一个完整范式用 AG-UI 协议把 CopilotKit 前端与 Mastra Agent 后端连接起来以共享的AgentState为单一事实来源让 Agent 通过前端动作和 TypeScript 工具双通道操作可视化画布。理解它的关键抓手有三个useCoAgentuseCopilotAction构成的前端状态桥、route.tsMastraAgent.getLocalAgents构成的 AG-UI 运行时桥、以及 ZodAgentStateschema 构成的前后端数据契约。把握住这三层你就能在此基础上扩展出自己的 AI 画布应用。提示该模板部分功能仍处于活跃开发中可能尚未完全按预期工作如遇问题可在 CopilotKit 仓库中提交 issue 反馈。【免费下载链接】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),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →