82 lines
3.1 KiB
Markdown
82 lines
3.1 KiB
Markdown
|
|
# 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_agents` 和 `llm` 配置并构建执行流程
|
|||
|
|
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 E2E(`backend/tests/e2e`)
|
|||
|
|
|
|||
|
|
新增 `test_agent_closed_loop_live.py`:
|
|||
|
|
- 标记为 `live`,默认不在 CI 执行。
|
|||
|
|
- 用真实 JWT、真实 HTTP 请求、真实 SSE 订阅。
|
|||
|
|
- 断言最小闭环标准:
|
|||
|
|
- run 返回 202
|
|||
|
|
- SSE 至少收到 `RUN_STARTED` 与终态(`RUN_FINISHED` 或 `RUN_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”路径并保留测试脚本诊断能力。
|