CopilotKit × Mastra:从 agentic-chat 演示看 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
本文以 CopilotKit 官方演示集中 Mastra 集成下的agentic-chat演示为对象,完整讲解 CopilotKit 最简对话界面的三层接线:前端CopilotKitProvider、CopilotChat渲染面、useConfigureSuggestions建议芯片,以及后端 Next.js 路由如何把 Mastra agent 挂接到 CopilotKit 运行时。读完本文,你能掌握在 Next.js 应用中用 Mastra 驱动一个 AG-UI 流式 agent 对话的最小可行架构,并理解演示仓库中 agent 名称注册、resourceId 隔离等支撑该演示可运行的关键实现细节。
演示定位:CopilotKit 的最简对话表面
演示文档(README)把agentic-chat定义为CopilotKit 最简的表面(the simplest CopilotKit surface):一个由 agent 驱动、但不依赖共享状态、工具渲染或生成式 UI 的纯对话界面。它展示三件事:
- 自然对话:在熟悉的聊天界面中与 Copilot 交流;
- 流式响应:助手消息通过 AG-UI 协议逐 token 流式返回;
- 建议芯片(Suggestion Chips):预置的起始建议以可点击的快速操作芯片形式渲染在输入框下方。
文档给出的典型交互方式是点击建议芯片或自行输入提示词,例如:
- "Write a short sonnet about AI"
- "Explain the difference between an LLM and an agent"
- "Give me three ideas for a weekend project"
这三个能力分别对应下面三个前端构建块:Provider 接线、CopilotChat渲染、useConfigureSuggestions建议注册。
前端接线:Provider、Chat 与建议芯片
演示页面入口在 page.tsx,全文仅 24 行,完整代码如下:
"use client"; import React from "react"; import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2"; import { useAgenticChatSuggestions } from "./suggestions"; export default function AgenticChatDemo() { return ( <CopilotKit runtimeUrl="/api/copilotkit" agent="agentic_chat"> <Chat /> </CopilotKit> ); } function Chat() { useAgenticChatSuggestions(); return <CopilotChat agentId="agentic_chat" />; }对照 README 的 "Technical Details" 一节,三个要点在源码中的落点如下:
Provider 接线:runtimeUrl 与 agent 选择
README 指出CopilotKit组件负责把页面连接到运行时,两个关键属性为:
runtimeUrl="/api/copilotkit":指向 Next.js 的 App Router 路由,该路由代理(proxy)到后端 agent(实际实现见 route.ts);agent="agentic_chat":选定运行时中注册的名为agentic_chat的 agent。在 Mastra 集成中,这个名字并不是一个独立注册的 agent,而是路由层通过别名机制解析到 Mastra 的weatherAgent(详见后文"后端代理"一节)。
渲染面:CopilotChat 与 agentId
README 说明CopilotChat渲染完整的聊天 UI,包括输入框、消息列表与流式显示。注意源码中<CopilotChat agentId="agentic_chat" />显式传入了agentId,与 Provider 上的agent属性保持一致——在单个 Provider 下只挂载一个 agent 时二者指向同一个 agent,agentId的作用是在多 agent 或显式挂载场景下消除歧义。
建议芯片:useConfigureSuggestions
建议逻辑单独抽到 suggestions.ts 中的一个自定义 hook:
"use client"; import { useConfigureSuggestions } from "@copilotkit/react-core/v2"; export function useAgenticChatSuggestions() { useConfigureSuggestions({ suggestions: [ { title: "Write a sonnet", message: "Write a short sonnet about AI." }, { title: "Tell me a joke", message: "Tell me a one-line joke." }, { title: "Is 17 prime?", message: "Walk me through whether 17 is prime.", }, ], available: "always", }); }对应 README 中的描述:useConfigureSuggestions注册静态建议,使其以可点击芯片的形式出现在聊天输入下方。从源码可以看出每条建议由title(芯片上显示的文案)和message(点击后实际发送的提示词)组成,二者解耦允许芯片文案短于完整提示词;available: "always"表示建议在任何对话状态下都可用,而非仅在首次进入或无历史消息时显示。README 举例的 "Write a short sonnet about AI" 正是其中一条建议的message,说明文档示例与实现完全一致。
后端代理:单一路由 + agent 别名机制
runtimeUrl指向的/api/copilotkit是整个演示(以及整个 Mastra 集成站点)的运行时入口,位于 route.ts。这一节是 README "Technical Details" 中 "Next.js route that proxies to the agent" 的完整展开。
运行时装配
POST 处理器的核心逻辑是三步:
const runtime = new CopilotRuntime({ agents: getAgents(), }); const copilotHandler = createCopilotRuntimeHandler({ runtime, basePath: "/api/copilotkit", mode: "single-route", }); response = await copilotHandler(req);CopilotRuntime来自@copilotkit/runtime/v2,agents是"agent 名称 → agent 实例"的映射;createCopilotRuntimeHandler以single-route模式工作,即所有 CopilotKit 请求打到/api/copilotkit这一个路径上,由运行时按basePath自行分派;- 路由源码中的注释明确说明了 V2 运行时的角色:Mastra agent 自行驱动 LLM,运行时只在前端与 agent 之间做 AG-UI 事件的代理(broker)。这也正是 README 所说"流式响应经 AG-UI 逐 token 送达"的底层通路。
agentic_chat 如何被解析到 weatherAgent
README 提到agent="agentic_chat"选定的 agent "defined in langgraph.json"——这句话沿用了演示集早期基于 LangGraph(Python)的后端描述;从当前仓库源码看,Mastra 集成目录下并不存在langgraph.json,实际解析发生在路由层:
demoAgentNames常量数组(route.ts 第 40 行起)列出了所有演示请求的 agent 名称,"agentic_chat"是其中第一个。源码注释强调:这个列表就是唯一的 agent 注册表("This list IS the registry"),任何新增演示都必须在此登记,否则运行时会返回 agent-not-found 错误;demoAgentIdOverrides映射表把特定演示别名指向专门的 Mastra agent(如headless-complete→headlessCompleteAgent、reasoning-default→reasoningAgent);agentic_chat不在覆盖表中,因此回退到默认的weatherAgent;buildAgents()通过@ag-ui/mastra的MastraAgent.getLocalAgents/getLocalAgent把 Mastra 实例中的本地 agent 包装成 AG-UI agent,再以mastra-<演示名>形式的独立resourceId绑定到每个演示别名上。
weatherAgent本身的定义在 agents/index.ts:一个使用openai("gpt-4o")模型、挂载get_weather等 7 个工具、并启用 LibSQL 存储支撑的 working memory 的 MastraAgent。对 agentic-chat 演示而言,工具不会被触发——它就只作为对话模型使用,这也印证了 README "最简对话表面"的定位。
为什么每个演示要独占一个 resourceId
源码注释解释了resourceId隔离的动机:Mastra Memory 在提供threadId时要求非空resourceId(而 CopilotKit 运行时总是提供threadId),且getLocalAgents默认对所有本地 agent 套用同一个 resourceId,会让多个演示共享同一个工作记忆桶。因此buildAgents()为每个演示别名分配mastra-<name>形式的独立 resourceId,并对 resourceId 唯一性做了断式校验(重复即抛错),防止跨演示的记忆污染。对 agentic-chat 这样的无状态演示,这一机制只是保证它不会读到其他演示残留的 working memory。
该注册表还受到测试守护:demoAgentNames.parity.test.ts 强制"每个演示页面中agent="…"的字面量都必须出现在demoAgentNames列表中",从两侧(页面声明 ↔ 路由注册)保证一致。
可观测性:三类失败的关联日志
路由层还内置了一套带errorId关联 ID 的错误日志结构,把失败分为setup(响应头写出前的同步失败,如 agent 装配出错,可返回 500 JSON)与stream(头部已刷出后的流中断,只能落日志)两类,并用wrapStreamingResponse包裹流式响应体,确保上游 SSE 循环中的异常不会无声逃逸。对运维者来说,按errorIdgrep 日志即可关联前后两类的失败。这部分属于演示站点的工程质量细节,与 README 描述的对话行为无直接关系,但在排查"聊天无响应"类问题时值得知晓。
端到端数据流小结
把前后端拼起来,agentic-chat 演示的一次完整交互是:
- 用户在
CopilotChat输入提示词(或点击建议芯片触发message发送); CopilotKitProvider 将请求发往runtimeUrl,即/api/copilotkit;- 路由层从
getAgents()缓存中按agent="agentic_chat"解析到别名绑定的 AG-UI agent(底层为weatherAgent); - 运行时以 AG-UI 事件流形式驱动 Mastra agent,agent 调用
openai("gpt-4o")生成回复; - 事件流经
/api/copilotkit的 SSE 响应逐 token 流回前端,CopilotChat实时渲染。
关键文件索引
- 演示 README:演示定位与交互说明;
- page.tsx:Provider 接线与
CopilotChat渲染; - suggestions.ts:
useConfigureSuggestions静态建议注册; - route.ts:运行时路由、agent 注册表与 resourceId 隔离;
- mastra/index.ts:Mastra 实例、LibSQL 存储与本地 agent 集合注册;
- agents/index.ts:
weatherAgent等本地 agent 定义; - demoAgentNames.parity.test.ts:演示页面 agent 名与路由注册表的 parity 测试。
【免费下载链接】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),仅供参考