174 lines
9.8 KiB
Markdown
174 lines
9.8 KiB
Markdown
# SuperAgent Open API 连通性基线 Spec
|
||
|
||
| 项 | 内容 |
|
||
| --- | --- |
|
||
| 状态 | Implemented |
|
||
| 日期 | 2026-09-04 |
|
||
| 负责人 | fire-safety-ymd 后端 |
|
||
| 需求来源 | 用户 checkpoint `fire-safety-ymd-superagent-openapi-connectivity` |
|
||
| 关联 Change Request | 无 |
|
||
|
||
## 1. 背景
|
||
|
||
fire-safety-ymd 需要由 Go 后端调用既有 SuperAgent 平台,并在后续让 SuperAgent 通过本项目 MCP 工具查询 PostgreSQL/PostGIS 消防数据。
|
||
|
||
TH Hotel 项目已经验证了“创建 Open Agent Session、流式发送消息、解析公开 Trace、严格判断完成状态和断流恢复”的调用形态。本 checkpoint 只迁移协议经验和安全边界,使用 Go 独立实现,不复制 Java、酒店业务、AgentBus、邮件、OSS 或任务结果写入逻辑。当前 SuperAgent 外部应用策略关闭了 Trace:同一 Key 使用 `include_trace=true` 返回 HTTP 403、Provider code 为 `open_agent_trace_disabled`,使用 `include_trace=false` 返回 HTTP 200,因此本项目默认采用无 Trace 模式,同时保留显式 Trace 开关。
|
||
|
||
## 2. 目标
|
||
|
||
- 建立独立、可测试的 Go SuperAgent Open API Adapter。
|
||
- 分离 `CreateSession` 与 `StreamMessage`,为后续一个本地对话复用一个 SuperAgent Session 做准备。
|
||
- 使用严格 SSE 成功条件,拒绝部分回答和不完整协议结果。
|
||
- 通过 `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE` 选择无 Trace 或公开 Trace;两种模式均不返回部分答案。
|
||
- 初始 SSE 断流后通过既有 Run 恢复,不重新发送原始消息。
|
||
- 提供默认关闭的 CLI 连通性探针,只发送固定无敏感信息消息。
|
||
- 所有自动化测试使用本地模拟 Provider,不需要真实 Secret 或网络。
|
||
|
||
## 3. 非目标
|
||
|
||
- 不实现浏览器或业务聊天 API。
|
||
- 不持久化本地会话与 SuperAgent Session 的映射。
|
||
- 不实现 `/mcp` endpoint 或消防工具。
|
||
- 不连接 PostgreSQL/PostGIS。
|
||
- 不创建或配置 SuperAgent Profile、外部应用、API Key 或 MCP Server。
|
||
- 不把 SuperAgent 输出写入消防业务事实。
|
||
|
||
## 4. 用户与场景
|
||
|
||
当前用户是开发和联调人员:在安全配置测试环境后,通过 CLI 探针验证 Go 服务能创建 Session、发送无敏感信息消息并取得严格完成的最终回答。
|
||
|
||
后续的用户对话 API v1 已在独立 Spec 中实现对该 Adapter 的复用、单进程会话映射、并发冲突和客户端 SSE;真实身份、持久化与主动取消仍需另行设计。
|
||
|
||
## 5. Definition of Ready
|
||
|
||
- 目标与非目标已确认:是。
|
||
- 协议基线已确认:以 TH Hotel 仓库保存的 2026-07-12 SuperAgent Open API 文档和当前实现为输入,真实环境上线前重新验证。
|
||
- 权限和安全边界已确认:Secret 仅由本项目环境变量注入;没有用户业务数据进入探针。
|
||
- Trace 策略已确认:默认无 Trace;如需 `include_trace=true`,外部应用必须允许 `trace_policy.enabled=true`。
|
||
- 外部依赖已确认:实现只使用 Go 标准库。
|
||
- 未确认问题已列出:Profile、外部应用、scope、真实 Base URL 和 API Key 均由平台管理员后续提供。
|
||
|
||
## 6. 协议与客户端契约
|
||
|
||
### 6.1 创建 Session
|
||
|
||
```text
|
||
POST /api/open/agent-sessions
|
||
```
|
||
|
||
请求包含:
|
||
|
||
- `external_subject_id`:调用方提供的稳定、非敏感主体标识。
|
||
- `idempotency_key`:创建 Session 的稳定幂等键。
|
||
- `metadata`:不包含 Secret 的关联元数据。
|
||
|
||
客户端接受响应中的 `session_id`,并兼容 `id` 字段。
|
||
|
||
### 6.2 流式发送消息
|
||
|
||
```text
|
||
POST /api/open/agent-sessions/{session_id}/messages/stream?include_trace=false
|
||
```
|
||
|
||
`include_trace` 由 `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE` 控制,默认值为 `false`;只有外部应用
|
||
策略明确开启 Trace 时才设置为 `true`。请求包含 `message`、稳定 `idempotency_key` 和安全
|
||
`metadata`。Session ID 由上层明确传入,Adapter 不在每条消息前隐式创建新 Session。
|
||
|
||
### 6.3 鉴权与关联 Header
|
||
|
||
- `Authorization: Bearer <Open API Key>`
|
||
- `X-Request-ID: <稳定请求关联 ID>`
|
||
- `X-CSRF-Token` 与 `Cookie: csrf_token=...` 使用同一个每请求随机值。
|
||
- SSE 使用 `Accept: text/event-stream` 和 `Cache-Control: no-cache`。
|
||
|
||
## 7. SSE 成功与恢复规则
|
||
|
||
一次调用只有满足对应模式的严格条件才成功:
|
||
|
||
- 无 Trace(`include_trace=false`):收到历史 `messages`/`values` 中最终 AI 消息,且其
|
||
`response_metadata.finish_reason=stop`,同时收到非空顶层 `event: message.final` 和顶层
|
||
`event: end`;最终回答只采用 `message.final.text`。
|
||
- Trace(`include_trace=true`):收到最终内容(优先 `message.final`,兼容累计
|
||
`message.delta` 和历史 `messages`/`values` AI 消息)、`run.completed` 且 `status=success`,
|
||
并收到顶层 `event: end`。
|
||
- 两种模式都不能收到顶层 `error` 或 `run.failed`;断流、缺少必要条件或协议错误不得返回部分答案。
|
||
|
||
无 Trace 不向调用方返回公开工具/步骤轨迹,但只控制 Trace 暴露和完成判定,不禁止 SuperAgent
|
||
在执行中调用已配置的 MCP 工具。是否实际调用工具仍须使用完整对话和 MCP 服务日志验收。
|
||
|
||
解析器必须支持 `event:`、多行 `data:`、`id:`、心跳注释和空行分帧,并按 SSE event ID 去重。
|
||
|
||
初始流提前结束时:
|
||
|
||
- 不重新 POST 消息。
|
||
- 从 `Content-Location` 获取同源 Run URL;必要时使用已解析的 Run ID 构造 URL。
|
||
- 查询 Run 状态,再订阅 `{run_url}/events`。
|
||
- 恢复请求携带 `Last-Event-ID`。
|
||
- 使用有上限的指数退避并服从调用方 context 取消。
|
||
- 恢复耗尽或进入失败终态时返回明确错误,不返回部分答案。
|
||
|
||
## 8. 配置契约
|
||
|
||
| 环境变量 | 默认值 | 说明 |
|
||
| --- | --- | --- |
|
||
| `FIRE_SAFETY_SUPERAGENT_ENABLED` | `false` | 总开关,默认不调用真实 Provider |
|
||
| `FIRE_SAFETY_SUPERAGENT_BASE_URL` | 空 | SuperAgent Open API Base URL |
|
||
| `FIRE_SAFETY_SUPERAGENT_OPEN_API_KEY` | 空 | Secret,启用时必填 |
|
||
| `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE` | `false` | 是否请求公开 Trace;`true` 要求外部应用策略开启 `trace_policy.enabled` |
|
||
| `FIRE_SAFETY_SUPERAGENT_CONNECT_TIMEOUT` | `15s` | 建连超时 |
|
||
| `FIRE_SAFETY_SUPERAGENT_RECOVERY_MAX_ATTEMPTS` | `5` | SSE 恢复最大次数;最大可配置为 20 |
|
||
| `FIRE_SAFETY_SUPERAGENT_RECOVERY_INITIAL_BACKOFF` | `250ms` | 首次恢复退避 |
|
||
| `FIRE_SAFETY_SUPERAGENT_MAX_MESSAGE_BYTES` | `65536` | 单条消息 UTF-8 字节上限;最大可配置为 16 MiB |
|
||
| `FIRE_SAFETY_SUPERAGENT_PROBE_SUBJECT_ID` | 固定探针主体 | 仅 CLI 探针使用 |
|
||
| `FIRE_SAFETY_SUPERAGENT_PROBE_TIMEOUT` | `10m` | 探针总超时 |
|
||
|
||
启用时配置缺失或不合法必须启动失败;错误不得包含 API Key。
|
||
|
||
## 9. 安全规则
|
||
|
||
- 不读取 TH Hotel 的环境变量或 Secret,不共享 API Key。
|
||
- Base URL 必须是绝对 HTTP/HTTPS URL,且不得带 userinfo、query 或 fragment。
|
||
- `Content-Location` 和恢复 URL 必须与配置 Base URL 同源,防止向其他主机转发 Authorization。
|
||
- 错误只暴露安全状态和经过限制的 Provider error code,不返回响应正文。
|
||
- 客户端不记录消息、Header、Cookie、API Key 或 SSE 原始数据。
|
||
- Probe 使用固定安全消息;不得用它发送真实火情、联系人或生产数据。
|
||
|
||
## 10. 需求追踪表
|
||
|
||
| 需求项 | 后端状态 | 测试状态 | 文档位置 | 当前状态 |
|
||
| --- | --- | --- | --- | --- |
|
||
| 环境配置与安全默认值 | Done | Passed | 本文第 8 节 | Implemented |
|
||
| CreateSession | Done | Passed | 本文第 6.1 节 | Implemented |
|
||
| StreamMessage 与按模式严格成功条件 | Done | Passed | 本文第 6.2、7 节 | Implemented |
|
||
| SSE 断流恢复 | Done | Passed | 本文第 7 节 | Implemented |
|
||
| CLI 探针 | Done | Automated passed;2026-09-06 live no-Trace passed | 项目集成指南 | Verified |
|
||
|
||
## 11. 验收标准
|
||
|
||
- Given 未启用 SuperAgent,When 执行真实调用,Then 返回受控禁用错误且不发起网络请求。
|
||
- Given 配置完整,When 创建 Session,Then请求具备鉴权、幂等、关联和 CSRF Header,且能解析 Session ID。
|
||
- Given `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE=false` 且收到 `finish_reason=stop`、非空顶层 `message.final` 与 `end`,Then 返回 `message.final.text` 和安全元数据,不要求 `run.completed`。
|
||
- Given `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE=true` 且同时收到最终内容、成功完成和 `end`,Then 返回最终回答与安全元数据。
|
||
- Given 对应模式缺少任一必要成功条件,When 无法恢复,Then 返回协议错误且不返回部分回答。
|
||
- Given 初始 SSE 提前结束且存在 Run URL,When 恢复,Then只 GET Run/events、携带 `Last-Event-ID`,消息 POST 次数仍为 1。
|
||
- Given未设置真实环境变量,When 运行全部测试,Then 不访问外网且测试通过。
|
||
|
||
## 12. 测试范围
|
||
|
||
- 配置默认值、合法值和错误值。
|
||
- Session 请求路径、Header、CSRF、请求体和响应解析。
|
||
- 无 Trace 的历史 messages/values 最终 AI 消息、`finish_reason=stop`、非空顶层 `message.final` 和顶层 `end`。
|
||
- Trace SSE 的最终内容、`run.completed(status=success)`、历史 messages/values 兼容、事件 ID 去重和多行 data。
|
||
- 缺少 final/completed/end、顶层 error、run.failed 和非法 JSON。
|
||
- 提前 EOF 恢复、Last-Event-ID、同源 URL 和不重复 POST。
|
||
- HTTP 非 2xx、超大控制响应和 context 取消。
|
||
|
||
## 13. Definition of Done
|
||
|
||
- 实现满足本文契约。
|
||
- `gofmt`、`go test ./...` 和 `go vet ./...` 通过。
|
||
- 没有真实 Secret、用户数据、构建产物或无关用户变更。
|
||
- 项目索引、集成指南、安全边界和 `PROJECT_STATE.md` 已同步。
|
||
- 默认无 Trace 能在不开放 `trace_policy` 时完成严格成功判定;Trace 模式仍保留 `run.completed` 成功门禁。
|
||
- 真实环境未配置时明确说明未做 live connectivity test。
|