Files
social-app/docs/protocols/ui/data-flow.md
T

4.7 KiB
Raw Blame History

前后端数据流通指南(Agent Chat)

本文档仅描述当前后端实现的 runs/events/history 数据流,不定义视觉细节。


1) 总体流程

  1. 客户端 POST /api/v1/agent/runs 提交 RunAgentInput
  2. 后端返回 202 + taskId/threadId/runId/created
  3. 客户端 GET /api/v1/agent/runs/{threadId}/events 订阅 SSE
  4. 后端输出 AG-UI 事件(如 RUN_STARTEDTOOL_CALL_RESULTTEXT_MESSAGE_END
  5. 客户端按需 GET /api/v1/agent/history 拉取历史快照(按天)

2) /runs 请求与响应

请求

  • Body: RunAgentInput
  • user message 可为纯文本,也可为文本+binary(图片 URL)

响应

{
  "taskId": "...",
  "threadId": "...",
  "runId": "...",
  "created": true
}

created 语义:是否在本次请求中创建了新会话。


3) /runs/{threadId}/events 事件流

SSE 形式

id: <stream-id>
event: <EVENT_TYPE>
data: <json>

事件类型

docs/protocols/agent/sse-events.md 为准。当前重点是:

  • 运行生命周期:RUN_STARTED / RUN_FINISHED / RUN_ERROR
  • 阶段:STEP_STARTED / STEP_FINISHED
  • 工具:TOOL_CALL_START / TOOL_CALL_ARGS / TOOL_CALL_END / TOOL_CALL_RESULT
  • 文本完成:TEXT_MESSAGE_END

文本流策略

当前后端不提供 token 级 TEXT_MESSAGE_CONTENT 增量流作为主路径; 而是在 worker 完成后通过 TEXT_MESSAGE_END 一次性携带完整语义结果。


4) /history 快照

GET /api/v1/agent/history 返回 HistorySnapshotResponse

{
  "scope": "history_day",
  "threadId": "...",
  "day": "2026-03-16",
  "hasMore": false,
  "messages": []
}

说明:

  • 这是普通 JSON 响应,不是 SSE 事件包装。
  • messages 已按 seq 升序组织。
  • before 采用 YYYY-MM-DD,语义是向更早日期翻页。

5) events 与 history 的一致性机制

5.1 语义来源一致

两条链路都来自同一运行时输出(worker/tool output)及其持久化元数据。

5.2 UI 编译器一致

两条链路都使用后端 ui_compiler.compile(...)toolui_hints 编译为可渲染结构:

  • events:在 runtime 发送事件前编译,字段名为 ui_schema
  • history:在历史转换时编译,字段名为 ui_schema

tool 结果走 UI 编译链路:TOOL_CALL_RESULT 在保留 tool_call_args + result 的同时可携带 ui_schema

  • metadata.tool_agent_output 是 tool 消息的完整信源(用于 runtime observation 与 history replay)。
  • message.content 保持轻量摘要(当前等于 result)。
  • tool_call_args 记录输入参数,result 记录输出事实,二者不做冗余重复。

5.3 当前命名差异(实现现状)

两条链路字段命名已统一:

  • events: ui_schemasnake_case
  • history: ui_schemasnake_case

6) 推荐消费顺序(面向客户端重构)

  1. 先以 /history 获取首屏快照
  2. 再接入 /events 处理后续增量
  3. runId + messageId/toolCallId 做去重与合并
  4. 统一消费 ui_schema

7) Navigation Action 数据流(ui_schema.actions

7.1 后端生成

  • runtime 基于 tool 输出中的 ui_hints.action.type = navigation 产出导航动作。
  • 编译后在 ui_schema 中保持 action.type = navigationaction.pathaction.params
  • 路由由工具能力直接给出 concrete pathagent 本身不需要维护 route_id 概念。

7.2 前端消费(统一解析规则)

  • type = navigation,前端仅走一条解析路径:
    1. 读取 path 作为内部路由目标;
    2. params 仅视为 query 参数(不用于 path 模板替换);
    3. 执行 GoRouter 跳转(建议 context.go(...))。
  • path 必须是已落地页面路由,且应是已实参化路径(如 /todo/123,而非 /todo/:id)。

7.3 路由表达粒度(Route-First 约束)

  • 关键业务动作(创建、编辑、分享、处理邀请等)应优先设计为可深链页面路由,而不是仅存在于临时弹层。
  • 若 UI 采用 sheet 风格展示,也应由页面路由承载状态,再以页面内 surface 呈现 sheet 视觉。
  • todo.edit 必须落地为独立子页面(/todo/{id}/edit),不应通过详情页内弹窗承载编辑主流程。
  • 推荐工具能力优先输出以下 concrete path(示例):
    • /calendar/events/new
    • /calendar/events/{id}/edit
    • /calendar/events/{id}/share
    • /todo/new
    • /todo/{id}/edit

7.4 约束建议

  • 为了让前端只保留一种解析逻辑,推荐强约束:
    • path 只接受内部路由;
    • params 只接受标量值(string/number/boolean);
    • 禁止在 params 里放嵌套对象数组。