CopilotKit × Langroid:Agent 状态流式生成式 UI(Agentic Generative UI)的实现与验收实践
CopilotKit × LangroidAgent 状态流式生成式 UIAgentic Generative UI的实现与验收实践【免费下载链接】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 showcase 中 Langroid 集成示例的 gen-ui-agent 演示展开讲解一个由 Agent 端持有steps状态、通过 AG-UI 的STATE_SNAPSHOT事件流式推送到前端、并由useAgent在聊天转录中原地更新进度卡片的完整链路。读完本文你将掌握这套Agent 自绘 UI的验收标准QA 检查清单、前后端关键源码实现以及配套的 Playwright E2E 回归测试如何锁定单卡片原地更新这一核心契约。1. 演示定位与运行前提gen-ui-agent 是 Langroid 集成示例中的一个官方演示Agent 在处理长任务的过程中把每一步的执行状态实时流式推送到聊天界面渲染出一张任务进度卡片。其核心描述见 manifest.yaml 中id: gen-ui-agent的条目route: /demos/gen-ui-agent入口源码指向 page.tsx。按 QA 检查清单 的定义验收前需要满足两个前提演示已部署并可访问路由/demos/gen-ui-agentAgent 后端健康可通过/api/health检查对应 health 路由。2. 基础功能验收聊天界面加载与消息收发QA 清单中Basic Functionality一节的检查项如下每一项都能在当前仓库源码中找到对应的实现或自动化验证QA 检查项源码/测试依据导航到 gen-ui-agent 演示页路由/demos/gen-ui-agent见 manifest.yaml聊天界面以居中、全高布局加载page.tsx 中flex justify-center items-center h-screen w-fullmax-w-4xl容器输入框占位文案 Type a message 可见E2E 断言page.getByPlaceholder(Type a message)见 gen-ui-agent.spec.ts发送基础消息后 Agent 有响应E2E 用例 sends message and gets assistant response等待[data-testidcopilot-assistant-message]出现30s 超时页面入口 page.tsx 的结构是CopilotKit runtimeUrl/api/copilotkit agentgen-ui-agent div classNameflex justify-center items-center h-screen w-full div classNameh-full w-full max-w-4xl Chat / /div /div /CopilotKit即CopilotKit组件把 runtime 指向前端代理/api/copilotkit该 Next.js 路由 route.ts 将HttpAgent指向 Python 后端的${AGENT_URL}/gen-ui-agent端点并把默认 agent 指定为gen-ui-agent。3. 建议按钮SuggestionsQA 清单要求验证建议按钮可见。当前 suggestions.ts 通过useConfigureSuggestions注册了三个建议useConfigureSuggestions({ suggestions: [ { title: Plan a product launch, message: Plan a product launch for a new mobile app. }, { title: Organize a team offsite, message: Organize a three-day engineering team offsite. }, { title: Research a competitor, message: Research our top competitor and summarize their strengths and weaknesses. }, ], available: always, });需要注意一个历史演进QA 检查清单中记录的建议是 Simple plan5 步登月计划与 Complex plan10 步披萨计划且Complex Plan一节要求验证 10 步进度条。而当前后端系统提示词_SYSTEM_PROMPT见 gen_ui_agent.py明确要求恰好规划 3 个具体步骤E2E 测试也固定断言 3 步全部完成。可以推断QA 清单保留的是更早一轮验收规格而演示实际已演进为3 步计划的版本——执行 QA 时应以当前源码与 E2E 断言为准把清单视为验收意图建议按钮存在、可触发进度卡片、步骤逐个完成而非逐字断言。4. 任务进度跟踪器useAgent messageView.children 的核心模式这是本演示的技术核心。QA 清单将其概括为 Task Progress Tracker (useAgent with state streaming)具体检查项包括进度组件渲染出来清单中锚点为data-testidtask-progress步骤条目带描述文本出现data-testidtask-step-textN/N Complete 计数器随步骤完成而更新已完成步骤绿色渐变背景 对勾图标 绿色文字当前处理中步骤蓝紫渐变背景 Spinner 图标 Processing... 文字 脉冲动画未开始步骤灰色背景 时钟图标 弱化文字。从当前仓库源码看这些视觉状态的实现落在 InlineAgentStateCard.tsx 中测试锚点为data-testidagent-state-card与data-testidagent-step带data-status属性三态视觉映射如下步骤状态Step.status渲染StepMarkercompleted绿色圆底bg-[#85ECCE] 对勾 SVG文字加删除线line-throughin_progress蓝紫圆底bg-[#BEC2FF]animate-spin旋转 SVGpending白底描边圆内显示序号弱化文字颜色卡片顶部还会根据status inProgress done total在 Spinner 与 Check 图标之间切换并用 Step X of Y / All N steps complete / Planning… 文案充当 QA 清单中N/N Complete计数器对应的进度指示。QA 清单描述的渐变进度条与源码中编号步骤列表 状态徽标存在措辞差异这同样属于清单与实现的版本演进差异验收时建议以 E2E 断言的agent-state-card/agent-step锚点为准。前端订阅链路在 page.tsxfunction Chat() { const { agent } useAgent({ agentId: gen-ui-agent, updates: [UseAgentUpdate.OnStateChanged], // 只关心状态变化 }); useSuggestions(); const steps (agent.state as AgentState | undefined)?.steps ?? []; const status agent.isRunning ? inProgress : complete; return ( CopilotChat agentIdgen-ui-agent classNameh-full rounded-2xl messageView{{ children: ({ messageElements, interruptElement }) ( MessageListWithState messageElements{messageElements} interruptElement{interruptElement} steps{steps} status{status} / ), }} / ); }其中AgentState即{ steps?: Step[] }Step为{ id, title, status: pending | in_progress | completed }。卡片挂载逻辑在 message-list-with-state.tsx只有当steps.length 0时才在messageElements之后、interruptElement之前渲染单个InlineAgentStateCard。这个模式解决了一个真实痛点gen-ui-agent.spec.ts 中的回归注释说明早期useCoAgentStateRenderV1方案会为每一条改状态的消息各推一张卡片一次 7 次set_steps调用的运行会堆出 7 张重复卡片迁移到 V2 的useAgentmessageView.children后整条转录中只存在一张原地更新的卡片。该测试用toHaveCount(1)把单卡片契约固定下来见 测试第 44-67 行。5. 后端set_steps 工具驱动的 STATE_SNAPSHOT 流前端看到的活状态来自 Python 侧 gen_ui_agent.py。其设计要点状态归一化与防御性清洗。_normalize_state把入站RunAgentInput.state强制归一为{steps: [...]}形状非 dict 输入视为空计划status不在{pending, in_progress, completed}白名单、或title非字符串的步骤会被静默丢弃缺id的步骤补发uuid4。_sanitize_steps对set_steps工具参数做同样的纵深防御——提示词很严格但一个行为不端的模型不应该搞坏 UI。工具契约。set_steps的 OpenAI function 规格_SET_STEPS_TOOL_SPEC要求模型每次状态迁移都调用且每次必须提交完整步骤列表整体替换而非增量补丁参数为{ steps: [{id, title, status}] }三者均为必填。有界工具循环。handle_run主循环以_MAX_TOOL_ITERATIONS 12为上限每轮调用 OpenAI chat completions模型取LANGROID_MODEL环境变量默认gpt-4.1openai.AsyncOpenAI从OPENAI_API_KEY/OPENAI_BASE_URL读取配置提取到set_steps调用时依次state[steps] sanitized更新本地状态发射TOOL_CALL_START→TOOL_CALL_ARGS→TOOL_CALL_END事件发射一条全新STATE_SNAPSHOT携带完整状态 dict——这正是前端useAgent订阅到OnStateChanged并原地重渲染的驱动源把 assistant 工具调用消息与role: tool结果Published N step(s).追加回消息历史供下一轮 LLM 决策。当某轮没有工具调用时流式发出TEXT_MESSAGE_START/TEXT_MESSAGE_CONTENT/TEXT_MESSAGE_END收尾文本并结束运行。整个响应是带Cache-Control: no-cache、X-Accel-Buffering: no头的 SSEtext/event-stream。事件序列概览一次典型运行RUN_STARTED STATE_SNAPSHOT(初始基线) [循环TOOL_CALL_* × set_steps STATE_SNAPSHOT × 1] TEXT_MESSAGE_START / CONTENT / END RUN_FINISHED6. 错误处理与边界行为QA 清单的 Error Handling 一节要求空消息被优雅处理、正常使用期间无 console 错误。结合源码本演示的边界行为可以归纳为空/无效请求体handle_run对 JSON 解析失败返回 400Invalid JSON bodyerrorId对RunAgentInput校验失败返回 422Invalid RunAgentInput payload两者均带errorId便于日志追踪gen_ui_agent.py#L394-L418LLM 调用失败捕获异常后发射RUN_ERRORRUN_FINISHED干净收尾而不是让 SSE 流悬空模型发出非法 steps 参数跳过该次快照发射但回填一条 Invalid steps payload — please retry with a list of steps. 的工具结果消息保持对话历史连贯、让模型可以重试循环失控防护12 轮内未产出最终文本时记录 warning 并终止运行前端steps缺省时回退为空数组?? []空状态不渲染卡片避免无消息时的欢迎屏场景下messageView.children尚未被调用带来的空引用。7. 自动化验证E2E 测试与 QA 清单的对应关系gen-ui-agent.spec.ts 用 Playwright 把 QA 清单转化为可执行断言关键用例页面加载/demos/gen-ui-agent后 Type a message 输入框可见消息收发发送 Hello 后 30s 内出现 assistant 消息单卡片回归核心契约发送 Plan a product launch for a new mobile app. 后等待agent-state-card与首个agent-step出现断言卡片数量恒为 1再等待 spinner 消失agent.isRunning翻转为 false 的视觉表现二次断言仍只有 1 张卡片全步骤完成断言 3 个[data-statuscompleted]步骤出现且总步骤数恰为 3无孤儿步骤fixture 短路回归通过建议按钮 Plan a product launch 触发确保 fixture 链按 pending → in_progress → completed 推进而非一次性吐出全部 completed 的终态该用例注释指出 aimock 响应极快浏览器可能观察不到瞬态 pending因此断言最终态。8. 预期结果验收基线QA 清单给出的性能与体验基线可作为人工验收的判定标准聊天界面在 3 秒内加载Agent 在 10 秒内响应任务进度跟踪器展示实时的步骤完成过程pending → in_progress → completed 逐格推进进度指示动画平滑无 UI 错误或布局破损。9. 小结gen-ui-agent 演示展示了一条完整的Agent 自绘 UI范式后端持有{steps: [{id, title, status}]}状态切片并定义唯一的set_steps写入工具每次调用都触发一条STATE_SNAPSHOTAG-UI 事件前端用 V2useAgentOnStateChanged订阅状态并在messageView.children中挂载单个原地更新的进度卡片从而保证任意次状态推送都只呈现一张卡片。验收侧则以 QA 清单 为意图基线、以 E2E 测试 为可执行契约覆盖了加载、建议按钮、进度动画、错误处理与性能基线。该模式在 showcase 的其他集成mastra、strands、ag2、agno、crewai-crews、langgraph-typescript、pydantic-ai 等的同名 gen-ui-agent 演示中保持一致是 CopilotKit 各 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),仅供参考