CopilotKit 集成 Google ADK:Sub-Agents 多代理委派 Demo 的端到端 QA 验证指南 📅 发布时间:2026/9/13 22:10:52 👁 浏览次数: CopilotKit 集成 Google ADKSub-Agents 多代理委派 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 的 Google ADKAgent Development Kit集成包中的 Sub-Agents Demo系统讲解其多代理委派架构supervisor 协调 research / writing / critique 三个子代理、共享状态delegations的前后端契约以及一套可直接执行的完整 QA 验证清单。读完本文你将掌握如何从功能、特性、错误处理三个维度验证该 Demo并能对照源码理解每一条验证项背后的实现原理同时可将其与仓库内置的 Playwright e2e 回归用例一一对应。一、Sub-Agents Demo 与 QA 文档的定位Sub-Agents 是 Google ADK 集成包manifest.yaml 中声明的subagents特性下的一个多代理 Demo一个 supervisor 类型的LlmAgent通过工具tool方式委派任务给三个各司其职的子代理并将每一次委派实时写入共享 Agent 状态前端据此渲染实时委派日志。其核心设计见 demo README三个专职子代理research_agent收集事实、writing_agent起草正文、critique_agent审阅草稿每个子代理在概念上都是一个独立的create_agent(...)子代理即工具supervisor 通过tool包装器调用它们每次调用结束后向共享状态的delegations槽位追加一条记录实时委派日志左侧面板渲染state[delegations]随着 supervisor 向外扇出任务而实时增长。本文所述的 QA 清单文件位于 qa/subagents.md它是该 Demo 上线前的完整人工验收标准同时与 tests/e2e/subagents.spec.ts 中四条 Playwright 用例高度对应可作为手工验收 自动化回归双轨验证的基线。二、前置条件环境就绪与状态契约执行 QA 前需要先满足以下环境前提与 QA 文档一致并给出仓库中的落地点前提说明仓库依据Demo 已部署并可在/demos/subagents访问前端页面入口page.tsxAgent 后端健康/api/copilotkit的 GET 探针会返回agent_statusNext.js 路由会轮询http://localhost:8000/healthroute.tsGOOGLE_API_KEY已设置或GOOGLE_GEMINI_BASE_URL指向 aimock 代理子代理二次调用 Gemini 的凭证/路由subagents_agent.py 中_client()supervisorLlmAgent通过工具委派给三个子代理每次委派向state[delegations]追加一条status: completed记录subagents_agent.py 中_append_completed_delegation关于密钥的两点补充后端启动脚本 entrypoint.sh 在容器启动时检查GOOGLE_API_KEY默认缺失时仅告警并继续启动便于排查设置REQUIRE_GOOGLE_API_KEY1则可升级为启动即失败的 fail-fast 模式GOOGLE_GEMINI_BASE_URL指向 aimock 代理时get_model()会构造一个带base_url的Gemini实例并安装 x-header 转发钩子见 shared_chat.py保证子代理调用与主代理走同一代理、同一批录制的夹具。状态契约是整条验证线的核心delegations只追加、不占位——后端从不写入running占位记录只在该子代理真正返回或失败后追加一条completed记录。前端渲染器也只为completed条目渲染这保证了侧栏条目数 子代理实际调用次数这一可断言事实。三、后端调用链与运行拓扑源码佐证在进入验证步骤前先厘清一次用户请求在仓库中的完整调用链前端CopilotKitprovider 以agentsubagents绑定运行时page.tsxroute.ts 为每个注册的 agent 名构造HttpAgent将subagents映射到${AGENT_URL}/subagents即 Python 后端:8000上的路径registry.py 中subagents: AgentSpec(subagents_root_agent)完成注册agent_server.py遍历该注册表为每个条目挂载一个 ADKAgent 中间件后端核心 subagents_agent.py 定义 supervisor 与三个子代理工具。supervisor 的定义位于 subagents_agent.py 的# region[subagent-setup]区块subagents_root_agent LlmAgent( nameSubagentsSupervisor, modelget_model(_SUB_MODEL), # _SUB_MODEL gemini-3.1-flash-lite instruction_SUPERVISOR_INSTRUCTION, tools[research_agent, writing_agent, critique_agent], after_model_callbackstop_on_terminal_text, )其中_SUPERVISOR_INSTRUCTION同文件第 235–255 行向模型明确了协作规则对每个非平凡请求按research_agent → writing_agent → critique_agent顺序委派每个子代理对每个用户请求只允许调用一次critique 返回后不得再次调用任何子代理而是整合意见直接给出最终答复若工具结果以[sub-agent error]为前缀则向用户简要说明失败而非编造结果。四、第一组验证基础功能Basic Functionality按 QA 文档顺序逐条执行每项给出对应的前端实现位置页面加载访问/demos/subagents3 秒内完成渲染左侧为 Sub-agent delegations 委派日志面板右侧为CopilotChat。布局由 demo-layout.tsx 实现section承载委派日志aside约 420px承载聊天区。面板标题与计数面板头部应显示 Sub-agent delegations初始计数为0 calls。对应 delegation-log.tsx 中data-testiddelegation-count元素渲染delegations.length。三个角色指示 chips面板顶部渲染 Researcher、Writer、Critic 三个常驻角色 chip未触发时呈暗淡dimmed样式。对应data-testidsubagent-indicators区块内的INDICATOR_ROLES常量与data-fired属性fired ? : opacity-60。空态提示面板主体显示 Ask the supervisor to complete a task. Every sub-agent it calls will appear here.。聊天输入占位符CopilotChat的labels.chatInputPlaceholder为 Give the supervisor a task...见 demo-layout.tsx。Hello 冒烟发送 Hello10 秒内应收到 Agent 回复——验证 supervisor 基础对话链路主 Gemini 调用 工具挂载通畅。五、第二组验证特性专项Feature-Specific Checks5.1 建议药丸Suggestions确认三颗建议 pill 全部可见标题逐字一致Write a blog postExplain a topicSummarize a topic三颗 pill 由 suggestions.ts 通过useConfigureSuggestions({ suggestions, available: always })注册。注意pill 标题与其实际发送给 supervisor 的 prompt 是两套文本——发送的 message 是明确要求先调研、再写作、再评审的完整指令例如{ title: Write a blog post, message: Produce a short blog post about the benefits of cold exposure training. Research first, then write, then critique., }这也解释了为何三颗 pill 最终都会走同一条3 卡片 / 3 委派链路真正驱动流程的是 message 中的顺序指令。5.2 多代理委派Research → Writing → Critique点击 Write a blog post 后在 60 秒内观察聊天流按顺序渲染 3 张内联活动卡片activity card顺序卡片 testid角色1data-testidsubagent-card-researcherResearcher 活动卡片2data-testidsubagent-card-writerWriter 活动卡片3data-testidsubagent-card-criticCritic 活动卡片逐条校验卡片状态机每张卡片依次经历starting → running → done三种状态完成后data-statuscomplete。状态映射来自 subagent-activity-card.tsx 的describeStatus()inProgress → starting、executing → running、complete → done真实结果每张卡片的data-testidsubagent-result内必须包含真实生成的文本——既不能是占位符(empty)也不能是 showcase 的欢迎语模板。前端渲染逻辑为result?.trim() ? result : (empty)侧栏委派条目左侧 Sub-agent delegations 列表出现 3 张data-testiddelegation-entry卡片分别标注 Research / Writing / Critique 角色及对应任务文本Supervisor running 徽章supervisor 运行期间面板头部出现Supervisor running徽章data-testidsupervisor-running带脉冲圆点动画运行结束即消失。实现剖析三张卡片由 page.tsx 中的三次useRenderTool注册——每个子代理工具一个 renderer返回SubAgentActivityCard组件。渲染状态由 CopilotKit v2 运行时随工具调用的生命周期参数流式到达 → 子代理执行 → ToolMessage 返回驱动因此卡片天然呈现参数未到齐等待 → 执行中 → 完成的渐进形态。这正是useRenderTool区别于普通前端组件的地方它把后端工具调用事件流式渲染进聊天流。5.3 Active-Subagent 吸顶横幅委派运行期间聊天面板顶部出现吸顶横幅data-testidactive-subagent-banner实时点名当前正在运行的子代理及其任务supervisor 完成后横幅消失。该横幅由 supervisor-activity-banner.tsx 渲染。当前运行的是谁由前端推断inferActiveSubAgent()见 active-subagent.ts遍历消息流找出最新的、尚未收到工具回复的 assistant 工具调用通过toolCalls与已回复的toolCallId集合对比并解析其task参数——即使参数是流式过程中的部分 JSON也会先尝试严格解析、再退化为正则嗅探task: ...。这一实现刻意采用防御式结构探测以兼容不同运行时版本的消息形状。5.4 Critic 循环回归每次运行恰好一张 Critic 卡片每次点击 pill恰好渲染1 张critic 卡片完成后停留 5 秒计数必须保持稳定若出现第二张 critic 卡片说明 supervisor 重复进入了 critic 阶段属于 bug——QA 文档明确要求按 subagents_agent.py 中单次工具调用指令来定位问题。这条验证项在仓库中有双重防线指令层_SUPERVISOR_INSTRUCTION明确写有 IMPORTANT: call EACH sub-agent EXACTLY ONCE per user request. After critique_agent returns, do NOT call any sub-agent again机制层supervisor 挂载了after_model_callbackstop_on_terminal_text见 shared_chat.py。该回调解决 Gemini 3.1 Flash-Lite 的一个已知怪癖——模型在拿到工具结果后不会自然终止 agentic loop反而会反复重发同一工具调用。回调仅在最终响应含文本且无待处理 function_call、且finish_reasonSTOP时才设置_invocation_context.end_invocation True终止循环从机制上杜绝了 critic 被无限重入。经验若回归复现优先怀疑两个方向——supervisor 指令被模型忽略弱指令或终止回调在流式/thinking 模式下提前/未能触发机制失效。5.5 所有药丸跑同一流程点击 Explain a topic验证同样的 3 卡片 / 3 委派模式点击 Summarize a topic验证同样的 3 卡片 / 3 委派模式。这条验证在 e2e 中各有独立用例详见第八节。其中 Summarize a topic 还是一条已知回归的守护用例该 pill 历史上曾因delegations状态键未声明 reducer 而触发INVALID_CONCURRENT_GRAPH_UPDATEHTTP 400补齐Annotated[..., operator.add]归约器后恢复正常——这正是三张卡片全部到达complete能被当作状态契约健康信号的原因。六、第三组验证错误处理Error Handling空消息 no-op发送空消息不应产生任何请求副作用子代理调用失败若某次 Gemini 子代理调用失败委派日志中仍会新增一条completed记录其result字段包含面向用户的失败信息同时服务端日志保留完整 traceback控制台无未捕获错误正常使用全程不应出现 uncaught console error。实现剖析subagents_agent.py_invoke_sub_agent()捕获宽泛的Exception而非只捕获窄的 API 异常集合目的是让传输层故障超时、httpx.ConnectError、任务取消引发的RuntimeError也不会压垮 supervisor 的工具调用统一改写为_SubAgentError重新抛出_delegate()捕获_SubAgentError后向delegations追加一条completed记录result为错误消息并以[sub-agent error] ...前缀的纯文本返回给 supervisor。这样成功与失败在前后端看到的是同一种数据形状渲染器无需单独的失败分支一个值得注意的安全细节面向用户的错误消息只暴露异常类名如sub-agent call failed: ConnectError而非str(exc)全文——因为 Gemini SDK 的异常文本可能携带 URL、请求 ID、部分凭证或配额信息而该集成包在 manifest.yaml 中声明deployed: true这些文本会被公开 Railway URL 接收。完整 traceback 通过logger.exception仅保留在服务端日志中空响应的兜底无候选safety blocked、candidates[0].content为 None、parts 为空、拼接后文本为空均会抛出_SubAgentError不会把空字符串当作成功结果写进日志。七、预期结果Expected Results验收结束时应同时满足以下全部条件预期结果验证方式聊天在 3 秒内加载完成首张委派卡片在 60 秒内出现基础功能 特性专项每次点击 pill3 个子代理各自恰好触发一次多代理委派 Critic 循环回归卡片结果是真实生成文本而非占位或模板文案subagent-result内容校验侧栏与内联聊天通过state[delegations]保持同步3 卡片 ↔ 3 delegation-entry 一一对应无控制台错误、无卡死状态、无 critic 循环回归错误处理 5 秒停留观察八、自动化回归QA 清单 ↔ Playwright e2e 用例QA 文档的手工步骤与 tests/e2e/subagents.spec.ts 存在清晰的对应关系建议两者配合使用e2e 用例对应的 QA 清单条目page loads with composer, 3 pills, and 3 subagent indicators基础功能 1–5 建议药丸Write a blog post pill produces 3 subagent cards with non-boilerplate results多代理委派 真实结果校验Explain a topic pill produces 3 subagent cards…全部药丸同一流程Summarize a topic pill produces 3 subagent cards (regression: delegations reducer)全部药丸同一流程 归约器回归Critic runs exactly once per pill click and stays done (no loop)Critic 循环回归含 5 秒 dwelle2e 测试中两个值得借鉴的断言策略先等状态、再断内容waitForAllCardsDone()先等三张卡片可见且data-statuscomplete90 秒超时再断言结果文本——因为结果div只在状态到达complete后才挂载防模板泄漏BOILERPLATE_FRAGMENTS常量Hi there! Im your showcase assistant 等用于断言子代理结果绝不回显聊天欢迎语——这守护的是历史上 Writer/Critic 卡片泄漏 showcase 简介文案的 bug。运行方式与仓库内其他集成包一致通过 Playwright 配置驱动playwright.config.ts夹具与消息流可在 aimock 代理中按 pill 链路回放e2e 注释中引用的夹具即服务于此目的。九、常见问题排查速查页面加载超过 3 秒 / 卡片 60 秒内未出现先查/api/copilotkitGET 返回的agent_status是否为reachable再确认GOOGLE_API_KEY是否设置后端未设置时会退化为请求期结构化错误Critic 出现第二张卡片确认 supervisor 指令中的EXACTLY ONCE约束未被模型违背并确认stop_on_terminal_text回调正常工作注意不要重新添加ADK_DISABLE_PROGRESSIVE_SSE_STREAMING环境变量——entrypoint.sh 中已注明该开关会抑制后端工具返回后的 LLM 再调用直接破坏 research → writing → critique 链条子代理结果为空或为模板文案检查subagent-result渲染分支与工具 renderer 的status传递并结合 e2e 的BOILERPLATE_FRAGMENTS断言定位是渲染问题还是后端空响应侧栏与聊天不同步验证delegations状态槽位的前后端契约——后端只追加completed条目前端仅订阅OnStateChanged/OnRunStatusChanged后读取agent.state.delegations。以上即完整 QA 执行基线。它既能作为新环境部署 Sub-Agents Demo 后的首次人工验收流程也可作为后续改动尤其是 supervisor 指令、子代理工具或委派状态逻辑的回归检查清单与仓库内 e2e 用例共同构成该多代理特性的质量护栏。【免费下载链接】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),仅供参考