ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CopilotKit 与 CrewAI Conversational Flows:Shared State 只读模式的完整 QA 验证指南

CopilotKit 与 CrewAI Conversational Flows:Shared State 只读模式的完整 QA 验证指南 CopilotKit 与 CrewAI Conversational FlowsShared State 只读模式的完整 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 集成示例crewai-conversational-flows中的Shared StateReading演示shared-state-read系统讲解如何对「前端发布、Agent 只读」的共享状态功能进行端到端 QA 验证。读完本文你将掌握该 demo 的功能验收清单、UI 测试断言data-testid、关键源码实现agent.setState与后端 Flow 的状态注入以及如何用 Playwright 自动化复现测试步骤。什么是 Shared StateReadingDemo在 CopilotKit 中useAgent暴露的agent.state是前端与 Agent 之间共享的单一事实来源single source of truth。shared-state-read演示的核心设计非常明确UI 拥有状态前端通过agent.setState将菜谱数据写入 agent 状态Agent 只读后端 Flow 每一轮对话都会读取该菜谱但不提供任何修改工具因此 UI 始终是唯一的数据权威双向感知用户既可以在表单中编辑状态也可以直接向 Agent 提问“我在做什么菜谱”Agent 的回答会实时引用当前状态。该 demo 的源码位于 showcase/integrations/crewai-conversational-flows/src/app/demos/shared-state-read/对应清单条目shared-state-read在 manifest.yaml 中被标记为shared-state-read特性与同目录下的shared-state-read-write双向读写形成对照。验证前置条件开始 QA 前需满足以下两个条件详见 QA 文档Demo 已部署且可访问本地开发或 Docker Compose 环境均可生产环境通过 Railway 部署Agent 后端健康访问/api/health接口应返回正常状态。本地 D6 验证可通过crewai-conversational-flows的 compose 服务在端口3120上运行见 PARITY_NOTES.md。该集成包基于 CrewAI 官方 Conversational Flows API每个 Agent 路由以conversationalTrue注册Flow 通过stream_turn(message, session_id...)处理对话并将 AG-UI 的threadId作为 CrewAI 会话的session_id。一、基础功能验证QA 文档的第一组检查点覆盖页面加载与基本对话链路导航至shared-state-readdemo 页面验证菜谱卡片表单加载成功data-testidrecipe-card验证CopilotSidebar默认打开标题为AI Recipe Assistant通过侧边栏发送一条消息验证 Agent 正常响应。在源码中这些要求逐一对应。页面主体由 page.tsx 构成CopilotKit runtimeUrl/api/copilotkit agentshared-state-read CopilotSidebar defaultOpen labels{{ modalHeaderTitle: AI Recipe Assistant }} / /CopilotKitdefaultOpen保证了侧边栏默认展开labels.modalHeaderTitle控制标题文案。而data-testidrecipe-card由表单组件 recipe-card.tsx 暴露form>await expect(page.locator([data-testidrecipe-card])).toBeVisible({ timeout: 15000, }); await expect(page.getByText(AI Recipe Assistant)).toBeVisible({ timeout: 10000, });二、初始菜谱状态验证QA 文档要求核对表单的默认值。这些默认值并非硬编码在 JSX 中而是集中定义在 types.ts 的INITIAL_RECIPE常量里export const INITIAL_RECIPE: RecipeData { title: Make Your Recipe, skill_level: SkillLevel.INTERMEDIATE, cooking_time: CookingTime.FortyFiveMin, special_preferences: [], ingredients: [ { icon: , name: Carrots, amount: 3 large, grated }, { icon: , name: All-Purpose Flour, amount: 2 cups }, ], instructions: [Preheat oven to 350°F (175°C)], };对应 QA 检查点QA 检查点源码位置菜谱标题默认为 Make Your RecipeINITIAL_RECIPE.title烹饪时间下拉默认 45 minCookingTime.FortyFiveMin枚举值见types.ts技能等级下拉默认 IntermediateSkillLevel.INTERMEDIATE默认食材胡萝卜3 large, grated、通用面粉2 cupsINITIAL_RECIPE.ingredients默认步骤Preheat oven to 350 FINITIAL_RECIPE.instructions烹饪时间下拉的默认值在recipe-card.tsx中通过索引映射实现cookingTimeValues.find((t) t.label recipe.cooking_time)?.value ?? 3其中value: 3恰好对应45 min兜底值保证了异常情况下的默认行为。初始状态的注入时机一个容易忽略的实现细节是初始菜谱并非在组件渲染时就写入状态而是通过useEffect在首次渲染后一次性播种见 page.tsxuseEffect(() { if (!(agent.state as RecipeAgentState | undefined)?.recipe) { agent.setState({ recipe: INITIAL_RECIPE } satisfies RecipeAgentState); } }, []);这段代码的含义是只有当agent.state.recipe尚不存在时才写入初始值确保 Agent 在第一轮对话时就能读到内容此后所有编辑都走agent.setState通道。QA 中验证“初始菜谱正确显示”本质上就是在验证这次播种是否成功。三、建议Suggestions验证QA 要求确认三条起步建议可见Create Italian recipeMake it healthierSuggest variations这三条建议由useConfigureSuggestions配置位于 page.tsxuseConfigureSuggestions({ suggestions: [ { title: Create Italian recipe, message: Create a delicious Italian pasta recipe. }, { title: Make it healthier, message: Make the recipe healthier with more vegetables. }, { title: Suggest variations, message: Suggest some creative variations of this recipe. }, ], available: always, });available: always表示建议在对话过程中始终可用而非仅在首屏出现。Playwright 测试对这三条建议做了逐条可见性断言page.getByRole(button, { name: title })可直接用于自动化回归。四、本地状态编辑验证Local StateQA 文档中篇幅最大的一组检查点是不经过 AI、纯前端驱动的表单编辑。核心设计是表单是一个完全受控组件fully controlled component每一次编辑都立即通过agent.setState同步进共享状态见 page.tsxconst handleChange (next: RecipeData) { agent.setState({ recipe: next } satisfies RecipeAgentState); };受控组件的更新链在 recipe-card.tsx 中实现update(partial)做浅合并updateIngredient与updateInstruction分别做不可变数组更新。QA 步骤与实现对应关系如下QA 步骤实现要点编辑标题update({ title: e.target.value })aria-labelRecipe title切换技能等级下拉update({ skill_level: value as SkillLevel })切换烹饪时间下拉通过cookingTimeValues[Number(value)].label写入切换饮食偏好如 Vegetarianrecipe.special_preferences数组的增删Badge组件以aria-pressed标记选中态点击 Add Ingredientdata-testidadd-ingredient-button追加{ icon: , name: , amount: }空行编辑食材名称与数量updateIngredient(index, field, value)点击 x 删除食材过滤recipe.ingredients数组点击 Add Step追加空字符串到instructions编辑步骤文案updateInstruction(index, value)点击 x 删除步骤过滤instructions数组偏好选项来自 types.ts 的SpecialPreferences枚举High Protein、Low Carb、Spicy、Budget-Friendly、One-Pot Meal、Vegetarian、Vegan共 7 个可多选标签。自动化方面Playwright 测试验证了 Add Ingredient 的行为shared-state-read.spec.tsconst ingredientCards page.locator([data-testidingredient-card]); const initialCount await ingredientCards.count(); await page.locator([data-testidadd-ingredient-button]).click(); await expect(ingredientCards).toHaveCount(initialCount 1, { timeout: 5000 });五、AI 驱动的菜谱更新useAgent 共享状态这一节验证 Agent 在读取共享状态后给出文本建议但不会真的改写 UI 数据。QA 步骤为点击 Create Italian recipe 建议验证 Agent 根据当前菜谱输出关于标题、食材、步骤的建议验证ping indicator在变更区域出现验证 Improve with AI 按钮data-testidimprove-button在加载中变为 Please Wait...点击 Improve with AI 并验证菜谱被增强。其中handleImprove的实现展示了「手动触发生成」的完整调用链page.tsxconst handleImprove () { if (agent.isRunning) return; agent.addMessage({ id: crypto.randomUUID(), role: user, content: Improve the recipe, }); void copilotkit .runAgent({ agent }) .catch((err) console.error([shared-state-read] runAgent failed, err)); };按钮的加载态由isLoading即agent.isRunning驱动recipe-card.tsxButton>SYSTEM_PROMPT ( You are a concise recipe assistant. The frontend-owned recipe state is included below. Read it when answering, but never claim to have edited the recipe because this demo intentionally gives the agent read-only access.\n\nCurrent recipe state:\n{recipe} ) class SharedStateReadState(CopilotKitState): recipe: dict[str, Any] | None None class SharedStateReadFlow(Flow[SharedStateReadState]): start() async def chat(self) - None: recipe json.dumps(self.state.recipe or {}, indent2, ensure_asciiFalse) response await copilotkit_stream( await acompletion( modelopenai/gpt-5.4, messages[ {role: system, content: SYSTEM_PROMPT.format(reciperecipe)}, *self.state.messages, ], toolsself.state.copilotkit.actions, streamTrue, ) ) self.state.messages.append(response.choices[0].message)三个关键点值得深入理解状态注入每个对话轮次都会把self.state.recipe序列化为 JSON拼进 system prompt。这意味着 Agent 每次回答都基于最新的前端状态用户中途的任何编辑都会立即生效只读约束后端不注册任何写入工具tools为空列表system prompt 还显式要求 Agent “不要声称编辑过菜谱”——这是该 demo 与shared-state-read-write的本质区别无状态上下文传递前端无需把菜谱内容当作消息上下文发送Agent 直接从runtime.state读取这正是共享状态模式相比“手动拼上下文”的优势。该 Flow 在 conversational_flows.py 中注册为_conversational_type(SharedStateReadFlow)对应shared-state-readagent 名称与前端agentshared-state-read及useAgent({ agentId: shared-state-read })一一对应。自动化回归中发送侧边栏消息的断言方式为shared-state-read.spec.tsconst input page.getByPlaceholder(Type a message); await input.fill(What recipe am I making?); await input.press(Enter); await expect( page.locator([data-testidcopilot-assistant-message]).first(), ).toBeVisible({ timeout: 30000 });七、错误处理验证QA 文档的错误处理检查点有三项检查点实现/验证方式发送空消息应被优雅处理侧边栏消息发送前对空内容进行过滤/拦截不触发 Agent 调用正常使用过程无 console 错误handleImprove对runAgent的 Promise 做了.catch兜底异常只会console.error而不会抛出未捕获错误Improve with AI 在加载期间禁用disabled{isLoading}if (agent.isRunning) return;双重防护recipe-card.tsx中的isLoading由agent.isRunning派生因此 Agent 执行期间的任何并发触发都会被拦截避免状态竞争。八、预期结果与验收标准QA 文档给出的最终验收标准如下菜谱卡片与侧边栏 3 秒内加载完成Agent 10 秒内响应菜谱状态在 UI 与 Agent 之间双向同步UI 编辑 → Agent 读取到新值Agent 建议 → UI 呈现ping indicator 高亮被修改的区域无 UI 错误、无布局破坏。Playwright 配置中对应的超时阈值15s 定位、30s 响应等待为线上环境留出了余量实际验收以文档中的 3s/10s 为目标基准。自动化测试覆盖了“页面加载 侧边栏挂载”“建议渲染”“添加食材”“发送消息并收到响应”四条核心链路其余编辑类操作可参照 QA 清单在手工测试中逐项核对。结语从验证清单反推架构shared-state-read的 QA 文档表面上是一份功能清单但其背后是 CopilotKit 共享状态模式的一种最小可信实现前端agent.setState负责写、后端 Flow 通过 system prompt 注入负责读、类型定义RecipeAgentState在前后端之间维持契约。对照同目录的shared-state-read-writedemoAgent 侧可写回 notes可以清晰看到 CopilotKit 在「只读上下文」与「双向共享状态」之间的设计取舍。若要在自己的项目中复刻该模式只需三件事定义一个共享状态类型、在 UI 中调用agent.setState、在后端 Flow 中把对应字段注入每次模型调用。【免费下载链接】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),仅供参考
返回列表