新闻详情

新闻详情

首页 / 资讯中心 / 详情

协议之间的梳理

发布时间:2026/9/2 6:30:16来源:尧图网络
协议之间的梳理
需要确认 agent 模式的图结构和/agui端点挂载方式全链路已完整掌握。梳理如下Agent 模式全链路数据流5 段 4 协议┌──────────────────────────────────────────────────────────────┐ │ 小程序前端 │ │ GenUITransport.ts (Taro SSE 客户端) useAGUI.ts (事件分发) │ └──────────────────────────────────────────────────────────────┘ │ ① AG-UI over SSEHTTP POST /agui ▼ ┌──────────────────────────────────────────────────────────────┐ │ Supervisoragent 模式 │ │ create_agent ReAct 单节点循环 2 个工具 │ └──────────────────────────────────────────────────────────────┘ │ ② A2A over HTTPJSON-RPC 2.0message/send ▼ ┌──────────────────────────────────────────────────────────────┐ │ 子 Agentcanteen / transport │ │ 各自的 LangGraph 图 MCP 工具 │ └──────────────────────────────────────────────────────────────┘ │ ③ MCP子 Agent 内部调工具对 supervisor 不可见 ▼ 数据源ES / Redis / 业务 API① 前端 → SupervisorAG-UI 协议SSE端点POST http://supervisor/agui请求体GenUITransport.ts:285-294{ threadId: tke-test-xxx, runId: run-001, messages: [{ id: m1, role: user, content: 推荐几道辣的菜 }], tools: [], state: { messages: [] }, context: [], forwardedProps: { langgraph_config: {} }, user: { id: u1, name: Alice } }响应text/event-stream流式事件每帧data: {...}\n\n关键点前端用Taro.request({ enableChunked: true })onChunkReceived收字节流自己做字节级缓冲按\n\n切分GenUITransport.ts:227-267。② Supervisor 内部LangGraph ReAct 循环Agent 模式下没有 planner/dispatcher/reflector 节点就一个 ReAct 节点死循环graph create_agent( modelllm, tools[single_tool, parallel_tool], middleware[_UserContextInjectorMiddleware(), _DoneCallBreakerMiddleware()], # type: ignore[list-item] state_schemaSupervisorAgentState, # type: ignore[arg-type] system_prompt_SYSTEM_PROMPT, checkpointercheckpointer, ) return graph.with_config(recursion_limit50)只有 2 个工具工具用途call_domain_agent调单个子 Agentorchestrate_parallel并行调多个子 Agent循环过程LLM 思考 → 决定调 call_domain_agent → 执行工具 → 结果回喂 LLM → 再思考 → 决定 orchestrate_parallel → ... → 最终输出文本 → 结束两个中间件防止死循环你们之前修的_UserContextInjectorMiddleware注入用户上下文位置等_DoneCallBreakerMiddleware同一 query 重复调用直接掐断③ Supervisor → 子 AgentA2A 协议JSON-RPC 2.0不是 SSE是一次性 HTTP POST。请求 envelopesub_provider.py:257-268{ jsonrpc: 2.0, id: sup-a1b2c3d4, method: message/send, params: { message: { role: user, parts: [{ text: 推荐几道辣的菜 }], message_id: uuid, context_id: thread-abc, metadata: { user_context: {\userId\:\...\,\location\:{...}}, currentLocation: { lat: 22.5, lng: 113.9 }, locationPermission: granted, session_id: thread-abc } } } }请求头Content-Type: application/json Authorization: Bearer delegated_token ← RFC 8693 token exchange Idempotency-Key: sup-随机UUID ← ⚠️ 目前是随机的无幂等保护 traceparent: ... ← OTel 链路追踪服务发现先查 Nacos 拿子 Agent 的ip:port再直连http://{ip}:{port}/a2a④ 子 Agent → SupervisorA2A 响应响应结构sub_provider.py:299-327解析逻辑{ jsonrpc: 2.0, id: sup-a1b2c3d4, result: { task: { id: task-xxx, status: { state: completed, // completed / failed / error / rejected message: { parts: [{ text: 为你推荐 3 道辣味菜品 }] } }, metadata: { // ⭐ 卡片在这里 card_template_id: dish_cards, card_data_model: { /* 卡片数据 */ }, card_category: recommend, bubble_text: 为你推荐 3 道辣味菜品, trace_id: xxx } } } }Supervisor 解析成DispatchResultsub_provider.py:320-327resultDispatchResult(agentagent_name,okTrue,contenttext,card_typeresolve_card_type(raw_ct)ifraw_ctelseNone,card_datameta.get(card_data_model)ormeta.get(card_data),card_categorymeta.get(card_category),bubble_textmeta.get(bubble_text),trace_idmeta.get(trace_id),)失败路径3 种都返回okFalseHTTP ≥ 300 →errorhttp_xxxtask.status.state∈ {failed, error, rejected} →errora2a_state_xxx其他异常 → Fail-Safe 捕获⑤ 卡片数据变身从card_data到a2ui_operations关键转换发生在工具内部orchestrator.py:467-479opsrender_card(ct,cd)# 卡片模板 数据 → A2UI 渲染指令returnjson.dumps({done:True,summary:summary,card_template_id:ct,card_data_model:cd,a2ui_operations:json.loads(ops)[a2ui_operations],# ⭐},ensure_asciiFalse)这个 JSON 字符串作为工具返回值→ 自动成为 LangGraph state 里的ToolMessage。⑥ Supervisor → 前端AG-UI SSE 事件流/agui端点由 copilotkit 注册main.py:261-270底层用ag_ui_langgraph把 LangGraph 原生事件翻译成 AG-UI 标准事件add_langgraph_fastapi_endpoint( appapp, agentLangGraphAGUIAgent( namesupervisor, descriptionf园区中枢编排mode{settings.mode}, graphgraph, config{recursion_limit: 50}, ), path/agui, )事件翻译对照表LangGraph 原生事件→AG-UI 事件前端是否用on_chain_start/end→RUN_STARTED/RUN_FINISHED✅ 用on_chat_model_stream→TEXT_MESSAGE_*❌前端跳过392 行 breakon_chat_model_*→RAW事件透传❌ 前端跳过on_chain_stream/end(model 节点)→RAW事件透传✅前端从这里取文本307/349 行状态变更→STATE_SNAPSHOT❌ 前端没处理—→ACTIVITY_SNAPSHOT⚠️前端只认这个取卡片253 行前端实际使用的两条通道文本RAW 事件 → on_chain_stream/on_chain_end(nodeNamemodel) → 读 data.chunk[].update.messages[].contenttypeai → useAGUI.ts:307-388 卡片ACTIVITY_SNAPSHOT → content.a2ui_operations → useAGUI.ts:253-296 → ⚠️ 后端从不发这个事件 → operations 为空 → 268 行 break → 卡片消失 协议断链点一句话后端把卡片包在 ToolMessage 的 content 里ToolMessage 只会出现在STATE_SNAPSHOT.snapshot.messages/MESSAGES_SNAPSHOT.messages但前端卡片只从ACTIVITY_SNAPSHOT取 —— 两者对不上。三种修法方案改谁说明A. 前端加读快照推荐前端 20 行从 STATE/MESSAGES_SNAPSHOT 的最后一条 tool 消息JSON.parse出a2ui_operationsB. 后端改发 ACTIVITY_SNAPSHOTsupervisor需 hack copilotkit 事件层影响面大C. 后端发 CustomEventsupervisor发一个自定义事件专门承载卡片前端多接一个 case数据流全景图卡片的一生① 用户推荐几道辣的菜 ↓ ② 前端 POST /aguiAG-UI 请求 ↓ ③ Supervisor ReActLLM 决定调 call_domain_agent(canteen-agent, 推荐辣的菜) ↓ ④ A2A JSON-RPC POST → canteen-agent /a2a ↓ ⑤ canteen 内部 LangGraph 跑图 → MCP 查 ES → 生成 final_ui_cards ↓ ⑥ canteen 返回 A2A 响应metadata.card_data_model 卡片数据 ↓ ⑦ supervisor 解析成 DispatchResultcard_type card_data ↓ ⑧ render_card(card_type, card_data) → a2ui_operationsA2UI 渲染指令 ↓ ⑨ 工具返回 JSON 字符串 → 成为 ToolMessage 进 messages ↓ ⑩ ag_ui_langgraph 翻译 LangGraph 事件 → SSE ↓ ⑪ STATE_SNAPSHOT.messages 里有那条 ToolMessage卡片在这 ↓ ⑫ 前端只查 ACTIVITY_SNAPSHOT → 空的 → ❌ 卡片不渲染之前的输出需要修正——我漏看了useAGUI.ts里第二条卡片通道RAW 事件内嵌 A2UI JSON。完整重读关键发现前端有三条卡片通道我之前只说了一条。查证后端 render_card 支持的卡片类型与前端白名单是否匹配查证两侧卡片类型白名单是否一致——这是断链的关键找到根因了。canteen 返回的card_type是stall_cards/dish_cards/canteen_cards/canteen_heatmap对比两端白名单全部查证完毕。以下是结合前端代码修正后的完整版本——我上一轮说后端从不发 ACTIVITY_SNAPSHOT卡片永远不渲染是错的实际前端有 3 条卡片通道。Agent 模式全链路数据流修正版总览4 段链路4 种协议┌─────────────────────────────────────────────┐ │ ① 前端 ←→ Supervisor AG-UI (SSE) │ │ ② Supervisor 内部 LangGraph ReAct │ │ ③ Supervisor ←→ 子 Agent A2A (JSON-RPC) │ │ ④ 子 Agent 内部 MCP │ └─────────────────────────────────────────────┘① 前端 → SupervisorAG-UI over SSE代码GenUITransport.ts:277-294POST http://supervisor/agui Content-Type: application/json Accept: text/event-stream{ threadId: tke-test-xxx, runId: run-001, messages: [{ id: m1, role: user, content: 推荐几道辣的菜 }], state: { messages: [] }, forwardedProps: { langgraph_config: {} } }前端收包Taro.request({ enableChunked: true })onChunkReceived字节级缓冲按\n\n切分GenUITransport.ts:227-267——因为 TCP 可能把 UTF-8 中文切两半。② Supervisor 内部LangGraph ReAct 单节点循环graph create_agent( modelllm, tools[single_tool, parallel_tool], middleware[_UserContextInjectorMiddleware(), _DoneCallBreakerMiddleware()], state_schemaSupervisorAgentState, system_prompt_SYSTEM_PROMPT, checkpointercheckpointer, ) return graph.with_config(recursion_limit50)只有 2 个工具call_domain_agent单 Agent、orchestrate_parallel多 Agent 并行。没有planner / dispatcher / reflector 节点——那是 workflow 模式才有的。③ Supervisor → 子 AgentA2AJSON-RPC 2.0代码sub_provider.py:257-268{ jsonrpc: 2.0, id: sup-a1b2c3d4, method: message/send, params: { message: { role: user, parts: [{ text: 推荐几道辣的菜 }], context_id: thread-abc, metadata: { user_context: {\userId\:\...\,\location\:{...}}, currentLocation: { lat: 22.5, lng: 113.9 }, session_id: thread-abc } }} }请求头Authorization: Bearer delegated_tokenRFC 8693 换发、Idempotency-Key: sup-随机UUID⚠️ 目前无幂等、traceparentOTel服务发现Nacos 查到ip:port→ 直连http://{ip}:{port}/a2a④ 子 Agent → Supervisor卡片数据的诞生canteen 内部跑完自己的图_prepare_a2ui_node产出final_ui_cards每个 card 的key是mapped: dict[str, Any] { key: key, surface_id: { canteen_cards: canteen-card-list, stall_cards: stall-card-list, dish_cards: dish-card-list, canteen_detail_card: canteen-detail-card, stall_detail_card: stall-detail-card, review_cards: review-card-list, }[key], data: data,A2A 响应里卡片放在task.metadata{ result: { task: { status: { state: completed, message: { parts: [{ text: 为你推荐 3 道菜 }] } }, metadata: { card_template_id: dish_cards, // ⭐ 内部 card key card_data_model: { /* 卡片数据 */ }, bubble_text: 为你推荐 3 道辣味菜品 } }}}Supervisor 解析sub_provider.py:319-327card_template_id→resolve_card_type()别名归一 →DispatchResult.card_type⑤ Supervisor → 前端AG-UI 事件流核心/agui由 copilotkit 注册main.py:261-270底层ag_ui_langgraph把 LangGraph 原生事件翻译成 AG-UI 事件。前端有 3 条卡片通道 1 条文本通道通道事件代码位置提取逻辑是否真在用文本RAW→on_chain_stream/end(model)useAGUI.ts:307-388data.chunk[].update.messages[].contenttypeai✅主用卡片①ACTIVITY_SNAPSHOTuseAGUI.ts:253-296content.a2ui_operations⚠️ 后端基本不发卡片②RAW→ 任意节点 outputuseAGUI.ts:396-465extractA2UIMessages()从 content 里扒a2ui_operations✅主力通道卡片③RAW→ 卡片 JSONuseAGUI.ts:413-504JSON.parse取card_template_idcard_data_model→generateA2UI()⚠️ 有白名单限制我之前只说了通道①漏了②和③——这是上一轮最大的错误。 真正的断链点修正后卡片②主力需要 JSON 里有a2ui_operations后端orchestrator.py:467-479opsrender_card(ct,cd)# ← 如果返回 None就没有 a2ui_operationsifopsisnotNone:returnjson.dumps({...,a2ui_operations:json.loads(ops)[a2ui_operations]})render_card逻辑a2ui/render.py:27-31schemaload_card_schema(card_type)ifschemaisNone:returnNone# ← 没有对应 schema 就没有卡片关键比对canteen 的 card_type vs supervisor 的 schemacanteen 产出的card_typesupervisorschemas/里有吗别名归一后canteen_heatmap✅ 有canteen_heatmap.jsonheatmap-cardcanteen_menu✅ 有 → 别名 →list-card✅canteen_recommend✅ 有 → 别名 →list-card✅stall_cards❌没有原样返回查不到 →Nonedish_cards❌没有原样返回查不到 →Nonecanteen_cards❌没有原样返回查不到 →Nonecanteen_detail_card❌没有→Nonestall_detail_card❌没有→Nonecontracts.py:18-24证明 canteen 现在主要产出后 5 种_CARD_RULES: list[tuple[tuple[str, ...], str]] [ ((热力图, 拥挤, 客流), canteen_heatmap), ((档口,), stall_cards), ((菜单, 菜品, 有什么菜), dish_cards), ((推荐, 错峰, 午餐, 晚饭, 晚餐, 早餐, 建议, 吃什么), dish_cards), ((有哪些食堂, 有什么食堂, 食堂列表, 可用食堂, 餐厅列表), canteen_cards), ]再看前端通道③的白名单const validTemplateIds: TemplateId[] [list-card, list-pane-card, message-card, identify-card, form-card, heatmap-card, navigation-card] if (templateId cardDataModel validTemplateIds.includes(templateId as TemplateId)) {dish_cards/stall_cards/canteen_cards全都不在白名单里→ 通道③也走不通。 结论三处不匹配卡片必挂canteen 产出 dish_cards / stall_cards / canteen_cards ↓ ① supervisor schemas/ 里没有这 3 个 schema → render_card() 返回 None → 工具返回值里没有 a2ui_operations → 前端通道②拿不到东西 ❌ ② 假设有 card_data_model前端通道③白名单也没有这 3 个 id ❌ ③ 后端发的是 STATE_SNAPSHOT前端通道①只认 ACTIVITY_SNAPSHOT ❌三条路全断所以卡片不显示。可行的修法按成本排序方案改法成本影响面A. 加别名映射supervisorcatalog.py加dish_cards: list-card、stall_cards: list-card、canteen_cards: list-card最低3 行只需确认数据结构与list-cardschema 兼容B. 加新 schemasupervisorschemas/新建dish-cards.json等中需同步前端validTemplateIds白名单C. 前端改读快照useAGUI.ts加 STATE_SNAPSHOT 处理中前端 20 行但卡片数据格式仍需匹配推荐 Acanteen 的dish_cards/stall_cards数据本质都是列表映射到现有list-card最快。前提是先确认card_data_model的字段结构与list-card.json的 dataModel 槽位对得上。要我先验证一下dish_cards的实际数据结构能否塞进list-cardschema 吗
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI图像超分辨率本地部署指南:从环境配置到批量处理实战 2026/9/2 7:21:24

