Files
group_fqcd_jr/docs/05-接口文档.md
T
lzf_0626 6516ccb385 feat: 第二版——接口契约对齐 docs/05,修复静默故障与数据库基线
相对第一版 46fc976 的完整变更。组员迁移对照表见 docs/20。

一、对外契约对齐 docs/05(破坏性,共 4 处,组员需按 docs/20 调整)
1) 配置发布端点改为文档规定的复数资源名:submit→validations、
   approve→reviews(需 body decision)、activate→activations、
   rollback→rollbacks;第一版这 4 个动词式路径 docs/05 从未定义过。
2) 错误码由 8 个笼统码改为 15 个具体语义码(FORBIDDEN→AGENT_PERMISSION_DENIED、
   UNAUTHORIZED→AUTHENTICATION_REQUIRED、CONFLICT→RESOURCE_VERSION_CONFLICT、
   RESOURCE_NOT_FOUND→RUN_NOT_FOUND/SESSION_NOT_FOUND 等),
   输入类错误状态码 400→422。
3) POST /api/v1/agent-runs 与 GET /api/v1/agent-runs/{run_id} 统一为
   {data, meta} 信封(data 内字段名与语义未变)。
4) 错误响应体统一为 {error:{code,message,retryable,field_errors}, meta:{trace_id}},
   不再返回 FastAPI 默认的 {"detail": ...}。

二、数据库基线与约束
新增 39 张表的基线迁移(链根)与联合唯一键纠偏(4 张表、删 8 增 4,幂等收敛);
撤下 config_release 的双人复核 CHECK(应用层已允许自审,审核节点保留,
自审如实写入 reviewer_id);记忆 active key 生成列与唯一键;
activate 开始记录 supersedes_release_id 使版本链可追溯。
docs/00 基线未修改,未重命名或删除任何表与字段。

三、修复会静默出错或无报错的缺陷
- 跑完集成测试后平台会静默失去生效配置:清理只删自己创建的版本,却没有恢复被它
  顶成 superseded 的原生效版本,且审计一并删除因而完全无痕,表现为所有工具被拒
  但没有任何报错。已修清理逻辑并加恢复。
- Worker 单轮异常导致进程退出;记忆抽取调用方的“事务已开始”异常;
  召回缓存丢失 degraded 标记;连接时区未生效导致 created_at/updated_at 差 8 小时;
  .env 与 os.getenv 密钥来源分裂导致“没有可用的已批准模型端点”。
- 记忆信号识别漏判与跨键误命中;SSE 未带 Accept 的协商行为。

四、功能补齐
记忆链路 P1/P2/P3(抽取、受控词表、召回与缓存、生命周期级联及投影事件)、
fin_* 场内交易只读 ORM 层、agent_intent_config 状态流转并在运行期真正生效、
限流(Redis 固定窗口、故障一律放行)、游标校验、trace_id 中间件、
示例业务 Agent fund_query_demo 与一键端到端验证脚本,以及审计/指纹/迁移状态工具。

五、文档与验证
新增 docs/19(业务 Agent 接入实操)、docs/20(第一版迁移指南)与 docs/evidence 证据;
docs/01/02/06/08/09/17 同步实现现状。

验证结果:ruff 通过、mypy 103 文件无错、unit+contract 447 passed、
integration 29 passed、acceptance_check --production 7 PASS、
demo_agent_e2e 9/9 PASS(含失败关闭反证)。
2026-09-10 15:55:54 +08:00

42 KiB
Raw Blame History

MVC+S Agent 平台接口文档

版本:v1.0
状态:评审稿
修订日期:2026-09-09
适用对象:前端、后端、测试、运维、业务 Agent 开发人员和编码 Agent
数据库约束:允许新增表和字段,禁止修改已有表名及已有字段定义

1. 文档目的

本文是 Agent 平台 HTTP 接口的唯一权威规范,定义运行面、会话面、平台管理面、SSE 传输、JWT 鉴权、统一信封、错误映射、幂等、分页、审计及业务扩展规则。

内部 Python 类型、Service Protocol、领域事件字段和数据库 DDL 不在本文重复定义。本文通过权威源矩阵引用已有设计,避免同一契约出现两个定义。

当前业务能力只针对场内基金模拟交易。场外基金运营使用独立业务表和接口,不得写入场内模拟交易表。

2. 权威源与边界

2.1 权威源矩阵

契约项 契约编号 唯一权威源 本文职责
Agent 请求与上下文 AGENT-REQ-001 01 §5.2 定义 HTTP 投影和映射规则
Agent 结果 AGENT-RESULT-001 01 §5.3 定义对外字段和序列化
Service Protocol AGENT-SERVICE-001 01 §5.4 仅登记依赖方向
Agent 错误体系 AGENT-ERROR-001 01 §5.5 定义 HTTP 状态码映射
领域事件 AGENT-EVENT-001 01 §5.4、02 §8.2 定义触发接口和触发时机
SSE 事件载荷 AGENT-SSE-001 01 §12 定义 HTTP 传输方式
Agent 执行顺序 AGENT-FLOW-001 01 §6、03 §3-§5 保证接口不绕过执行顺序
数据库实体 DB-BASE-001 00、02 仅定义资源与实体映射
请求幂等 DB-IDEMPOTENCY-001 02 §8.3 定义 HTTP 幂等语义
Agent 运行 DB-RUN-001 02 中的 agent_run 定义运行资源语义
领域状态机 DOMAIN-FLOW-001 对应业务流程文档 仅登记入口和 Agent 边界

