ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CopilotKit 逐 Token 状态流式(State Streaming)实战:让 Agent 工具参数实时写入共享状态并驱动 UI 渲染

CopilotKit 逐 Token 状态流式(State Streaming)实战:让 Agent 工具参数实时写入共享状态并驱动 UI 渲染 CopilotKit 逐 Token 状态流式State Streaming实战让 Agent 工具参数实时写入共享状态并驱动 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导读State Streaming 是 CopilotKit 共享状态体系中最直观、也最魔法的能力当 Agent 还在调用write_document工具时LLM 为工具参数生成的每一个 token 就已经被镜像进共享状态state.document前端文档面板会像打字机一样逐字符生长而不是等整个工具调用结束才一次性刷新。本文以 agno 集成中的 State Streaming 演示 为主体结合仓库内 SDK 导出、LangGraph 规范后端实现与 E2E 测试完整拆解这一机制的配置方式、前端订阅原理与底层数据流。读完你将掌握StateStreamingMiddlewareStateItem的一行式接入方法、useAgent状态订阅的正确姿势以及如何用字符计数器 LIVE 徽标让逐 Token 增量在 UI 上肉眼可见。这个 Demo 展示了什么演示的核心效果一句话概括工具参数逐 Token 直接流入共享 Agent 状态——文档在 UI 中一个字符一个字符地增长而此刻工具调用仍在进行中。具体拆解为三个可见特性实时文档面板Live document panelstate.document被渲染在一个文档视图中带有一个闪烁光标和一个 LIVE 徽标Token 级增量Token-level deltasAgent 的write_document工具参数中流式生成的每一个 token都会被直接转发到document状态键字符计数器Char counter一个实时刷新的字符数统计让逐 Token 流式过程变得一目了然。如何交互页面默认展示一个文档面板 聊天侧边栏CopilotSidebar点击建议芯片suggestion chip或直接在输入框发送以下任一提示词即可体验Write a short poem about autumn leaves.Draft a polite email declining a meeting next Tuesday afternoon.Write a 2-paragraph explanation of quantum computing for a curious teenager.随后观察文档面板在 Agent 写作过程中被实时填充。这三个提示词并非随手示例而是通过 suggestions.ts 中useConfigureSuggestions以配置形式注册的且available: always保证随时可用useConfigureSuggestions({ suggestions: [ { title: Write a short poem, message: Write a short poem about autumn leaves. }, { title: Draft an email, message: Draft a polite email declining a meeting next Tuesday afternoon. }, { title: Explain quantum computing, message: Write a 2-paragraph explanation of quantum computing for a curious teenager. }, ], available: always, });前端实现解析状态订阅驱动逐 Token 重渲染页面入口与 useAgent 订阅页面根组件page.tsx通过CopilotKit上下文绑定运行时与 AgentCopilotKit runtimeUrl/api/copilotkit agentshared-state-streaming DemoContent / /CopilotKit核心逻辑在DemoContent中——它同时订阅状态变化与运行状态变化两类更新事件。前者驱动文档的逐 Token 重渲染后者在 Agent 开始/结束时切换 LIVE 徽标const { agent } useAgent({ agentId: shared-state-streaming, updates: [UseAgentUpdate.OnStateChanged, UseAgentUpdate.OnRunStatusChanged], }); const agentState agent.state as StreamingAgentState | undefined; const document agentState?.document ?? ; const isRunning agent.isRunning; return DemoLayout document{document} isStreaming{isRunning} /;其中StreamingAgentState仅声明了一个可选的document?: string字段——这也是逐 Token 状态流式在类型层面的全部约定后端往document键写入什么前端就渲染什么。UseAgentUpdate枚举定义在 packages/react-core/src/v2/hooks/use-agent.tsx共有三个取值OnMessagesChanged、OnStateChanged、OnRunStatusChanged本演示用到了后两者。文档面板LIVE 徽标、字符计数器与闪烁光标DemoLayout 将文档内容与流式状态传入DocumentView同时挂载CopilotSidebardefaultOpen{true}输入占位符 Ask me to write something...。真正的视觉反馈在 document-view.tsx 中实现LIVE 徽标仅当isStreaming为真时渲染红色胶囊底色 白色脉冲圆点配 Live 文案data-testiddocument-live-badge字符计数器const charCount content.length以等宽字体显示 {charCount}charsdata-testiddocument-char-count闪烁光标流式期间在文档末尾追加一个animate-pulse的黑色竖条 span空态占位文档为空且未流式时显示斜体提示 Ask the agent to write something — its output will stream here token by token.正文渲染whitespace-pre-wrap 衬线字体保证换行与缩进忠实呈现。这些组件注释里写得很直白On every streamed token, the parent re-renders this component with a longercontentstring——即每次 token 到达父组件就会用更长的字符串重渲染本组件从而形成逐字符生长的视觉效果。核心机制一行 StateStreamingMiddleware 接入逐 Token 状态镜像配置入口README 给出的魔法只有一段中间件配置StateStreamingMiddleware( StateItem( state_keydocument, toolwrite_document, tool_argumentcontent, ) )StateItem的三个字段语义如下字段含义在本 Demo 中的取值state_key共享状态中要实时更新的键名documenttool需要监听其参数流的工具名write_documenttool_argument该工具参数中要被逐 Token 镜像进状态的字段content有与没有中间件的差别没有它state.document只会在工具调用结束后更新一次——用户看到的是文档瞬间出现有它LLM 为content参数生成的每一个 token 都被立即镜像进状态——用户看到的是文档逐字符被写出。前端侧的配合无需任何额外代码useAgent({ updates: [OnStateChanged, OnRunStatusChanged] })驱动文本与 LIVE 徽标的重渲染agent.isRunning控制光标闪烁。源码级佐证SDK 导出与规范后端实现SDK 导出链StateStreamingMiddleware与StateItem由 Python SDK 统一导出。在 sdk-python/copilotkit/init.py 中可以看到它们源自ag_ui_langgraph.middlewares.state_streaming模块并被列入__all__公开 APIfrom ag_ui_langgraph.middlewares.state_streaming import ( StateStreamingMiddleware, StateItem, )LangGraph 规范实现完整接线仓库中逐 Token 状态流式的规范后端实现位于 showcase/integrations/langgraph-python/src/agents/shared_state_streaming.py它完整展示了从状态 Schema、工具到中间件装配的整个过程状态 SchemaAgentState继承BaseAgentState并声明document: str工具定义write_document(document: str, runtime: ToolRuntime)返回Command(update{...})把完整文档写入document键同时追加一条ToolMessage(Document written to shared state.)系统提示约束提示词明确要求任何写作/起草/修改请求都必须调用write_document把全文作为document参数传入不要把文档贴进聊天消息——这是保证状态流式路径被稳定触发的关键中间件装配graph create_agent( modelChatOpenAI(modelgpt-5.4), tools[write_document], middleware[ CopilotKitMiddleware(), StateStreamingMiddleware( StateItem( state_keydocument, toolwrite_document, tool_argumentdocument, ) ), ], state_schemaAgentState, )该文件注释里还有一条极易踩坑的约束值得单独强调前端usePredictStateSubscription钩子是按state_key对部分 JSON 解析后的工具参数做索引的因此工具的参数字段名必须与state_key保持一致逐 Token 增量才能真正落到state.document。也就是说如果state_keydocument那么工具签名必须是write_document(document...)参数名对不上则流式增量无法命中状态键这也是为何本文主文档 agno 示例中tool_argumentcontent与 LangGraph 规范实现的tool_argumentdocument存在差异——它取决于具体后端工具的参数命名。平行实现CrewAI Flows同类能力在 CrewAI 集成中以copilotkit_predict_state呈现见 showcase/integrations/crewai-conversational-flows/src/agents/shared_state_streaming.py用法语义一致——把StateItem(state_keydocument, toolwrite_document, tool_argumentdocument)传给copilotkit_predict_stateAgent 边流式生成边将参数增量预测进共享状态配套的单元测试 tests/python/test_specialized_flows.py 还验证了预测的StateItem列表、flow.state.document的写入结果与工具结果的 emit 行为。运行时接线CopilotRuntime 如何路由到该 Agent在 agno 集成中该 Demo 的前端通过/api/copilotkit路由接入后端接线逻辑在 route.ts 中使用copilotkit/runtime/v2的CopilotRuntimecreateCopilotRuntimeHandler以mode: single-route单路由方式服务所有 Agent后端 Agent 以独立进程运行在AGENT_URL默认http://localhost:8000前端通过HttpAgent按 AG-UI 协议代理转发shared-state-streaming被列入mainAgentNames数组route.ts 第 67 行即该名称被别名到主 Agent上前端按每个 demo 名称注册的工具/组件作用域因此可以正确隔离。该 Demo 同时在 agno 的 manifest.yaml 中注册id: shared-state-streaming、路由/demos/shared-state-streaming、标签agent-state并高亮src/agents/main.py、page.tsx与route.ts三个文件。需要说明的是Agno 的协议级 parity 清单将该特性列在not_supported_features中即逐 Token 状态流式的规范后端实现以仓库内 LangGraph 集成上文shared_state_streaming.py为准Agno 集成的此页面主要承担完整前端演示与路由别名的作用。质量保障E2E 测试如何验证逐 Token 流式仓库为这个 Demo 提供了完整的 Playwright 端到端测试tests/e2e/shared-state-streaming.spec.ts断言与上述组件一一对应可作为复现/回归的验收清单页面装载document-view面板可见Document 标题存在字符计数初始为 0 chars侧边栏输入框占位符正确空态无内容时显示 Ask the agent to write something 占位文本且document-content不出现建议芯片三条建议Write a short poem / Draft an email / Explain quantum computing均渲染为按钮流式触发发送 Write a short poem about autumn leaves. 后document-content出现且文本长度在 60 秒内增长到超过 10 个字符toPass轮询断言字符计数增长发送消息后计数从 0 变为大于 0LIVE 徽标发送前徽标不可见流式期间出现侧边栏回复copilot-assistant-message出现证明 Agent 在流式文档的同时仍在正常对话。这套断言本质上是把逐 Token 状态流式翻译成了可机器验证的行为document-content从无到有、char-count单调增长、live-badge随运行状态切换。延伸阅读路径本文主文档showcase/integrations/agno/src/app/demos/shared-state-streaming/README.md前端四件套page.tsx、demo-layout.tsx、document-view.tsx、suggestions.ts规范后端实现showcase/integrations/langgraph-python/src/agents/shared_state_streaming.pySDK 导出sdk-python/copilotkit/init.py订阅 API 定义packages/react-core/src/v2/hooks/use-agent.tsxE2E 测试showcase/integrations/agno/tests/e2e/shared-state-streaming.spec.ts【免费下载链接】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),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进