AI图像超分辨率本地部署指南:从环境配置到批量处理实战

这次我们来看一个名为“靠近点……再靠近点……”的项目。从标题来看,这很可能是一个与图像处理、超分辨率或细节增强相关的工具或模型。这类项目通常致力于解决一个核心痛点:如何在不损失质量的前提下,将低分辨率、模糊或细节缺失的图像/视频…

阅读更多 →
基于YOLOv8的考古文物识别系统:从数据标注到桌面应用全流程实践 2026/9/2 7:21:24

基于YOLOv8的考古文物识别系统:从数据标注到桌面应用全流程实践

简介:本资源是一套面向计算机、人工智能及相关专业在校生与初学者的考古文物目标检测实践项目,基于YOLOv8框架构建端到端识别系统,解决文物图像中多类别器物(如陶器、青铜器、玉器等)的自动定位与分类问题,…

阅读更多 →
Python实现微电网两阶段鲁棒优化:CCG算法详解与工程实践 2026/9/2 7:21:24

Python实现微电网两阶段鲁棒优化:CCG算法详解与工程实践

简介:本资源是一套面向计算机及相关专业(如人工智能、数据科学、电子信息、物联网等)本科生与初阶研究者的微电网优化调度实战代码包,聚焦两阶段鲁棒优化这一前沿经济调度方法,完整复现从建模、分解到求解的全流程&…

