Files
group_fqcd_jr/docs/05-接口文档.md
T
张胜宇 f68b052a69 fix: 端点编号去重与 milvus-lite 降为可选依赖
按 qyqy 在 PR #7 评审中的要求处理两项:

- docs/05-接口文档.md §19:客服画像候选的两个端点由 A034/A035 改为 A039/A040。
  原编号与 qyqy 侧登录 / RBAC 只读接口(A034-A038)重复;docs 守卫脚本只校验
  文档文件名编号、不校验 §19 端点编号,因此该重复会静默遗留。改后全表 55 个
  端点编号唯一。
- pyproject.toml / requirements.txt:milvus-lite 由主 dependencies 挪到
  [project.optional-dependencies] dev;requirements.txt 只保留说明性注释,
  不再作为生效依赖。理由:它仅用于本地开发(Docker Milvus 未运行时的本地
  持久化向量库),进主依赖会让生产环境多背一个包。

验证:pytest tests/unit tests/contract -> 1275 passed, 2 skipped, 0 failed;
ruff check app tests tools alembic 通过;mypy app 通过(244 个源文件)。
2026-09-12 11:53:35 +08:00

53 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 幂等冲突、版本冲突或非法状态转换
413 请求体或上传文件超过大小限制
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,不得自行构造引用。

8.3 知识库文档管理

POST   /api/v1/knowledge/upload
GET    /api/v1/knowledge/list
DELETE /api/v1/knowledge/{knowledge_id}
Authorization: Bearer <token>

需求来源:老师《需求文档-修改版》Phase 1 验收第 7 条「知识库管理接口可正常上传/查询/删除文档」与 F1.2。与 §8.2 的 /knowledge-references/{reference_token}(引用解析,K001)是两个不同的资源面:本节是管理面文档生命周期,凭 knowledge:manage 操作,不解析令牌、不按客户归属过滤;K001 是读侧引用解析,凭 knowledge:reference:read,返回可用展示的引用片段。两者不复用同一 prefix 语义。

三个端点均需 knowledge:manage(现只授给管理员角色)。created_by 取自认证上下文,调用方不能指定。三个端点共用 router 级限流;底座没有匿名路径,认证先于限流。

上传

{
  "filename": "理财产品销售管理办法.md",
  "content_base64": "<文档字节的标准 base64>",
  "knowledge_type": "policy"
}
  • filename 只能是文件名本身(不得含路径与分隔符)、长度 ≤ 256。
  • knowledge_type 取 faq / product / policy 之一,由服务端映射集合,调用方不得指定集合名;非法取值返回 422。
  • content_base64 严格解码;非法 base64 返回 422 AGENT_INPUT_INVALID。
  • 老师原文写 multipart/form-data,一期实现为 JSON(理由见下)。

成功 201 返回本次产生的知识行(一份文档切多块即为多行):

{
  "knowledge_ids": [109, 110],
  "filename": "理财产品销售管理办法.md",
  "knowledge_type": "policy",
  "created_by": "9003",
  "chunk_count": 2
}

查询列表

GET /api/v1/knowledge/list?limit=20&offset=0&knowledge_type=policy

limit 默认 20、上限 100;offset ≥ 0;knowledge_type 可选。默认只列未过期行。响应只给 content_preview(前 200 字符)与 content_length,不返回整篇 content_text —— 正文是检索侧素材,管理面列表不得变成"直读知识正文"的旁路:

{
  "items": [
    {
      "knowledge_id": 109,
      "knowledge_type": "policy",
      "title": "### 第一条 目的…",
      "source_file": "理财产品销售管理办法.md",
      "collection": "fin_policy_collection",
      "version": "v1",
      "status": "active",
      "review_status": "published",
      "created_by": 9003,
      "tags": {"chunk_index": 2, "heading_path": ["理财产品销售管理办法"]},
      "content_preview": "### 第一条 目的…",
      "content_length": 457
    }
  ],
  "count": 1
}

删除

DELETE /api/v1/knowledge/{knowledge_id}

删除不改物理行,而是标记 fin_knowledge_meta.status='expired' 并在同一事务投递 knowledge.vector_delete_requested(aggregate_id 与 payload 均为 str(knowledge_id)), 由知识向量 Worker 消费后删除 Milvus 向量;本地文件随后尽力归档,归档失败不回滚已提交的删除(只记日志)。

成功 200:

