Files
fire-safety-ymd/docs/workflows/user-chat.md
2026-09-06 01:40:15 +08:00

6.9 KiB
Raw Blame History

用户对话 API 工作流

1. 首轮对话

客户端向 POST /api/chat 发送 message,不传 conversation_id。服务端创建 SuperAgent Session随后通过 SSE 返回:

  1. conversation:包含新生成的 conversation_idreused=false
  2. 零个或多个 progress:只用于展示运行/工具进度。
  3. message:严格完成后的最终回答。
  4. done:包含同一 conversation_id、安全 Run ID 和 token usage。

客户端只有在收到 done 后才把本轮标记为成功,并保存 conversation_id

2. 受控测试页面

FIRE_SAFETY_CHAT_PAGE_ENABLED=trueGo 服务提供 GET /chatGET /chat/。页面只 用于测试,不是新的对话协议或生产用户入口;关闭开关时两个路径都返回 404。Nginx 可以保留这 两个精确反代路径,最终是否可用由 Go 开关决定。

页面与既有第三方客户端使用完全相同的兼容接口:

页面 GET /chat/
  -> 同源 POST /api/v1/apps/<FIRE_SAFETY_CHAT_COMPAT_APP_ID>/completion
  -> xtoken + input.prompt + parameters
  -> event: result SSE

页面打开后由用户手动输入受控测试 xtoken。页面不在 HTML、JavaScript 常量、Cookie、URL、 localStorage 或 sessionStorage 中嵌入/保存 Token也不把 Token 发送到除同源 completion 之外 的地址;页面只在当前 JavaScript 内存中使用它。首轮返回的 output.session_id 也只保存在页面 内存中,并在同一页面的后续请求中作为 input.session_id 发送。刷新、关闭或新开页面都会丢弃 Token 和 Session。

浏览器页面的 Origin 是 https://agent.nianxx.com,所以服务器配置 FIRE_SAFETY_CHAT_ALLOWED_ORIGINS 必须包含该精确值,不得用 *。页面 GET 本身不要求 Token 但 completion 仍由 Go 校验 xtoken;静态测试 Token 不是最终用户认证。

页面验收时打开 https://agent.nianxx.com/chat/,输入测试 Token 和不含敏感信息的问题。浏览器 Network 应显示同源 POST 到精确 app ID 的 completion 路径Request Headers 含 xtoken,请求 体为兼容 JSON响应为 event: result SSE。只有 output.finish_reason=stop 才算本轮成功;再 发送第二个问题时,应在第二次请求中看到上一轮返回的 session_id 被放入 input.session_id。不要把初始 finish_reason=null 或 断流内容当作最终答案。

页面客户端看到的成功契约不随上游 Trace 开关变化,始终以兼容流最后的 output.finish_reason=stop 为准。服务端到 SuperAgent 的严格判定由 FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE 控制:默认 false 时要求上游最终 AI 消息 finish_reason=stop、非空顶层 message.final 和顶层 event: end;设置为 true 时还要求 run.completed(status=success)。无 Trace 只是不返回工具/步骤轨迹,不代表 SuperAgent 不会 调用 MCP要确认 MCP 是否实际执行,必须同时检查服务日志和工具结果。

3. 后续对话

后续请求同时发送 message 和前一轮保存的 conversation_id。成功流中的 conversation 事件返回 reused=true,说明复用了原 SuperAgent Session 上下文。

同一对话在收到 done 或终止 error 前不得再次提交。若服务端返回 CHAT_CONVERSATION_BUSY,客户端应保留当前流并稍后重试,不能自动改用同一个问题创建多轮并发 Run。

4. 失败处理

  • HTTP JSON 错误SSE 尚未开始;按 HTTP 状态和 error.code 处理。
  • SSE error:流已经开始,但本轮没有可信最终回答;不得把此前进度当作答案。
  • CHAT_CONVERSATION_NOT_FOUND:会话已过期、服务重启或请求落到其他实例;提示用户上下文已失效,并在用户确认后省略 conversation_id 创建新对话。
  • 上游超时、协议错误、Run 失败或客户端中途断开:当前实现会使会话映射失效,以免继续复用可能仍有活动 Run 的 Provider Session。
  • 网络断开且没有看到 done:结果未知;首版不自动重放原消息,避免重复 Run。

如果上游返回 open_agent_trace_disabled 或 HTTP 403先检查是否将 FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE 设置为 true。当前应用策略关闭 Trace 时,使用 include_trace=true 会被拒绝;同一 Key 使用默认的 include_trace=false 可以返回 HTTP 200。 只有在外部应用策略明确启用 trace_policy.enabled=true 后,才应切换为 true。修改环境变量后 必须重建或重新创建运行容器,不能只依赖 docker compose restart 重新读取配置。

5. curl 联调

先把 .env 显式加载到当前 shell再启动服务Go 程序不会自动读取 .env

set -a
source .env
set +a
go run ./cmd/server

另开终端发起首轮请求:

curl -N \
  -H "Authorization: Bearer ${FIRE_SAFETY_CHAT_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  --data '{"message":"观水镇附近有哪些水源候选?"}' \
  http://127.0.0.1:8080/api/chat

conversationdone 事件复制 ID 后测试下一轮:

curl -N \
  -H "Authorization: Bearer ${FIRE_SAFETY_CHAT_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  --data '{"message":"再说明这些候选的限制","conversation_id":"conv_替换为上一轮返回值"}' \
  http://127.0.0.1:8080/api/chat

浏览器前端还必须把其精确 Origin 加入 FIRE_SAFETY_CHAT_ALLOWED_ORIGINS,例如 http://localhost:5173。静态 Chat Bearer 会被浏览器用户看到,因此只适用于受控联调,不能直接作为公网最终用户鉴权。

6. 既有 DashScope 风格客户端

设置 FIRE_SAFETY_CHAT_COMPAT_APP_ID 后,同一个 Chat Service 还会注册:

POST /api/v1/apps/{FIRE_SAFETY_CHAT_COMPAT_APP_ID}/completion

首轮请求使用 xtoken: ${FIRE_SAFETY_CHAT_AUTH_TOKEN}

curl -N \
  -H "xtoken: ${FIRE_SAFETY_CHAT_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"input":{"prompt":"杨家盘瞭望哨 3 公里内的水源?"},"parameters":{}}' \
  http://127.0.0.1:8080/api/v1/apps/fire-safety-public-app/completion

兼容流先返回 finish_reason: "null" 和本地 session_id,严格成功后返回 finish_reason: "stop" 与最终 text。后续轮次把该 session_id 放入 input.session_id。客户端不得使用 URL 中的 App ID、静态 token 或 session ID推断身份与权限也不得把未出现 stop 的断流结果当作成功答案。

公网 Nginx 示例和完整 curl 见 ../project/operations/nginx-public-entry.md。兼容字段的唯一项目契约见 ../specs/fire-safety-ymd-dashscope-compatible-chat-v1.md。页面开关、Docker 重建、浏览器验收和回滚见 ../specs/fire-safety-ymd-chat-page-v1.md