阅读更多 →
YOLOv8电梯开关状态人员进出检测:从数据集解析到模型训练部署全流程 2026/9/2 7:21:24

YOLOv8电梯开关状态人员进出检测:从数据集解析到模型训练部署全流程

简介:本资源是面向智能楼宇、电梯安全监控与计算机视觉初学者的高质量目标检测数据集,聚焦电梯开关状态及人员进出场景识别任务。数据集共2220张真实场景图像,涵盖4类关键状态:电梯关闭、轿厢内有人、轿厢空载、电梯开启&#xff…

阅读更多 →
基于Fo-Dicom的MPPS与MWL服务可视化工具开发实践 2026/9/2 7:21:24

基于Fo-Dicom的MPPS与MWL服务可视化工具开发实践

简介:本资源是一个基于Fo-Dicom开源库开发的C#可视化DICOM服务程序,面向医学影像系统开发者、PACS工程师及放射科IT支持人员,用于直观实现与调试MPPS(设备执行步骤)和MWL(模态工作列表)两类关键…

阅读更多 →
从点灯到FOC:嵌入式开发者如何突破技术瓶颈实现高薪进阶 2026/9/2 7:18:23

从点灯到FOC:嵌入式开发者如何突破技术瓶颈实现高薪进阶

这次我们来看一个关于嵌入式开发领域职业发展路径的讨论,核心围绕“FOC(Field-Oriented Control,磁场定向控制)”技术的学习价值与“点灯”这类基础技能练习的对比展开。这个话题源于网络上一个引发热议的观点:有同学因…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