{
  "knowledge_id": 109,
  "status": "expired",
  "vector_delete_event": "knowledge.vector_delete_requested"
}

不存在的 knowledge_id 返回 404,不静默成功。

两处口径说明(避免误读)

  1. 请求体形状:老师原文为 multipart/form-data,一期用 JSON + content_base64。 理由是底座其余写接口(admin 配置面、conversations、agent-runs)全是 JSON,错误信封(§3.4) 与 ValidationAgentError 的 422 口径都建立在 JSON body 上;一期单独引 multipart 等于新开一条 无测试覆盖的上传失败路径。后续接前端表单时新增一个 multipart 端点复用同一 Service 即可 (Service 只吃 filename + content: bytes,与传输形状无关)。
  2. 删除的 404 错误码:现实现复用 SESSION_NOT_FOUND(底座通用资源不存在码),语义上偏会话面; 若后续要求精确语义,应新增 KNOWLEDGE_NOT_FOUND。本文按现状登记,不做美化。

8.4 公共只读工具索引(Agent 面)

工具不是 HTTP 接口,但它们决定 Agent 能读什么,且必须由 AgentFactory 注入的 ToolExecutor 统一执行(鉴权、数据范围、审计不得绕过)。登记口径: 工具名 / 必需权限 / 只读 / 越权行为。

工具名 必需权限 只读 越权与失败行为
check_suitability suitability:read 是 除管理员外不得查他人风险测评;测评过期/缺失一律拒绝(失败关闭)
query_fund_quote fund:quote:read 是 只读行情,不得改写为成交、委托或持仓语义
query_knowledge knowledge:query 是 集合名由服务端按意图映射,调用方不得指定;维度不符失败关闭
query_customer_profile memory:read:self(查他人为 memory:read:customer) 是 越范围按"不存在"处理且不泄露存在性;无当前画像抛错而不返回空画像

工具的白名单是两段式:代码里的 allowed_tools 是上限,实际可用范围还要与 当前 active 的 config_release 中 namespace=agent_tools、config_key=<agent_type>:<intent> 发布的工具白名单取交集;缺发布配置时交集为空、工具失败关闭。

query_customer_profile 的返回值遵循 §8.1 的字段策略:只投影画像属性白名单 (investor_type / investment_horizon / trading_frequency / preferred_asset_class / risk_tags / customer_tier / behavior_score / total_asset / assessment_valid_until / assessment_expired), 不返回 real_name、birth_date、mobile_masked、trade_account 等 PII; assessment_expired 按当前时间重算,不采信快照里的历史布尔值。

8.5 客服画像候选(Phase 2)

编号说明:本节为客服二期新增,不占用 §8.1–§8.4 既有号段,以避免破坏 AGENTS.md、docs/09、docs/14 对「§8.3 知识库管理三端点」「§8.4 公共只读工具索引」的既有引用。

客服 Agent 不读取或直接修改正式画像。已登录用户明确陈述长期偏好、约束或目标时,系统 异步生成 memory_unit.status='candidate' 候选;访客不会生成候选。候选不进入客服召回, 必须经过用户确认和管理员审核后才能晋升为 active。

GET  /api/v1/users/me/memory-candidates
POST /api/v1/users/me/memory-candidates/{candidate_id}/decisions
GET  /api/v1/admin/customer-profile-candidates
POST /api/v1/admin/customer-profile-candidates/{candidate_id}/reviews

用户确认请求体为 { "decision": "confirmed" | "rejected" },需要 memory:candidate:confirm;确认只将状态改为 verified。管理员审核请求体复用 ReviewPayload,需要管理员角色和 memory:candidate:review;approved 会在事务内 处理同键旧记忆冲突并将候选改为 active,rejected 将其改为 rejected。接口只返回 结构化候选值,不返回对话证据摘录、密码、验证码或其他原始敏感内容。

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 才能查看未脱敏详情。

9.7 客服转人工队列(只读)

GET /api/v1/admin/customer-service/handover-tickets?limit=20&cursor={ticket_id}
GET /api/v1/admin/customer-service/handover-tickets/{ticket_no}
Authorization: Bearer <token>

