CopilotKit 聊天界面插槽(Slots)定制实战指南:以 LangGraph(Python)集成中的 chat-slots Demo 与 QA 测试为蓝本

发布时间:2026/9/13 8:20:04
CopilotKit 聊天界面插槽(Slots)定制实战指南:以 LangGraph(Python)集成中的 chat-slots Demo 与 QA 测试为蓝本 CopilotKit 聊天界面插槽Slots定制实战指南以 LangGraphPython集成中的 chat-slots Demo 与 QA 测试为蓝本【免费下载链接】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 开源仓库中 LangGraphPython集成的chat-slots演示与 QA 文档展开系统讲解如何通过 CopilotKit 的插槽Slot系统对CopilotChat进行组件级定制以及如何使用 Playwright 端到端测试对定制结果做逐项验收。读完本文你将掌握插槽系统的三级定制机制、五个根级插槽与嵌套插槽的注册方式、useConfigureSuggestions建议胶囊的用法并能独立复现与验证一个欢迎屏 免责声明 助手消息容器完全自绘的聊天界面。一、Demo 定位一个刻意无业务的 UI 定制演示chat-slots是 showcase/integrations/langgraph-python 集成中的一个前端演示单元。在 manifest.yaml 中它被登记为名称Chat Customization: Slots描述Customize CopilotChat via its slot system路由/demos/chat-slots重点文件src/agents/main.py、src/app/demos/chat-slots/page.tsx、src/app/demos/chat-slots/slot-wrappers.tsx、src/app/api/copilotkit/route.ts这个 Demo 的关键设计是底层 Agent 是一个中立的助手helpful, concise assistant无前端工具、无 Agent 工具整个演示只聚焦于前端插槽定制不涉及任何业务逻辑。这样 QA 与读者可以纯关注 UI 定制行为本身而不会被工具渲染、生成式 UI 等噪音干扰。二、前置条件让 Demo 可被访问与验证根据 chat-slots.md 的 Prerequisites运行该 QA 前需要满足Demo 已部署且在 dashboard 宿主机上可通过/demos/chat-slots访问Agent 后端健康可通过/api/health或/api/copilotkit的 GET 请求确认OPENAI_API_KEY已在 Railway 上配置LANGGRAPH_DEPLOYMENT_URL指向一个 LangGraph 部署该部署暴露中立的sample_agent图且该图被注册到chat-slots这个 agent 名称下特别说明本 Demo 的每个自定义插槽都带有data-testid属性QA 中以这些属性作为主选择器。后端注册机制agent 名称与图的绑定注册到chat-slotsagent 名称在源码中的具体实现位于 src/app/api/copilotkit/route.tsconst neutralAssistantCells [ human_in_the_loop, shared-state-read, shared-state-write, prebuilt-sidebar, prebuilt-popup, chat-slots, // ← 本 Demo chat-customization-css, headless-simple, ]; const agents: Recordstring, LangGraphAgent {}; for (const name of neutralAssistantCells) { agents[name] createAgent(); // 默认 graphId sample_agent }其中createAgent()使用new LangGraphAgent({ deploymentUrl, graphId, langsmithApiKey, assistantConfig })并将recursion_limit默认设为 100LangGraph 默认 25这里在 assistantConfig 中显式烘焙保证每次 run 都携带。所有共享中立图的单元各自拥有独立注册名使每个单元的前端插槽注册作用域彼此隔离——这正是 Demo 前置条件所描述的架构。该路由的 GET 同时充当健康探针返回langgraph_url、langgraph_status以及OPENAI_API_KEY是否设置的诊断信息对应 QA 中的健康检查步骤。三、核心概念CopilotChat 的插槽Slot体系在进入 QA 步骤前先明确插槽系统的底层模型。仓库文档 custom-look-and-feel/slots.mdx 给出了权威定义每一个 CopilotKit 聊天组件都由可组合的插槽构成——插槽是命名子组件可被单独覆盖且插槽是递归的可以任意深度下钻到嵌套子组件。定制有三个层级Tailwind 类传入类字符串与默认组件类合并Props 覆盖传入对象覆盖默认组件的特定 props如className、data-testid、事件处理器自定义组件传入自己的 React 组件完全替换插槽。在CopilotChat/CopilotSidebar/CopilotPopup上的根级插槽如下表插槽说明messageView消息列表容器scrollView带自动滚动行为的滚动容器input带发送/转写控件的文本输入区suggestionView消息下方的建议胶囊welcomeScreen初始空状态屏传false可禁用CopilotSidebar与CopilotPopup额外拥有header弹窗头部栏与toggleButton开合切换按钮。四、源码剖析chat-slots 页面如何注册插槽Demo 入口 page.tsx 展示了完整的插槽注册模式。整体结构如下CopilotKit runtimeUrl/api/copilotkit agentchat-slots div classNameh-full w-full max-w-5xl Chat / /div /CopilotKitruntimeUrl/api/copilotkit指向上一节分析的运行时路由agentchat-slots与后端注册名对应聊天容器被限制在max-w-5xl、满视口高度内居中与 QA 中居中聊天界面max-width 5xl满视口高度的描述一致。Chat()内部将所有插槽覆盖收敛为局部变量再传给CopilotChatconst welcomeScreen makeSlotOverridetypeof CopilotChatView.WelcomeScreen(CustomWelcomeScreen); const input { textArea: makeSlotOverridetypeof CopilotChatInput.TextArea(CustomTextArea), sendButton: makeSlotOverridetypeof CopilotChatInput.SendButton(CustomSendButton), disclaimer: makeSlotOverridetypeof CopilotChatInput.Disclaimer(CustomDisclaimer), addMenuButton: makeSlotOverridetypeof CopilotChatInput.AddMenuButton(CustomAddMenuButton), toolsMenu: [{ label: Demo tool (no-op), action: () {} }], }; const messageView { assistantMessage: makeSlotOverridetypeof CopilotChatAssistantMessage(CustomAssistantMessage), userMessage: makeSlotOverridetypeof CopilotChatUserMessage(CustomUserMessage), reasoningMessage: makeSlotOverridetypeof CopilotChatReasoningMessage(CustomReasoningMessage), cursor: CustomCursor, }; const suggestionView { container: CustomSuggestionContainer, suggestion: CustomSuggestion }; const scrollView { scrollToBottomButton: CustomScrollToBottomButton, feather: CustomFeather }; return ( CopilotChat agentIdchat-slots classNameh-full rounded-2xl border ... welcomeScreen{welcomeScreen} input{input} messageView{messageView} suggestionView{suggestionView} scrollView{scrollView} / );几个值得注意的实现细节makeSlotOverride集中做类型断言slot-overrides.snippet.tsx的注释解释了为什么需要as unknown as typeof X断言——wrapper 组件与WithSlots类型结构兼容但名义上不完全一致集中封装在一个命名 helper 中可避免断言散落各处。input同时接受插槽覆盖与CopilotChatInput的其余 props代码中种子化toolsMenu是为了让addMenuButton插槽有渲染的理由该插槽仅在设置了onAddFile或toolsMenu时渲染。scrollView.feather的默认实现是空 div因此 Demo 自绘了可见渐变层并附带可点击复制徽标让插槽肉眼可见。教学用精简片段源码中的 slot-overrides.snippet.tsx 是仅供文档展示、不参与运行的 teaching extract它剥离了生产 Demo 中十几处插槽同时注册的噪音只保留三个最小教学示例并配以region[...]/endregion[...]标记供文档引用const welcomeScreen CustomWelcomeScreen as unknown as typeof CopilotChatView.WelcomeScreen; const messageView { assistantMessage: CustomAssistantMessage as unknown as typeof CopilotChatAssistantMessage, }; const input { disclaimer: CustomDisclaimer as unknown as typeof CopilotChatInput.Disclaimer, }; return { welcomeScreen, messageView, input };这就是三个核心插槽的最小形态也是阅读后续 QA 步骤时的对照参考。五、欢迎屏插槽welcomeScreen的定制与验证实现嵌套子插槽的示例slot-wrappers.tsx 中CustomWelcomeScreen接收input与suggestionView两个元素由CopilotChatView以 props 形式注入并嵌套渲染CustomWelcomeMessage子插槽——这正是文档所说插槽可以嵌套的实例export function CustomWelcomeScreen({ input, suggestionView }) { return ( SlotMarker colorindigo labelWelcomeScreen classNameflex-1 m-3 div>export function useChatSlotsSuggestions() { useConfigureSuggestions({ suggestions: [ { title: Write a sonnet, message: Write a short sonnet about AI. }, { title: Tell me a joke, message: Tell me a short joke. }, ], available: always, }); }文件头注释还澄清了一个值得注意的细节本 Demo 绑定的是中立的sample_agent图纯ChatOpenAI无 Responses API、无推理配置因此不会发出 AG-UI 的REASONING_MESSAGE_*事件——messageView.reasoningMessage插槽虽已包裹但在本 Demo 中保持休眠Show reasoning 相关演示位于/demos/reasoning-default与/demos/reasoning-custom。QA 验证要点suggestionView插槽中渲染两条建议胶囊标题逐字匹配Write a sonnet 与 Tell me a joke点击 Tell me a joke会发送消息 Tell me a short joke.且 10 秒内出现助手文本响应。七、免责声明插槽input.disclaimer的定制与验证实现欢迎态之后才可见CustomDisclaimer同样在 slot-wrappers.tsx 中定义渲染于聊天输入框下方export function CustomDisclaimer(props) { return ( SlotMarker coloryellow labelInput.Disclaimer classNamemx-auto my-1.5 div {...props}>export function CustomAssistantMessage(props: CopilotChatAssistantMessageProps) { return ( SlotMarker coloremerald labelMessageView.AssistantMessage classNamemy-3 CopilotChatAssistantMessage {...props} / /SlotMarker ); }QA 文档描述的自定义容器视觉特征indigo 色调卡片背景bg-indigo-50/60、indigo 边框border-indigo-200、左上角绝对定位 slot 徽标来自页面最终的组合样式。QA 验证要点助手响应到达后助手消息被自定义容器包裹data-testidcustom-assistant-message具有上述卡片特征用户消息气泡不被包裹用户消息使用默认样式——这是插槽粒度隔离的直接证据发送第二条提示Write a one-line sonnet后第二个助手响应同样被包裹证明插槽对每一轮生效而非仅首轮。九、SlotMarker让每个插槽路径可见可复制的实现机制QA 中反复提到的slot 徽标与悬停显示插槽路径其底层实现是 slot-marker.tsx 中的SlotMarker组件每个标记输出data-slot-label插槽路径属性——这正是 E2E 测试将其视为插槽覆盖是否生效的规范信号的原因使用静态类查找表SLOT_COLORS14 种颜色注释明确指出不能动态拼接 Tailwind 类名如border-${color}-400否则 Tailwind v4 的源码扫描器在构建期找不到这些类徽标默认opacity-0仅在悬停且没有任何后代标记同时被悬停时显示通过:not(:has(.slot-marker:hover))谓词隔离嵌套标记避免嵌套结构下所有标签一起点亮点击徽标将插槽路径复制到剪贴板navigator.clipboard.writeText并短暂显示 Copied 状态。整个 Demo 因而被戏称为 Slot Atlas插槽图谱每个可覆盖插槽都包裹在虚线、彩色编码的标记中开发者一眼就能看出什么可定制、定制点在哪里。十、E2E 测试把 QA 步骤固化为可回归的断言QA 文档中的每一条手测步骤在仓库中都对应 Playwright 自动化测试 tests/e2e/chat-slots.spec.ts覆盖了四个测试用例欢迎屏插槽首屏渲染同时断言custom-welcome-screen与嵌套的custom-welcome-message可见——注释明确说明同时断言两者可防止意外回退到默认 CopilotChat 欢迎页两条建议胶囊逐字渲染通过[data-testidcopilot-suggestion]过滤文本 Write a sonnet 与 Tell me a joke超时 15 秒点击建议后助手消息被自定义容器包裹点击 Tell me a joke 后等待[data-slot-labelMessageView.AssistantMessage]可见超时 45 秒自定义免责声明在首条消息后渲染通过发送按钮而非 textarea 回车键——注释指出该部署上回车偶发丢提交发送消息随后断言助手插槽标记与custom-disclaimer均可见第二轮同样被包裹使用expect.poll等待首轮流式响应文本稳定2 秒无新内容再发第二轮断言自定义包裹的助手消息数量 ≥ 2。测试注释还透露了 QA 文档未明说的细节该集成使用 aimock fixture 消息保证响应确定性并断言流式完成后输入框退出 responding 状态。十一、完整 QA 测试步骤清单手测验收手册以下内容直接继承自 chat-slots.md作为完整的手测验收清单1. 基本功能导航到/demos/chat-slots验证页面在 3 秒内渲染出居中的聊天界面max-width 5xl、满视口高度验证自定义欢迎屏可见data-testidcustom-welcome-screen取代默认欢迎页验证嵌套的welcomeMessage子插槽在欢迎屏内渲染data-testidcustom-welcome-message正文为 Hover any region to see its slot path · click the badge to copy验证欢迎卡包裹默认聊天input元素及其下方suggestionView行两者均由 CopilotChatView 以 props 传入。2. 功能专项检查欢迎屏插槽welcomeScreen确认欢迎卡显示可悬停的 SlotMarker 徽标indigo/violet 渐变环与默认 CopilotChat 欢迎页视觉区分确认默认 CopilotChat 欢迎标题未渲染自定义卡片完全替换。建议胶囊useConfigureSuggestions验证suggestionView插槽中输入框下方渲染两条建议胶囊标题逐字匹配Write a sonnet、Tell me a joke点击 Tell me a joke验证发送消息 Tell me a short joke.且 10 秒内出现助手文本响应。免责声明插槽input.disclaimer——首条消息后可见发送首条消息后验证自定义免责声明渲染在聊天输入框下方data-testidcustom-disclaimer包含小徽标文字 slotindigo 背景、小写加粗正文 Custom disclaimer injected viainput.disclaimer.其中input.disclaimer为等宽字体验证默认 CopilotChat 免责声明文本如有不出现——自定义免责声明将其替换。助手消息插槽messageView.assistantMessage助手响应到达后验证助手消息被自定义容器包裹data-testidcustom-assistant-message具有indigo 色调卡片背景浅色模式下bg-indigo-50/60indigo 边框border-indigo-200左上角绝对定位的 slot 徽标indigo-600 背景、白色大写加粗文本验证用户消息气泡未被自定义容器包裹用户消息保持默认样式发送第二条提示Write a one-line sonnet验证第二个助手响应同样被custom-assistant-message容器包裹。3. 错误处理尝试发送空消息验证其为 no-op无用户气泡、无网络请求发送约 500 字符的长消息验证其在 max-w-5xl 容器内自动换行、无横向滚动或布局破坏自定义助手消息卡片随之增长以容纳响应验证上述任何流程中 DevTools → Console 均无未捕获错误或缺失 props 警告。十二、预期结果Acceptance Criteria聊天界面 3 秒内渲染完成自定义欢迎卡可见助手文本响应 10 秒内出现且每一轮都被自定义助手消息插槽包裹三个自定义插槽welcomeScreen、input.disclaimer、messageView.assistantMessage均替换其默认实现并通过 slot 徽标 / 渐变样式在视觉上可区分无 UI 布局破坏无未捕获控制台错误。十三、迁移到自己的应用最小插槽定制模板如果要在自己的 CopilotKit 应用中复刻本 Demo 的模式可直接套用 slot-overrides.snippet.tsx 的教学形态类型断言集中在一处并结合 slots.mdx 中的三级定制示例Tailwind 类定制最轻量CopilotChat messageViewbg-gray-50 dark:bg-gray-900 p-4 inputborder-2 border-blue-400 rounded-xl /Props 覆盖CopilotChat messageView{{ className: my-custom-messages, data-testid: message-view }} input{{ autoFocus: true }} /嵌套下钻递归插槽——覆盖助手消息工具栏中的复制按钮CopilotChat messageView{{ assistantMessage: { copyButton: ({ onClick }) button onClick{onClick}Copy/button, }, }} /文案标签labels便利 prop——不属于插槽体系但常与插槽搭配使用CopilotChat labels{{ chatInputPlaceholder: Ask your agent anything..., welcomeMessageText: How can I help you today?, chatDisclaimerText: AI responses may be inaccurate., }} /十四、小结通过chat-slotsDemo 与其 QA 文档的对照可以清晰看到 CopilotKit 插槽系统的完整工作链路后端 route.ts 将chat-slots名称绑定到中立sample_agent图 → 前端 page.tsx 通过welcomeScreen/input/messageView/suggestionView/scrollView五个根级插槽注册自定义组件 → slot-wrappers.tsx 以包裹默认组件的方式保留默认行为、叠加视觉定制 → SlotMarker 让每个插槽路径可视化、可复制 → chat-slots.spec.ts 将 QA 手测步骤固化为可回归的自动化断言。这套QA 文档 → 源码实现 → E2E 测试三位一体的模式既可以直接用作验收手册也是学习插槽 API 的最佳起点。【免费下载链接】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),仅供参考