2.2 冲突裁决

  1. 本文的认证、路径、Header、HTTP 信封、分页、错误码映射和版本规则优先于业务接口文档。
  2. 业务字段、业务状态机和业务校验以对应业务文档为准,本文不得复制后形成第二权威源。
  3. 内部 DTO、Service Protocol、事件字段和数据库字段以矩阵指定文档为准。
  4. 同一契约出现两处定义时,非权威定义必须删除并改为引用,不允许两份定义同时进入实现。
  5. OpenAPI 是本文 HTTP 契约的机器可读投影。OpenAPI 与本文冲突时先停止发布并修正文档或生成逻辑。

2.3 MVC+S 依赖边界

Controller -> Application Service -> Domain Service/Repository -> Model
     |
     `-> View

AgentRunService -> RunRepository/IdempotencyService/RunDispatchPort
Run Worker -> AgentExecutor -> AgentFactory -> BaseAgent
Run Query Service -> RunRepository/ConversationRepository -> JSON/SSE View
  • Controller 不调用 Agent、ORM、Redis、Milvus、Neo4j 或消息中间件。
  • Worker 不依赖 HTTP、Controller 或 SSE View。
  • BaseAgent 返回传输无关的执行结果,不生成 HTTP 数据帧。
  • JSON 查询和 SSE 订阅使用同一个 RunQueryService 权威投影。
  • HTTP DTO 与内部 Agent DTO 分离,通过显式 Mapper 转换。
  • Redis 只承担缓存和实时通知;MySQL 保存权威运行状态和最终结果。

3. 通用 HTTP 约定

3.1 基础地址与命名

  • 业务接口前缀:/api/v1。
  • 平台管理接口前缀:/api/v1/admin。
  • 内部运维接口前缀:/internal。
  • HTTP 路径使用 kebab-case,资源名称使用复数。
  • agent_type 使用 snake_case,格式为 [a-z][a-z0-9_]{1,31}。
  • 请求和响应编码统一为 UTF-8。
  • JSON 请求使用 Content-Type: application/json。

3.2 通用请求 Header

Header 是否必填 规则
Authorization 是 Bearer <JWT>,运维接口除外
Idempotency-Key 写接口按本文要求 8-64 个可打印 ASCII 字符
Content-Type 有请求体时是 application/json
Accept 否 默认 application/json;SSE 为 text/event-stream
If-Match 管理面更新和状态转换是 使用服务端上次返回的 ETag
traceparent 否 符合 W3C Trace Context;非法值由服务端替换

所有响应返回 X-Trace-ID。客户端不能通过请求正文或 metadata 指定用户、角色、客户范围、模型、工具、合规策略或追踪标识。

3.3 成功信封

单资源:

{
  "data": {},
  "meta": {
    "trace_id": "trace-uuid"
  }
}

列表资源:

{
  "data": [],
  "meta": {
    "trace_id": "trace-uuid",
    "next_cursor": "opaque-cursor",
    "has_more": true
  }
}

业务接口不得增加其他顶层字段。SSE、文件下载和运维健康检查不使用业务 JSON 信封。

3.4 错误信封

{
  "error": {
    "code": "IDEMPOTENCY_CONFLICT",
    "message": "幂等键已用于不同请求",
    "retryable": false,
    "field_errors": []
  },
  "meta": {
    "trace_id": "trace-uuid"
  }
}

field_errors 元素格式为:

{
  "field": "metadata.ui_entry",
  "reason": "格式不正确"
}

错误响应禁止包含异常堆栈、SQL、模型原文、供应商响应、内部网络地址和密钥引用。

3.5 HTTP 状态码

状态码 使用场景
200 查询、幂等更新或同步操作成功
201 同步创建资源成功
202 异步任务或取消请求已受理
204 操作成功且无响应体
304 条件查询内容未变化
400 JSON、Header 或查询参数无法解析
401 JWT 缺失、无效、过期或已吊销
403 角色、权限、适当性或数据范围拒绝
404 资源不存在,或为防止越权枚举而隐藏资源
409 幂等冲突、版本冲突或非法状态转换
422 已解析请求不满足字段或业务输入约束
429 频率、并发或配额限制
500 未分类内部错误
502 上游模型或工具返回无效响应
503 必需依赖不可用
504 上游调用超时且无法降级

3.6 核心错误码

错误码 HTTP 是否可重试 说明
AGENT_INPUT_INVALID 422 否 请求内容不满足 Agent 输入约束
AGENT_PERMISSION_DENIED 403 否 角色、入口或数据范围不允许
AUTHENTICATION_REQUIRED 401 否 Token 缺失或无效
SESSION_NOT_FOUND 404 否 会话不存在或已被资源隐藏
SESSION_NOT_ACCESSIBLE 404 否 当前身份不能访问会话
AGENT_TYPE_NOT_FOUND 404 否 Agent 未注册
IDEMPOTENCY_CONFLICT 409 否 同一幂等键对应不同正文
RESOURCE_VERSION_CONFLICT 409 是 If-Match 版本过期
RUN_NOT_FOUND 404 否 运行不存在或不可见
RUN_NOT_CANCELLABLE 409 否 运行已进入不可取消阶段
RUN_CANCELLED 409 否 运行已取消
INVALID_CURSOR 400 否 游标非法、过期或与过滤条件不符
RATE_LIMITED 429 是 频率、并发或配额限制
DEPENDENCY_UNAVAILABLE 503 是 必需依赖不可用
UPSTREAM_TIMEOUT 504 是 上游超过时间预算
AGENT_INTERNAL_ERROR 500 视情况 未分类内部错误

3.7 数据格式

  • 时间统一使用 UTC 的 RFC 3339,例如 2026-09-09T08:30:00.000000Z。
  • 金额、价格、数量和置信度使用十进制字符串,禁止使用 JSON 浮点数。
  • 数据库 BIGINT 对外序列化为字符串,避免前端整数精度丢失。
  • 布尔值使用 true/false,不得使用 0/1。
  • 空集合返回 [],空对象返回 {},无值返回 null。
  • 未特别说明的文本字段去除首尾空白,禁止不可见控制字符。

3.8 游标分页

列表接口统一使用 cursor 和 limit。limit 默认 20、最小 1、最大 100。游标是不透明字符串,绑定用户、查询条件、排序字段和方向,客户端不得解析或修改。

默认排序为 created_at DESC, id DESC。默认不返回总条数;确需精确统计时使用对应领域的独立统计接口。

3.9 接口版本

SSE 实现补充:运行未完成时建立的连接,在观察到最终事务提交后分块输出 delta; 已完成运行的新连接使用 replace 返回完整结果。两者都是结果级恢复,不提供事件游标续传。 块长度通过 .env 的 SSE_CHUNK_CHARACTERS 控制,按 Unicode 字符切分,空结果也输出一个 delta。

  • 兼容变更:新增可选字段、新增接口、新增可识别的错误码。
  • 破坏性变更:删除或重命名字段、改变字段类型或含义、把可选字段改为必填、改变既有状态语义。
  • 破坏性变更必须升级主路径,例如 /api/v2。
  • 客户端必须对未知枚举值提供兜底行为。
  • 废弃接口返回 Deprecation、Sunset 和替代接口链接。
  • 废弃期不得少于两个发布周期且不得少于 90 天。

4. JWT 鉴权与授权

4.1 Token 要求

Authorization: Bearer <access-token>

JWT 至少包含 sub、jti、iss、aud、iat、nbf 和 exp。服务端必须验证签名算法白名单、签发方、受众、时间窗口和吊销状态。

JWT 只证明身份和基础授权范围。服务端每次请求重新加载有效用户状态、角色、权限、客户归属和数据范围;不得完全信任 Token 中的历史角色信息。

4.2 权限处理

实现补充(2026-09-09):统一 REST 入口在服务端设置 portal=api;Agent 声明须显式允许 此入口,metadata、Header 和 JWT 中的 portal/roles 均不作为授权依据。用户状态须为基线的 正常,角色状态为 active,角色分配在有效期内。每次请求直读 RBAC,撤权立即生效; 暂不缓存授权数据。运行同时要求 agent:run 权限及 AgentDefinition 的角色、入口交集。 权限范围按 permission_code 分别保存,禁止把另一权限的 all 扩散到全部资源。 管理面需 admin/super_admin 角色及第 19 节对应操作权限;拒绝追加审计。

  • 客户只能访问自己的运行、会话、消息、反馈、转人工请求和安全记忆投影。
  • 客服只能访问进入客服队列或分配给自己的会话和工单。
  • 投顾只能访问 sys_customer_assignment 中归属自己的客户。
  • 风控人员只能访问其角色和数据范围允许的风险记录。
  • 普通管理员默认无权查看未脱敏会话正文和敏感审计详情。
  • 越权资源统一返回 404,避免泄露资源是否存在;明确功能无权限时返回 403。

4.3 SSE 鉴权

SSE 订阅必须携带 Bearer Token。浏览器客户端使用支持自定义 Header 的 fetch 流式实现或合规 SSE 客户端,不使用无法设置 Authorization Header 的原生 EventSource。

连接建立时验证 JWT 和资源权限。Token 在连接期间过期不强制截断已经通过鉴权的短连接,但重连必须重新鉴权。

5. 幂等与并发

5.1 幂等范围

必须携带 Idempotency-Key 的接口包括:

  • 创建 Agent 运行。
  • 取消 Agent 运行。
  • 创建或关闭会话。
  • 创建转人工请求。
  • 业务写接口。
  • 配置审核、激活、回滚、停用和归档。

通用幂等范围为 user_id + HTTP method + normalized_path + idempotency_key。Agent 运行同时校验 agent_type。请求哈希使用规范化后的路径、查询参数和 JSON 正文计算,不包含 Authorization、trace Header 和传输时间。

5.2 重复请求

  • 同一范围、同一键、同一哈希:返回原资源和当前状态。
  • 同一范围、同一键、不同哈希:返回 409 IDEMPOTENCY_CONFLICT。
  • 原异步任务仍在执行:返回原 run_id,不得创建第二个任务。
  • Worker 租约超时:接管原 run_id,不得生成新的运行记录。
  • 已完成请求:返回原结果资源地址。

5.3 乐观并发

管理面草稿更新和状态转换必须携带 If-Match。ETag 是服务端根据资源版本生成的不透明值。版本不一致返回 409 RESOURCE_VERSION_CONFLICT。

已审核、已激活、已停用或已归档的不可变版本不得原地编辑。

6. Agent 运行接口

6.1 运行状态

queued -> running -> succeeded
                  -> failed
queued/running -> cancel_requested -> cancelled
  • queued:受理事务已提交,等待 Worker。
  • running:Worker 持有有效租约并正在执行。
  • cancel_requested:已收到取消请求,等待 Worker 到达安全停止点。
  • succeeded:最终消息、审计、幂等完成状态和 Outbox 已原子提交。
  • failed:不可恢复错误及审计已经提交。
  • cancelled:在最终事务开始前成功取消。

6.2 创建运行

POST /api/v1/agent-runs
Authorization: Bearer <token>
Idempotency-Key: <key>
Content-Type: application/json

请求:

{
  "agent_type": "customer_service",
  "session_id": "session-uuid",
  "message": "场内基金卖出后资金什么时候可用?",
  "end_session": false,
  "metadata": {
    "locale": "zh-CN",
    "client_version": "1.0.0",
    "ui_entry": "customer_chat"
  }
}

message 长度 1-8000,不能只包含空白。metadata 只允许 locale、client_version 和 ui_entry,当前 locale 只允许 zh-CN。会话必须属于当前用户或在员工数据范围内,Agent 必须已注册且允许当前角色和入口。

返回 202 Accepted:

{
  "data": {
    "run_id": "run-uuid",
    "trace_id": "trace-uuid",
    "status": "queued",
    "status_url": "/api/v1/agent-runs/run-uuid",
    "events_url": "/api/v1/agent-runs/run-uuid/events",
    "created_at": "2026-09-09T08:30:00.000000Z"
  },
  "meta": {
    "trace_id": "trace-uuid"
  }
}

受理事务必须原子保存用户消息、request_idempotency、agent_run 和 agent.run_requested Outbox。事务失败时不得返回 run_id。

主要错误:AGENT_INPUT_INVALID、AGENT_PERMISSION_DENIED、SESSION_NOT_FOUND、SESSION_NOT_ACCESSIBLE、AGENT_TYPE_NOT_FOUND、IDEMPOTENCY_CONFLICT、RATE_LIMITED。

6.3 查询运行

GET /api/v1/agent-runs/{run_id}
Authorization: Bearer <token>

返回 200 OK:

{
  "data": {
    "run_id": "run-uuid",
    "trace_id": "trace-uuid",
    "session_id": "session-uuid",
    "agent_type": "customer_service",
    "status": "succeeded",
    "result_version": 1,
    "result": {
      "message_id": "12345",
      "reply": "最终安全回复",
      "intent": "faq",
      "confidence": "0.9400",
      "source_references": [],
      "suggestions": [],
      "transfer_required": false,
      "transfer_reason": null,
      "degraded": false,
      "degradation_reason": null
    },
    "error": null,
    "created_at": "2026-09-09T08:30:00.000000Z",
    "started_at": "2026-09-09T08:30:01.000000Z",
    "completed_at": "2026-09-09T08:30:04.000000Z"
  },
  "meta": {
    "trace_id": "trace-uuid"
  }
}
  • 未完成时 result 和 error 均为 null。
  • 成功时 result 来自已持久化助手消息,不能从 Worker 内存拼装。
  • 失败时 result 为 null,error 只包含安全错误码、消息和可重试标志。
  • 取消时不创建助手成功消息。
  • result_version 用于客户端重连去重,MVP 成功结果固定为 1。

主要错误:RUN_NOT_FOUND、AGENT_PERMISSION_DENIED。

6.4 订阅运行结果

GET /api/v1/agent-runs/{run_id}/events
Authorization: Bearer <token>
Accept: text/event-stream

成功响应 Header:

Content-Type: text/event-stream; charset=utf-8
Cache-Control: no-cache, no-transform
X-Accel-Buffering: no
X-Trace-ID: trace-uuid

传输顺序:

运行未完成:start -> 注释心跳 -> 等待
正常完成:start -> tools(可选) -> delta(一个或多个) -> done -> 关闭
安全替换:start -> replace -> done -> 关闭
不可恢复:start -> error -> 关闭

帧示例:

event: start
data: {"trace_id":"trace-uuid","session_id":"session-uuid"}

: keepalive

event: delta
data: {"trace_id":"trace-uuid","text":"安全文本片段"}

event: done
data: {"trace_id":"trace-uuid","intent":"faq","confidence":"0.9400","sources":[],"suggestions":[]}

事件名称和业务载荷以 AGENT-SSE-001 为准。注释心跳不是业务事件。tools、delta、replace 和 done 只能在最终持久化事务成功后发送。

MVP 采用结果级恢复,不实现事件级游标续传。Last-Event-ID 可以被忽略。重连时服务端根据 agent_run 和 conversation_message 重新发送完整最终结果,客户端按 run_id + result_version 去重。

若错误发生在响应 Header 发送前,返回统一 JSON 错误;发送后使用 error 事件并关闭连接。done 和 error 都是终止事件,之后不得继续发送数据。

主要错误:RUN_NOT_FOUND、AGENT_PERMISSION_DENIED、SSE_NOT_ACCEPTABLE。

6.5 取消运行

POST /api/v1/agent-runs/{run_id}/cancellations
Authorization: Bearer <token>
Idempotency-Key: <key>

请求:

{
  "reason": "user_cancelled"
}

返回 202 Accepted:

{
  "data": {
    "run_id": "run-uuid",
    "status": "cancel_requested",
    "cancel_requested_at": "2026-09-09T08:30:02.000000Z"
  },
  "meta": {
    "trace_id": "trace-uuid"
  }
}

重复取消返回同一状态。运行已成功、失败或进入最终提交事务时返回 409 RUN_NOT_CANCELLABLE。取消成功后,request_idempotency 使用 failed + RUN_CANCELLED 表示原请求已终止,不扩展其既有状态枚举。

7. 会话、消息、反馈与转人工接口

7.1 创建会话

POST /api/v1/conversations
Authorization: Bearer <token>
Idempotency-Key: <key>
Content-Type: application/json

请求:

{
  "agent_type": "customer_service"
}

返回 201 Created:

{
  "data": {
    "session_id": "session-uuid",
    "agent_type": "customer_service",
    "portal": "customer_chat",
    "status": "active",
    "clarification_round": 0,
    "created_at": "2026-09-09T08:20:00.000000Z"
  },
  "meta": {"trace_id": "trace-uuid"}
}

服务端根据请求入口确定 portal,通过 AgentFactory 校验 Agent、角色和入口。客户端不得提交 user_id、portal 或澄清轮次。

7.2 查询会话

GET /api/v1/conversations/{session_id}
Authorization: Bearer <token>

返回会话的 session_id、agent_type、portal、status、clarification_round、message_count、last_active_at、started_at 和 ended_at。权限不满足时按资源隐藏规则返回 404。

7.3 查询会话消息

GET /api/v1/conversations/{session_id}/messages?limit=20&cursor=<cursor>
Authorization: Bearer <token>

返回 conversation_message 的对客投影:message_id、role、content、intent、confidence、source_references、created_at 和脱敏后的 tool_calls。不返回内部 Prompt、模型原文、权限判断详情、未脱敏工具参数或其他客户数据。

用户消息的 intent、confidence 和 source_references 按现有流程可以为空;助手消息必须来自已经完成合规和持久化的结果。

7.4 结束会话

POST /api/v1/conversations/{session_id}/closures
Authorization: Bearer <token>
Idempotency-Key: <key>

请求体可为空。服务端条件更新会话状态为 ended,触发记忆提取事件的判定由公共底座完成。已结束会话重复调用返回当前会话状态;已转人工会话不得通过此接口绕过客服状态机。

7.5 创建用户反馈

POST /api/v1/conversation-messages/{message_id}/feedback
Authorization: Bearer <token>
Idempotency-Key: <key>
Content-Type: application/json

请求:

{
  "rating": -1,
  "feedback_type": "inaccurate",
  "feedback_content": "回答没有说明到账条件"
}

rating 只能为 1 或 -1,正文最多 1000 字符。消息必须属于当前用户;同一用户对同一消息只能有一条有效反馈,重复提交相同内容返回原反馈,内容不同返回 409 FEEDBACK_ALREADY_EXISTS。

7.6 用户申请转人工

POST /api/v1/conversations/{session_id}/handover-requests
Authorization: Bearer <token>
Idempotency-Key: <key>
Content-Type: application/json

请求:

{
  "reason_code": "user_requested",
  "reason_detail": "希望人工解释"
}

客户端只能提交 reason_code=user_requested 和有限长度的补充说明,不能提交 priority、assigned_to、置信度、会话摘要或来源引用。返回 202 Accepted:

{
  "data": {
    "handover_id": "ticket-uuid",
    "session_id": "session-uuid",
    "status": "pending",
    "created_at": "2026-09-09T08:35:00.000000Z"
  },
  "meta": {"trace_id": "trace-uuid"}
}

该接口只负责创建通用转人工请求。客服工单分配、接单、解决和关闭由客服领域 Service 处理,不允许 Controller 直接写 svc_handover_ticket。

7.7 查询转人工请求

GET /api/v1/handover-requests/{handover_id}
Authorization: Bearer <token>

客户只能查看自己的 status、创建时间和安全提示;客服坐席可按权限查看队列和分配信息。工单状态 pending -> assigned -> processing -> resolved -> closed,取消规则和字段以 02 §7.2 及客服业务文档为准。

8. 记忆与知识引用接口

8.1 查询记忆画像

GET /api/v1/users/me/memory-profile
GET /api/v1/customers/{customer_id}/memory-profile
Authorization: Bearer <token>

客户只能查询自己的画像;投顾、客服或授权员工必须通过客户归属和数据范围校验。返回经过字段策略过滤的当前画像、有效期、来源摘要和版本,不返回模型原始推理、Prompt、其他客户信息或未解决冲突的内部详情。

记忆提取没有客户端写接口。memory.extraction_requested 由 complete_run() 与最终结果在同一事务写入 Outbox,再由 Worker 调用内部 MemoryService。更正、遗忘和监管删除属于独立隐私流程,本接口不临时复用 memory_conflict。

8.2 解析知识引用

GET /api/v1/knowledge-references/{reference_token}
Authorization: Bearer <token>

reference_token 为服务端签发的短期不透明令牌,绑定用户、知识版本和过期时间。返回允许展示的标题、版本、生效日期、来源机构和摘要;客户端不能通过修改令牌枚举 doc_id 或读取草稿知识。

知识上传、审核、发布、失效和 Milvus 同步由知识业务文档定义。Agent 只能使用工具返回的 SourceReference,不得自行构造引用。

9. 平台管理面接口

管理面只操作草稿、审核、激活、停用、回滚和归档流程,不提供绕过版本控制的通用 CRUD。所有更新和状态转换都需要 If-Match;创建、审核、激活、回滚和停用需要 Idempotency-Key。

9.1 配置发布

POST /api/v1/admin/config-releases
GET  /api/v1/admin/config-releases
GET  /api/v1/admin/config-releases/{release_id}
POST /api/v1/admin/config-releases/{release_id}/validations
POST /api/v1/admin/config-releases/{release_id}/reviews
POST /api/v1/admin/config-releases/{release_id}/activations
POST /api/v1/admin/config-releases/{release_id}/rollbacks

创建草稿请求至少包含 release_no、title、change_summary。验证接口执行 Schema、权限上限、引用完整性、路由备用端点、Prompt、模板和意图配置校验;未通过验证不得审核或激活。

审核请求:

{
  "decision": "approved",
  "comment": "已完成审核"
}

创建人可以审核自己创建的版本(允许自审,不要求审核人不同于创建人);审核这一状态机节点不可跳过,未提交审核的草稿不能直接审核或激活。自审时 reviewer_id 留空——库约束 chk_config_release_separation(reviewer_id IS NULL OR reviewer_id <> created_by)属于数据库基线,不能把创建人写进 reviewer_id;自审人身份由 interaction_audit 的审核记录承担。他人复核仍照常写入 reviewer_id。激活必须是审核通过的完整批次,且原子切换当前生效版本。回滚不修改历史记录,而是创建新的发布记录并填写 rollback_of_release_id。

9.2 平台配置项

POST /api/v1/admin/config-releases/{release_id}/platform-config-items
GET  /api/v1/admin/config-releases/{release_id}/platform-config-items
PUT  /api/v1/admin/config-releases/{release_id}/platform-config-items/{item_id}

配置项必须按 namespace + item_key 唯一。value_json 必须通过对应 Pydantic Schema 校验,不接受任意权限扩大、模型端点、工具白名单或客户范围参数。

9.3 模型端点

POST /api/v1/admin/model-endpoints
GET  /api/v1/admin/model-endpoints
GET  /api/v1/admin/model-endpoints/{endpoint_id}
PUT  /api/v1/admin/model-endpoints/{endpoint_id}
POST /api/v1/admin/model-endpoints/{endpoint_id}/reviews
POST /api/v1/admin/model-endpoints/{endpoint_id}/activations
POST /api/v1/admin/model-endpoints/{endpoint_id}/disablements

请求只允许提交 endpoint_code、供应商标识、能力、敏感级别、超时、成本和 secret_ref。不得提交或返回 API 明文密钥。健康检查失败可以熔断流量,但不能自动把数据库配置改成 active。

9.4 模型路由

POST /api/v1/admin/config-releases/{release_id}/model-routing-rules
GET  /api/v1/admin/config-releases/{release_id}/model-routing-rules
PUT  /api/v1/admin/config-releases/{release_id}/model-routing-rules/{rule_id}

路由规则请求使用:

{
  "rule_code": "customer_service_answer",
  "agent_type": "customer_service",
  "task_type": "answer_generation",
  "model_policy": "balanced",
  "primary_endpoint_id": "1001",
  "fallbacks": [
    {"endpoint_id": "1002", "fallback_order": 1},
    {"endpoint_id": "1003", "fallback_order": 2}
  ],
  "max_attempts": 3,
  "latency_budget_ms": 15000
}

HTTP 不接受或返回旧的 fallback_endpoint_ids JSON 字段。备用链以 model_routing_fallback 为权威关系表,服务端校验主端点不在备用链、顺序不重复、端点存在且总尝试数不超过 3。

9.5 Prompt、意图和回复模板

POST /api/v1/admin/prompt-templates
GET  /api/v1/admin/prompt-templates
GET  /api/v1/admin/prompt-templates/{prompt_id}

POST /api/v1/admin/agent-intent-configs
GET  /api/v1/admin/agent-intent-configs
PUT  /api/v1/admin/agent-intent-configs/{config_id}

POST /api/v1/admin/reply-templates
GET  /api/v1/admin/reply-templates
PUT  /api/v1/admin/reply-templates/{template_id}

POST /api/v1/admin/negative-word-rules
GET  /api/v1/admin/negative-word-rules
PUT  /api/v1/admin/negative-word-rules/{rule_id}

这些资源使用各自的草稿、审核、激活和归档状态。由于现有表没有统一 release_id 外键,接口不得声称它们与 config_release 自动原子绑定;发布服务必须在激活前校验引用版本一致。

模板和意图配置的同一业务组合最多一个 active 版本,数据库生成列唯一约束是最终保障。已激活版本不可原地编辑。

9.6 审计查询

GET /api/v1/admin/audit-records
Authorization: Bearer <token>

支持 trace_id、run_id、用户、Agent 类型、事件类型、结果、时间范围和游标过滤。接口只读,不提供修改和删除。audit:read-sensitive 才能查看未脱敏详情。

10. SSE 与领域事件映射

10.1 SSE 事件

事件名称和载荷以 AGENT-SSE-001 为准:start、tools、delta、replace、done、error。本文只定义传输和发送时机,不重新定义字段。

10.2 Outbox 事件

事件 产生位置 消费者
agent.run_requested 创建运行受理事务 Agent Worker
agent.run_cancel_requested 取消状态事务 Agent Worker
conversation.completed complete_run() 最终事务 会话投影、通知
conversation.transfer_requested complete_run() 最终事务 客服转人工消费者
memory.extraction_requested complete_run() 最终事务 记忆提取 Worker
agent.run_failed 失败状态事务 监控和告警
config.release_activated 配置激活事务 缓存失效、实例刷新
config.release_rolled_back 回滚激活事务 缓存失效、监控
model.endpoint_disabled 端点停用事务 模型路由缓存

Outbox 消费者按 event_id 幂等。失败事件保留并重试,超过阈值进入死信状态并告警;不能删除未完成事件。

11. 审计分界

11.1 必须写 interaction_audit

  1. 委托、成交、资金、持仓和风险预警处置等受监管业务状态变化。
  2. 配置发布、审核、激活、停用和回滚。
  3. 越权、适当性、跨客户和其他权限决策拒绝。
  4. 工单全生命周期、方案审核和人工处置。
  5. Agent 运行的输入摘要、结果、模型/Prompt 版本、合规动作、降级原因和耗时。

request_idempotency 的完成状态随 complete_run() 与业务结果同一事务写审计。

11.2 只写运行日志或指标

心跳和租约续期、幂等抢占重试、缓存读写与失效、SSE 游标与断流、健康检查和普通限流拒绝只写运行日志或指标。若限流同时判定为攻击、越权或安全策略命中,则另写安全审计。

12. 业务接口索引与 Agent 边界

公共接口文档只登记入口、归属和 Agent 禁止边界,不预先定义领域载荷和状态机。

业务域 接口入口 归属文档 Agent 边界
客服工单 /api/v1/customer-service/handover-tickets/** 客服业务文档 可生成摘要和转人工请求,不分配、接单、解决或关闭工单
投顾方案 /api/v1/advisory-plans/** 投顾业务文档 只生成分析草案,不代替投顾审核发布
场内模拟交易 /api/v1/sim-orders/** 交易业务文档 只读查询,不创建、确认或撤销委托
风控扫描 /api/v1/risk-scans/** 风控业务文档 可解释规则结果,不启动人工处置
风险预警 /api/v1/risk-alerts/** 风控业务文档 只读分析,不确认、升级或关闭预警
场外基金运营 不属于当前系统 独立运营系统 不读写场内交易表

B 类业务写接口必须复用 JWT、响应信封、错误码、幂等、统一 RequestContext、事务和审计规则。Controller 只路由、校验、映射和调用 Service;禁止直接访问 Model。

13. A 类和 B 类扩展

13.1 A 类:Agent 能力扩展

组员新增 Agent、意图或 handle() 分支时,继续使用 /api/v1/agent-runs,不新增 Controller。允许修改 Agent 实现、启动注册和测试数据;不得复制或覆盖 BaseAgent 的鉴权、记忆、模型、工具、合规、审计、SSE 和事件逻辑。

13.2 B 类:业务 API 扩展

新增模拟下单、方案审核或预警处置等领域接口时,新增该业务域的 Controller、Application Service、DTO、Repository 和测试。B 类接口必须登记:资源路径、权限码、幂等范围、事务边界、审计类别、归属文档和 Agent 只读边界。

13.3 组员 Agent 交付清单

  1. <agent_type>_agent.py:继承 BaseAgent,只实现 handle()。
  2. AgentDefinition:角色、入口、意图、工具、合规策略、模型策略和记忆视图。
  3. 启动注册新增一行,不修改工厂实现。
  4. 正常、低置信、工具失败、模型失败和越权用例。
  5. 每个来源引用必须来自工具或知识服务返回值。
  6. 不覆盖 run_stream()、执行模板、记忆沉淀或事件广播方法。

14. 内部契约索引

本文不复制以下签名。实现和测试必须引用指定权威源:

契约 权威源
AgentRequest、RequestContext、配置 DTO 01 §5.2,AGENT-REQ-001
IntentResult、SourceReference、AgentResult 01 §5.3,AGENT-RESULT-001
ModelGateway、MemoryService、ComplianceService、AuditService 01 §5.4,AGENT-SERVICE-001
AgentError 分类 01 §5.5,AGENT-ERROR-001
BaseAgent 执行顺序和 complete_run() 01 §6,AGENT-FLOW-001
DomainEvent 和 Outbox 01 §5.3/§6.2、02 §8.2,AGENT-EVENT-001
SSE 事件载荷 01 §12,AGENT-SSE-001
表和字段 00、02,DB-BASE-001

HTTP 层使用 DTO Mapper 投影内部对象。Controller 和 View 不得直接返回 ORM Model 或内部异常对象。

15. 运维与安全接口

GET /internal/health/live
GET /internal/health/ready
GET /internal/metrics

这些接口不使用业务 JSON 信封,不暴露数据库地址、模型密钥、Token、完整客户资料或异常堆栈,只允许内网和监控系统访问。JWT 签发、刷新、注销由统一身份认证模块负责,Agent 平台不重复实现。

16. 验收与契约测试

16.1 HTTP 通用测试

  • 所有 JSON 接口使用统一成功或错误信封。
  • JWT 缺失、过期、签发方错误、受众错误和吊销均被拒绝。
  • 同键同正文返回原资源,同键不同正文返回 409。
  • 跨客户查询返回 404,且响应不泄露资源是否存在。
  • 分页游标绑定过滤条件,非法游标返回 400 INVALID_CURSOR。
  • Controller 不直接导入 ORM、数据库客户端、Agent 实现或消息客户端。

16.2 Agent 运行测试

  • 受理事务同时创建用户消息、幂等记录、agent_run 和 agent.run_requested Outbox。
  • Worker 租约过期后使用同一 run_id 安全接管。
  • 最终消息、审计、幂等完成状态和领域事件在同一事务提交。
  • memory.extraction_requested 不得由请求线程在提交后直接调用。
  • SSE 仅在最终事务成功后发送 tools、delta、replace 和 done。
  • 断流重连可以根据 run_id 获取完整结果;MVP 不声称支持事件级续传。

16.3 管理面测试

  • 创建人可以审核自己创建的配置;审核状态机不可跳过。
  • 未通过校验、审核或版本检查的配置不能激活。
  • 已激活版本不可原地编辑。
  • 模板和意图组合最多一个 active 版本。
  • 备用端点必须存在、顺序唯一,且主端点不能出现在备用链。
  • 激活、回滚、停用和权限拒绝都写审计。

16.4 静态检查

检查 OpenAPI 与本文路径、方法和必填 Header 一致
检查每个接口都有权限码、幂等说明、错误码和审计分类
检查 Controller 不直接访问 Model
检查 Agent 子类未覆盖公共执行模板
检查契约编号唯一且引用存在

17. 实施顺序

  1. 创建 agent_run 表及 Alembic 迁移,核对 00 基线和 02 新表,不修改已有表名和已有字段定义。
  2. 实现 HTTP DTO、统一信封、JWT 依赖、错误映射、Trace 中间件和游标工具。
  3. 实现 AgentRunApplicationService、幂等、运行租约和 RunDispatchPort。
  4. 将 Agent 执行从 HTTP/SSE 中解耦为 Worker 可调用的 AgentExecutor。
  5. 实现 JSON 状态查询和结果级恢复 SSE。
  6. 实现会话、消息、反馈和公共转人工入口。
  7. 实现管理面配置、模型路由、Prompt、意图、模板和禁止表达接口。
  8. 生成 OpenAPI 并执行契约测试、安全测试、故障恢复和迁移演练。

18. 完成标准

  • 所有公共 HTTP 接口具有稳定路径、请求、响应、权限、错误、幂等和审计定义。
  • run_id 可在服务重启后查询、恢复和获取完整结果。
  • JSON 和 SSE 不共享传输实现,但共享运行查询投影和权限检查。
  • A 类 Agent 不需要修改公共 Controller、Factory、BaseAgent 或 SSE View。
  • B 类业务接口遵守统一 MVC+S 骨架和 Agent 只读边界。
  • 内部契约和数据库结构没有在本文形成第二权威定义。
  • 49 张表的迁移不修改已有表名和已有字段定义。

19. 接口总目录

下表是 v1 接口的实现清单。除特别标注外,成功响应均使用第 3.3 节信封,错误响应均使用第 3.4 节信封。

编号 方法与路径 权限 幂等 成功状态 审计
R001 POST /api/v1/agent-runs agent:run 必须 202 Agent 运行
R002 GET /api/v1/agent-runs/{run_id} 资源所有者/数据范围 否 200 否
R003 GET /api/v1/agent-runs/{run_id}/events 资源所有者/数据范围 否 SSE 否
R004 POST /api/v1/agent-runs/{run_id}/cancellations agent:cancel 必须 202 取消操作
C001 POST /api/v1/conversations conversation:create 必须 201 会话创建
C002 GET /api/v1/conversations/{session_id} 会话所有者/数据范围 否 200 否
C003 GET /api/v1/conversations/{session_id}/messages 会话所有者/数据范围 否 200 否
C004 POST /api/v1/conversations/{session_id}/closures conversation:close 必须 200 会话结束
C005 POST /api/v1/conversations/{session_id}/handover-requests handover:create 必须 202 转人工请求
C006 GET /api/v1/handover-requests/{handover_id} 客户/客服数据范围 否 200 否
C007 POST /api/v1/conversation-messages/{message_id}/feedback conversation:feedback 必须 201 反馈创建
M001 GET /api/v1/users/me/memory-profile memory:read:self 否 200 敏感访问
M002 GET /api/v1/customers/{customer_id}/memory-profile memory:read:customer 否 200 敏感访问
K001 GET /api/v1/knowledge-references/{reference_token} knowledge:reference:read 否 200 否
A001 POST /api/v1/admin/config-releases config:write 必须 201 配置草稿
A002 GET /api/v1/admin/config-releases config:read 否 200 否
A003 GET /api/v1/admin/config-releases/{release_id} config:read 否 200 否
A004 POST /api/v1/admin/config-releases/{release_id}/validations config:write 必须 200 配置校验
A005 POST /api/v1/admin/config-releases/{release_id}/reviews config:review 必须 200 配置审核
A006 POST /api/v1/admin/config-releases/{release_id}/activations config:activate 必须 200 配置激活
A007 POST /api/v1/admin/config-releases/{release_id}/rollbacks config:activate 必须 201 配置回滚
A008 POST /api/v1/admin/config-releases/{release_id}/platform-config-items config:write 必须 201 配置变更
A009 GET /api/v1/admin/config-releases/{release_id}/platform-config-items config:read 否 200 否
A010 PUT /api/v1/admin/config-releases/{release_id}/platform-config-items/{item_id} config:write 必须 200 配置变更
A011 POST /api/v1/admin/model-endpoints model-endpoint:manage 必须 201 端点创建
A012 GET /api/v1/admin/model-endpoints config:read 否 200 否
A013 GET /api/v1/admin/model-endpoints/{endpoint_id} config:read 否 200 否
A014 PUT /api/v1/admin/model-endpoints/{endpoint_id} model-endpoint:manage 必须 200 端点变更
A015 POST /api/v1/admin/model-endpoints/{endpoint_id}/reviews config:review 必须 200 端点审核
A016 POST /api/v1/admin/model-endpoints/{endpoint_id}/activations model-endpoint:manage 必须 200 端点激活
A017 POST /api/v1/admin/model-endpoints/{endpoint_id}/disablements model-endpoint:manage 必须 200 端点停用
A018 POST /api/v1/admin/config-releases/{release_id}/model-routing-rules config:write 必须 201 路由变更
A019 GET /api/v1/admin/config-releases/{release_id}/model-routing-rules config:read 否 200 否
A020 PUT /api/v1/admin/config-releases/{release_id}/model-routing-rules/{rule_id} config:write 必须 200 路由变更
A021 POST /api/v1/admin/prompt-templates config:write 必须 201 Prompt 变更
A022 GET /api/v1/admin/prompt-templates config:read 否 200 否
A023 GET /api/v1/admin/prompt-templates/{prompt_id} config:read 否 200 否
A024 POST /api/v1/admin/agent-intent-configs config:write 必须 201 意图配置
A025 GET /api/v1/admin/agent-intent-configs config:read 否 200 否
A026 PUT /api/v1/admin/agent-intent-configs/{config_id} config:write 必须 200 意图配置
A027 POST /api/v1/admin/reply-templates config:write 必须 201 回复模板
A028 GET /api/v1/admin/reply-templates config:read 否 200 否
A029 PUT /api/v1/admin/reply-templates/{template_id} config:write 必须 200 回复模板
A030 POST /api/v1/admin/negative-word-rules config:write 必须 201 禁止表达
A031 GET /api/v1/admin/negative-word-rules config:read 否 200 否
A032 PUT /api/v1/admin/negative-word-rules/{rule_id} config:write 必须 200 禁止表达
A033 GET /api/v1/admin/audit-records audit:read 否 200 否
O001 GET /internal/health/live 内网 否 200 否
O002 GET /internal/health/ready 内网 否 200/503 否
O003 GET /internal/metrics 监控系统 否 200 否

业务域接口 /customer-service/handover-tickets/**、/advisory-plans/**、/sim-orders/**、/risk-scans/** 和 /risk-alerts/** 的具体方法、请求体、领域状态机和错误码分别由对应业务文档登记;它们仍必须遵守本文第 3-5、11 和 12 节。

20. 变更流程

任何新增或修改接口必须同时更新:

  1. 本文对应章节和第 19 节目录。
  2. OpenAPI 机器可读定义。
  3. 权限码、审计类别、幂等说明和错误码清单。
  4. 请求、响应、越权、重复提交、故障恢复和安全测试。
  5. 对应业务文档的入口索引;业务载荷不得复制到公共文档。

涉及内部契约时,先修改权威源文档,再更新本文索引。禁止只修改 OpenAPI 或只修改某个业务文档造成第二权威源。