两个接口均要求 admin 或 super_admin 角色和 handover:read 权限。列表仅返回工单号、 会话标识、来源 Agent、优先级、转接原因、状态和时间;详情才追加二次脱敏后的转接原因、 会话摘要、意图置信度和受控知识来源。接口不得返回客户标识、原始会话正文、账户数据、 联系方式、工单分配信息或处理结论。当前仅支持查看,不支持接单、分配、处理、解决或关闭。

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() 或客户转人工申请事务 客服转人工消费者;写入 handover.queue_ready 审计,不改变工单 pending 状态
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/** 风控业务文档 可解释规则结果,不启动人工处置
风险预警 /api/v1/risk/** 风控业务文档 只读分析,不确认、升级或关闭预警
场外基金运营 不属于当前系统 独立运营系统 不读写场内交易表

风控模块落地时把扫描、预警、证据、通知和日报收在同一个 Controller 下,入口为 /api/v1/risk/**(早期规划写作 /risk-scans/**、/risk-alerts/**,以本节的实际入口为准)。 具体端点清单、权限与字段映射由风控业务文档登记,见第 19 节末尾。

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 平台不重复实现。

实现现状(2026-09-11 更新):上面这句原本是"平台不做签发"的依据,实际落地时确认了 平台必须有一个登录入口 —— 否则客户 / 员工 / 管理员三种身份无法区分(各 Agent 的 allowed_roles 早就分开了,缺的只是"怎么证明你是谁")。因此平台现在提供 POST /api/v1/auth/tokens(账号密码换访问令牌,见 §19 的 A034), 这是本文档 §11 那句的唯一例外。

边界仍然守住:平台只做登录,刷新与注销仍归统一身份认证模块 (app/core/security.py 已留好 RevocationStore 协议,接上 Redis 即可)。 令牌里只放 sub,角色 / 权限 / 数据范围一律由 IdentityService 每次请求查库解析, 所以权限变更立即生效,不受令牌有效期影响。

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 只读边界。
  • 内部契约和数据库结构没有在本文形成第二权威定义。
  • 数据库迁移不修改已有表名和已有字段定义(当前现库 52 张表;本行原写"49 张"是早期快照, 已于 2026-09-10 按实测更正 —— 表的数量会随新增表变化,因此这里只保留"不修改已有表名与字段定义"这一硬约束)。

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 敏感访问
M003 GET /api/v1/users/me/memory-candidates memory:read:self 否 200 候选查询
M004 POST /api/v1/users/me/memory-candidates/{candidate_id}/decisions memory:candidate:confirm 必须 200 用户确认/拒绝
A039 GET /api/v1/admin/customer-profile-candidates memory:candidate:review 否 200 候选审核列表
A040 POST /api/v1/admin/customer-profile-candidates/{candidate_id}/reviews memory:candidate:review 必须 200 候选审核
K001 GET /api/v1/knowledge-references/{reference_token} knowledge:reference:read 否 200 否
K002 POST /api/v1/knowledge/upload knowledge:manage 否 201 知识文档变更
K003 GET /api/v1/knowledge/list knowledge:manage 否 200 否
K004 DELETE /api/v1/knowledge/{knowledge_id} knowledge:manage 否 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 否
A034 POST /api/v1/auth/tokens 公开(登录前无身份) 否 200 登录成功/失败
A035 GET /api/v1/admin/roles audit:read 否 200 否
A036 GET /api/v1/admin/roles/{role_code} audit:read 否 200 否
A037 GET /api/v1/admin/roles/{role_code}/permissions audit:read 否 200 否
A038 GET /api/v1/admin/users/{user_id}/roles audit:read 否 200 否
O001 GET /internal/health/live 内网 否 200 否
O002 GET /internal/health/ready 内网 否 200/503 否
O003 GET /internal/metrics 监控系统 否 200 否

A034 – A038 的两点说明:

  • POST /api/v1/auth/tokens 是平台内唯一的登录入口(§11 已注明这是"平台不重复实现 签发"的唯一例外;刷新与注销仍归统一身份认证模块)。
  • A035 – A038 是 RBAC 的只读查询,供管理员回答"谁能访问什么""这个人为什么 403"。 它们复用 audit:read 而不新增 rbac:read:这份清单本身就是审计材料,且复用是 零数据改动、立刻可用(新增权限码得先改 sys_permission,而它目前由 seed_test_rbac.py 以 DELETE 重建语义管理)。 权限变更(提权 / 降权)尚无接口 —— 那条写路径必须带三条红线 (审计留痕、禁止自我提权、保护内置角色),需要单独评审,不是遗漏。

业务域接口 /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 或只修改某个业务文档造成第二权威源。