Files
social-app/docs/plans/2026-03-05-agent-runtime-closed-loop-e2e-design.md
T

3.1 KiB
Raw Blame History

Agent Runtime Closed Loop E2E Design

背景

当前 test_agent_sse_flow.py 不能稳定证明真实闭环:

  • session_id 由随机 UUID 生成,导致 POST /api/v1/agent/runs 经常 404。
  • 测试脚本存在不可达重复代码,诊断信息不完整。
  • 未覆盖首聊自动建会话语义,和真实聊天入口不匹配。

目标是验证真实环境下业务闭环是否可用:

  1. 用户请求 agent 路由
  2. 请求进入异步任务
  3. runtime 读取 system_agentsllm 配置并构建执行流程
  4. 真实 LLM 请求发出并返回
  5. sessions/messages 正确落库
  6. 成本和 token 统计正确
  7. 事件按 AG-UI 规范发布并可由 stream_events 订阅

设计原则

  • 真实优先:不使用 mock,不替换 queue/redis/db/llm。
  • 双轨验证:
    • 诊断脚本用于本地排障(快速观察全链路状态)。
    • pytest E2E 用例用于可重复回归。
  • 明确前置条件:必须先使用 infra/scripts/app.sh start 启动 tmux 服务。
  • 本地真实 LLM 基线:DashScope Qwen。

API 契约调整

POST /api/v1/agent/runs

  • 现状:session_id 必填且必须存在。
  • 新契约:session_id 可选。
    • 有值:复用现有会话,校验 owner。
    • 无值:在服务层先创建会话,再入队 run。
  • 响应扩展:返回 created 标识是否为首聊自动建会话。

该契约与聊天产品行为一致:用户首条消息即可开始,不需要前置调用创建会话接口。

数据关系与删除语义

  • messages.session_id -> sessions.id 为外键,且硬删除级联(ondelete=CASCADE)。
  • 软删除需要补齐级联:
    • 软删 sessions 时,同事务更新对应 messages.deleted_at
    • E2E 增加验证,确保软删后默认查询不可见。

测试架构

A. 诊断脚本(根目录)

重构 test_agent_sse_flow.py

  • 增加环境健康检查(web/redis/db)。
  • 支持两种模式:
    • --new-session:不传 session_id,验证首聊自动创建。
    • --reuse-session <id>:验证复聊路径。
  • 输出结构化阶段日志:HTTP、task_id、SSE 事件、数据库断言、失败根因。

B. pytest E2Ebackend/tests/e2e

新增 test_agent_closed_loop_live.py

  • 标记为 live,默认不在 CI 执行。
  • 用真实 JWT、真实 HTTP 请求、真实 SSE 订阅。
  • 断言最小闭环标准:
    • run 返回 202
    • SSE 至少收到 RUN_STARTED 与终态(RUN_FINISHEDRUN_ERROR
    • sessions 状态和计数更新
    • messages 有新增记录
    • token/cost 字段非负且会话聚合一致

验收标准

  • uv run python test_agent_sse_flow.py --new-session 通过。
  • uv run pytest backend/tests/e2e/test_agent_closed_loop_live.py -v -m live 通过。
  • 首聊场景不需要外部先建 session_id
  • 软删除会话后,消息软删除行为与约束一致。

风险与回退

  • 真实 LLM 网络抖动会造成不稳定:通过重试和超时策略降低误报。
  • 生产契约变更风险:保持字段向后兼容(原 session_id 仍可传)。
  • 如果新契约引入问题,可临时退回“必传 session_id”路径并保留测试脚本诊断能力。