资讯动态

CopilotKit A2UI 错误恢复实战:Google ADK 的 validate→retry 恢复循环与硬失败降级

发布时间:2026/9/13 3:28:29 来源:尧图企业网站定制
CopilotKit A2UI 错误恢复实战Google ADK 的 validate→retry 恢复循环与硬失败降级【免费下载链接】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 仓库中 Google ADK 集成的 A2UI Error Recovery 演示a2ui-recovery系统讲解生成式 UIA2UI在模型产出畸形渲染结果时的完整容错机制中间件如何通过parse_and_fix在单次尝试内治愈松散参数如何通过 validate→retry 恢复循环在达到尝试上限后返回a2ui_recovery_exhausted硬失败信封以及前端ag-ui/a2ui-middleware如何以building → retrying → failed → painted的生命周期状态优雅呈现全过程。读完本文你将掌握这套后端中间件恢复 前端生命周期渲染的 A2UI 容错架构并能够复现其 QA 验证流程。一、为什么生成式 UI 需要错误恢复A2UIAgent-to-UI让 Agent 直接生成 UI 描述而非传统地逐个调用工具。模型生成的 UI 描述天然存在不确定性——它可能把 components 与 data 序列化成 JSON 字符串而非结构化数组松散参数也可能引用一个不存在的子节点结构性错误。在 CopilotKit 的 v2 React Core 中A2UI 中间件驱动整个生成式 UI 生命周期于单个a2ui-surfaceactivity 上一个稳定的 messageIdreplace: true见 A2UIMessageRenderer.tsxbuilding动画骨架屏 Building interface可选实时 token 计数retrying同一骨架屏当重试可感知后副标题变为 Retrying generation… (N/M attempts)failed干净的错误卡片替换骨架屏绝不出现半渲染的坏 surfacepaintedsurface 渲染器接管 UI上述状态不再渲染任何内容这一生命周期的状态机、时序与调试信息曝光均定义在 A2UIRecoveryStates.tsx。本演示OSS-158的价值在于把这些内部机制显式暴露出来通过两个建议按钮分别验证可治愈与不可治愈两条路径。二、Demo 概览ADK-only 的架构定位本演示是ADK-only的恢复循环recovery loop存在于 Google ADK 的ag_ui_adk中间件中而 langgraph-python 运行时路径没有等价实现因此该 demo 没有 langgraph-python 的 parity 对照在 LP e2e-parity 对比中豁免原文档 Notes 部分OSS-375 跟踪 LP parity。与 declarative-gen-ui 演示不同本 demo 采用**后端拥有backend-owned**的 A2UI 接线组件配置说明运行时路由injectA2UITool: false防止运行时再注入一份工具双重绑定ADK Agentget_a2ui_tool({ recovery: { maxAttempts: 3 } })后端 Agent 自己拥有generate_a2ui工具目录defaultCatalogId: declarative-gen-ui-catalog复用 declarative-gen-ui 目录不引入新组件主题Vantage Threads 销售上下文复用销售数据集让修复后的 surface 有真实数字可渲染只有 backend-owned 路径会显式暴露恢复循环与a2ui_recovery_exhausted硬失败declarative-gen-ui 演示采用的是运行时自动注入不暴露该循环。三、前置条件复现与验证本演示前需满足以下条件完整继承自 原文档Demo 已部署可在 dashboard 主机上通过/demos/a2ui-recovery访问Agent 后端健康/api/healthGOOGLE_API_KEY已设置AGENT_URL指向暴露a2ui_recoveryagent 路径的 ADK agent serveragent 注册名为a2ui-recovery见 copilotkit-a2ui-recovery/route.ts依赖版本要求ag-ui-adk 0.7.0提供 validate→retry 恢复循环 a2ui_recovery_exhausted硬失败信封ag-ui/a2ui-middleware 0.0.10提供building/retrying/failed生命周期渲染后端拥有式接线路由设置injectA2UITool: falseAgent 通过get_a2ui_tool({ recovery: { maxAttempts: 3 } })拥有generate_a2ui见 recovery_agent.py复用declarative-gen-ui目录catalogId: declarative-gen-ui-catalog与 Vantage Threads 销售上下文无新增组件本演示为ADK-only无 langgraph-python parity 参照3.1 运行时路由backend-owned 接线实现route.ts 的核心逻辑const AGENT_URL process.env.AGENT_URL || http://localhost:8000; const recoveryAgent new HttpAgent({ url: ${AGENT_URL}/a2ui_recovery, headers, // 转发入站 x-aimock-context 头 }); const runtime new CopilotRuntime({ agents: { a2ui-recovery: recoveryAgent }, a2ui: { injectA2UITool: false, // 关键后端已拥有工具运行时不得再注入 defaultCatalogId: declarative-gen-ui-catalog, }, });injectA2UITool: false是承重墙配置——CopilotKit#5611 之后 provider catalog 默认将injectA2UITool置为 true若此处不显式关闭运行时会再注入一份generate_a2ui造成双重绑定。3.2 ADK Agent把恢复循环参数显式钉死recovery_agent.py 中Agent 以LlmAgent形式注册recovery_agent LlmAgent( nameA2uiRecoveryAgent, modelget_model(), instruction_INSTRUCTION, tools[ get_a2ui_tool({ model: get_a2ui_model(), default_catalog_id: declarative-gen-ui-catalog, recovery: {maxAttempts: 3}, on_a2ui_attempt: _log_attempt, }) ], after_model_callbackstop_on_terminal_text, )要点解析recovery: {maxAttempts: 3}恢复与恢复耗尽硬失败本是 toolkit 默认行为此处为演示显式钉死上限使渲染器的 Retrying… (N/M) 标签与适配器上限一致on_a2ui_attempt: _log_attempt开发可观测性钩子每次尝试含被拒绝的都会记录[a2ui recovery] attempt N: valid/invalid errors见 recovery_agent.pyget_a2ui_model()A2UI 子 Agent 需要具体的Gemini模型对象而非字符串因为在强制render_a2ui调用中模型被直接调用同时该函数会按GOOGLE_GEMINI_BASE_URL接入 aimock 代理并安装 x-header 钩子使子 Agent 的调用与主 Agent 走同一代理、匹配同一批 aimock fixtures见 shared_chat.pystop_on_terminal_textafter_model_callbackGemini 3.1 Flash-Lite 在成功工具调用后不会自然结束 agentic 循环该回调在含文本且无 pending function_call且finish_reasonSTOP时设置_invocation_context.end_invocation True终止循环防止无限重复调用工具四、测试步骤4.1 基础功能导航到/demos/a2ui-recovery验证页面在 3 秒内渲染且单个CopilotChat面板居中max-width ~896px、rounded-2xl、全高。前端实现见 page.tsx它使用CopilotKit组件并指定runtimeUrl/api/copilotkit-a2ui-recovery、agenta2ui-recovery、a2ui{{ catalog: myCatalog }}验证聊天已接线到runtimeUrl/api/copilotkit-a2ui-recovery与agenta2ui-recoveryDevTools → Network发送消息命中该端点而非/api/copilotkit验证两个建议按钮suggestion pills以逐字标题可见Recover a bad renderShow an unrecoverable failure两个按钮的定义见 suggestions.ts通过useConfigureSuggestions注册。前端聊天面板在 chat.tsx 中通过CopilotChat agentIda2ui-recovery classNameh-full rounded-2xl /渲染并复用 declarative-gen-ui 的销售上下文。4.2 治愈路径Healing path点击 Recover a bad render消息Render my Q2 sales dashboard, recovering if the first attempt is malformed.内层render_a2ui返回free-form / 松散sloppyA2UI 参数components 与 data 以 JSON 字符串而非结构化数组形式存在。验证中间件通过parse_and_fix**治愈heals**这些参数为有效 surface 并完成渲染——无坏 surface、无错误横幅验证渲染出的surface 有效包含declarative-metric行Quarterly Revenue $4.2M、Win Rate 31%——即松散渲染被修复并正常呈现DevTools → Network验证最终工具结果携带a2ui_operations容器无a2ui_recovery_exhausted验证聊天回复为一句话简述治愈结果aimock fixture 中 HEAL 分支的内层render_a2ui参数即为典型松散形态a2ui-recovery.json{ id: call_d6_recover_heal_design, name: render_a2ui, arguments: {\surfaceId\: \recovery-demo\, \catalogId\: \declarative-gen-ui-catalog\, \components\: \[{\\\id\\\: \\\root\\\, ...}]\, \data\: \{}\} }注意components与data都是字符串而非数组——这正是模型常产出的松散形态。治愈本身由 ADK 中间件实时执行parse_and_fix单次通过而非 fixture 预先修复。对应的 Playwright 断言a2ui-recovery.spec.ts确认declarative-metric元素数量 ≥ 2且页面上不出现Couldnt generate the UI、Catalog not found、Cannot create component ... without a type 等错误文本。4.3 硬失败路径Hard-fail / recovery exhausted点击 Show an unrecoverable failure消息Render a dashboard that keeps failing validation so I can see the fallback.验证生命周期以得体的failed状态结束既不是坏/半渲染 surface也不是静默丢弃DevTools → Network验证render_a2ui被尝试至上限3 次尝试全部无效工具返回a2ui_recovery_exhausted信封无a2ui_operations渲染验证聊天回复用一句话优雅解释降级行为EXHAUST 分支的 fixture 结构性无效root 引用了未定义的子节点never-defineda2ui-recovery.json因此每次尝试都校验失败循环必然触顶。对应断言a2ui-recovery.spec.tsCouldnt generate the UI 可见超时 90sdeclarative-metric数量恒为 0坏 surface 永不渲染——中间件门控 适配器恢复循环共同保证的 no-wipe 语义且聊天输入框仍可用对话在硬失败后可继续使用。4.4 回归与隔离验证恢复演示不影响 declarative-gen-ui 或 beautiful-chat 演示各自独立的路由与 Agent每个按钮再次运行验证产生相同的生命周期五、双按钮的 fixture 选择机制per-pill 区分两个按钮跑的是同一个内层render_a2ui工具但它们之所以能分别命中可治愈与恒无效的 fixture依赖一个精妙机制原文档 Per-pill fixture selection 小节ag_ui_adk 0.7.0会把运行时的对话转发进内层render_a2ui调用因此 aimock 匹配的最后一个用户回合就是按钮提示语本身通用的 A2UI 渲染指引作为 system prompt 携带不参与用户消息匹配。由此每个按钮按userMessage命中自己的内层 fixtureHEAL → free-form/可治愈 fixtureEXHAUST → 恒无效 fixture。经 aimock journal 验证HEAL →call_d6_recover_heal_designEXHAUST →call_d6_recover_exhaust_design被调用 3 次对应重试循环。三个 e2e 测试页面加载、heal、exhaust在 aimock 下全部通过。六、前端生命周期渲染的源码级细节ag-ui/a2ui-middleware 0.0.10负责把中间件状态渲染为可见 UI。其状态字段由中间件盖印在a2ui-surfaceactivity 内容上A2UIRecoveryStates.tsxstatus: building | retrying | failed可选 attempt / maxAttempts / progressTokens / error / errors / attempts可选 debugExposure: hidden | collapsed | verbose可选服务端可覆盖客户端选项可调项客户端a2ui.recovery选项见 CopilotKitProvider.tsx选项默认值作用showAfterMs2000Retrying… 副标签在延迟多少毫秒后可见showAfterAttempts2一旦attempt达到该值立即显示 Retrying… 副标签debugExposurecollapsed调试细节曝光程度hidden/collapsed/verbose关键实现行为A2URetryingState快速/瞬态重试不会闪烁只有重试可感知后超过showAfterMs或attempt越过showAfterAttempts副标签才显示Retrying generation… (N/M attempts)否则与正常 building 状态无异debugExposure ! hidden且有校验错误时骨架屏下方出现可折叠的 validation issues 调试面板失败态A2UIRecoveryFailure以琥珀色卡片替换骨架屏标题 Couldnt generate the UI副文案提示可继续聊天并重试开发细节折叠在debugExposure门控的 expander 内。渲染器的状态分派逻辑在 A2UIMessageRenderer.tsxstatus failed→ 失败卡片status retrying→ 重试态默认building→ 宿主提供的 loader 优先否则内建骨架屏。surface 挂载完成后以a2ui_operations键进行最终渲染A2UI_OPERATIONS_KEY a2ui_operations见 A2UIMessageRenderer.tsx。七、注意事项与已知限制畸形渲染由 aimock fixtures 强制产生showcase/aimock/d6/google-adk/a2ui-recovery.json内层render_a2ui调用按userMessagetoolNamerender_a2ui匹配。治愈healing本身由 ADK 中间件实时执行而非 fixture 完成因此运行验证需要以 aimock 启动整套栈GOOGLE_GEMINI_BASE_URL指向 aimock 代理畸形渲染才能确定性触发对接真实 LLM 时demo 无法可靠地产出无效尝试本演示为ADK-only恢复循环位于ag_ui_adk中间件langgraph-python 的运行时 A2UI 路径无等价实现OSS-375 跟踪 LP parity测试刻意不断言瞬态的 Retrying generation… (N/M) 标签——该标签是阈值门控 时序依赖的见copilotkit/react-core/v2的A2UIRecoveryStates断言它会引入 flaky 测试a2ui-recovery.spec.ts八、总结A2UI Error Recovery 演示展示了 CopilotKit A2UI 生态中一条完整的容错链路后端ag_ui_adk中间件通过parse_and_fix单次治愈松散参数、通过 validate→retry 循环在尝试上限后返回a2ui_recovery_exhausted硬失败信封前端ag-ui/a2ui-middleware以building → retrying → failed → painted生命周期状态在不渲染坏 surface的前提下优雅呈现全过程aimock 则通过转发对话到内层调用 userMessage 匹配保证两条路径的确定性复现。这套后端恢复 前端生命周期 fixture 驱动验证的组合可直接迁移到其他接入 A2UI 协议的后端集成中。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价