新增 §T 用户自助段(docs/05 §19 新号段 7 个 = A×40/C×7/K×4/M×4/O×3/R×4/T×9): - T001 GET /api/v1/users/me/account/dashboard — 账户/资金/持仓/盈亏汇总 - T002 POST /api/v1/users/me/orders — 委托提交(首版 market 立即全额成交) - T003 / T004 / T005 委托列表/详情/撤单 - T006 GET /api/v1/users/me/holdings — 持仓列表(含市值/盈亏/当日盈亏) - T007 / T008 成交记录列表/详情 - T009 GET /api/v1/users/me/cash-ledger — 资金账本 要点(与 docs/00 §6.6 一致): - 首版市价委托立即全额成交,不实现撮合队列/部分成交;T005 撤单首版对任何在场委托返回 ORDER_NOT_CANCELLABLE (409) - 价格来源复用 base FundQuoteService;service 层不二次封装(满足 AGENTS 第 2 条) - 首版风控 3 条硬性:产品可交易、客户适当性、持仓比例上限(fin_market_price 缺失或过期 → 拒绝买入) - 数据库零修改:10 张 fin_* 表全部 docs/00 既定,本批 PR 改列类型与可空性均 0;底座实际偏差(id 无 AUTO_INCREMENT、所谓'生成列'是普通 NOT NULL)由 service _next_id / 业务派生值补偿 注册 API:9 端点均注册进 app.main;user=9001(cust)'s id 写账 权限码(tools/seed_test_rbac.py 同步登记 + CUSTOMER 全量): 9047 account:read:self 9048 trade:order:create 9049 trade:order:read 9050 trade:order:cancel 9051 holding:read:self 9052 trade:txn:read 错误码(app/core/errors.py + docs/05 §3.6 + tests/unit/core/test_errors.py DOCUMENTED 三方同步): 404 ACCOUNT_NOT_FOUND / ORDER_NOT_FOUND 409 ORDER_NOT_CANCELLABLE 422 INSUFFICIENT_FUNDS / INSUFFICIENT_HOLDING / HOLDING_RATIO_EXCEEDED / SUITABILITY_MISMATCH / PRODUCT_NOT_TRADABLE 503 FUND_QUOTE_UNAVAILABLE(可重试) 新增:app/api/controllers/trading.py / app/api/schemas/trading.py / app/service/trade_service.py / tools/seed_sim_account_demo.py / tests/unit/service/test_trade_service.py(unit×8) / tests/contract/test_trading_endpoint_contract.py(contract×11) 修改:app/main.py(挂载 controller) / app/core/errors.py(10 新异常类) / tools/seed_test_rbac.py / docs/05-接口文档.md(§19 T001-T009 + §3.6 9 新码) / tests/unit/core/test_errors.py(DOCUMENTED 同步) 门禁:pytest tests/unit tests/contract 1313 passed (+19 新增) / ruff all clean / 三道守卫全过
56 KiB
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 冲突裁决
- 本文的认证、路径、Header、HTTP 信封、分页、错误码映射和版本规则优先于业务接口文档。
- 业务字段、业务状态机和业务校验以对应业务文档为准,本文不得复制后形成第二权威源。
- 内部 DTO、Service Protocol、事件字段和数据库字段以矩阵指定文档为准。
- 同一契约出现两处定义时,非权威定义必须删除并改为引用,不允许两份定义同时进入实现。
- 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 | 视情况 | 未分类内部错误 |
ACCOUNT_NOT_FOUND |
404 | 否 | 账户不存在或状态非"正常" |
INSUFFICIENT_FUNDS |
422 | 否 | 账户可用资金不足以扣减本次买入金额+费用 |
INSUFFICIENT_HOLDING |
422 | 否 | 可用持仓不足以卖出本次数量 |
PRODUCT_NOT_TRADABLE |
422 | 否 | 产品未上市或不在交易时段 |
FUND_QUOTE_UNAVAILABLE |
503 | 是 | 行情快照缺失或过期(持仓比例上限校验依赖) |
HOLDING_RATIO_EXCEEDED |
422 | 否 | 买入后超过产品持仓比例上限 |
SUITABILITY_MISMATCH |
422 | 否 | 客户适当性等级与产品风险等级不兼容 |
ORDER_NOT_CANCELLABLE |
409 | 否 | 委托已进入不可撤单阶段(首版直接成交后不可撤) |
ORDER_NOT_FOUND |
404 | 否 | 委托不存在或不属于当前客户 |
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,不静默成功。
两处口径说明(避免误读)
- 请求体形状:老师原文为
multipart/form-data,一期用 JSON +content_base64。 理由是底座其余写接口(admin 配置面、conversations、agent-runs)全是 JSON,错误信封(§3.4) 与ValidationAgentError的 422 口径都建立在 JSON body 上;一期单独引 multipart 等于新开一条 无测试覆盖的上传失败路径。后续接前端表单时新增一个 multipart 端点复用同一 Service 即可 (Service 只吃filename+content: bytes,与传输形状无关)。 - 删除的 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
- 委托、成交、资金、持仓和风险预警处置等受监管业务状态变化。
- 配置发布、审核、激活、停用和回滚。
- 越权、适当性、跨客户和其他权限决策拒绝。
- 工单全生命周期、方案审核和人工处置。
- 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 交付清单
<agent_type>_agent.py:继承BaseAgent,只实现handle()。AgentDefinition:角色、入口、意图、工具、合规策略、模型策略和记忆视图。- 启动注册新增一行,不修改工厂实现。
- 正常、低置信、工具失败、模型失败和越权用例。
- 每个来源引用必须来自工具或知识服务返回值。
- 不覆盖
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_requestedOutbox。 - 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. 实施顺序
- 创建
agent_run表及 Alembic 迁移,核对 00 基线和 02 新表,不修改已有表名和已有字段定义。 - 实现 HTTP DTO、统一信封、JWT 依赖、错误映射、Trace 中间件和游标工具。
- 实现
AgentRunApplicationService、幂等、运行租约和RunDispatchPort。 - 将 Agent 执行从 HTTP/SSE 中解耦为 Worker 可调用的
AgentExecutor。 - 实现 JSON 状态查询和结果级恢复 SSE。
- 实现会话、消息、反馈和公共转人工入口。
- 实现管理面配置、模型路由、Prompt、意图、模板和禁止表达接口。
- 生成 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 |
否 |
| T001 | GET /api/v1/users/me/account/dashboard |
account:read:self(已登录) |
否 | 200 |
账户看板(汇总账户/资金/持仓/盈亏) |
| T002 | POST /api/v1/users/me/orders |
trade:order:create(已登录) |
必须 | 201 |
委托提交(市价立即全额成交) |
| T003 | GET /api/v1/users/me/orders |
trade:order:read(已登录) |
否 | 200 |
委托列表(按 id 倒序游标分页) |
| T004 | GET /api/v1/users/me/orders/{order_no} |
trade:order:read(资源所有者) |
否 | 200 |
委托详情 |
| T005 | POST /api/v1/users/me/orders/{order_no}/cancellations |
trade:order:cancel(资源所有者) |
必须 | 200 |
撤单(首版仅"已接受/已部分成交"可撤) |
| T006 | GET /api/v1/users/me/holdings |
holding:read:self(已登录) |
否 | 200 |
持仓列表(含市值/盈亏/当日盈亏) |
| T007 | GET /api/v1/users/me/transactions |
trade:txn:read(已登录) |
否 | 200 |
成交记录列表 |
| T008 | GET /api/v1/users/me/transactions/{txn_no} |
trade:txn:read(资源所有者) |
否 | 200 |
成交详情 |
| T009 | GET /api/v1/users/me/cash-ledger |
account:read:self(已登录) |
否 | 200 |
资金账本(按 id 倒序游标分页) |
T001 – T009 的四点说明:
- 首版只支持
price_type="market"市价委托(docs/00§6.6 定义),系统立即全额成交, 委托状态直接落到已成交;因此 T005 撤单首版对任何在场委托都返回ORDER_NOT_CANCELLABLE(409),保留接口作为后续限价/部分成交开启的入口。- 价格来源仅复用底座
FundQuoteService的公共行情快照 (fin_market_price最新交易日,quote_source =eastmoney_demo_seed); Service 层不做行情二次封装,从而满足 AGENTS.md 第 2 条 Agent/Service 不直接命中行情 API。- 数据库零变更:T 段所用的 10 张
fin_*表均由docs/00定义;本批 PR 不重命名/删除/修改列类型 与可空性,与 AGENTS.md 第 1 条一致。- 持仓比例上限在 T002 买入路径强制校验
(当前持仓 + 本次拟成交)/ total_fund_shares * 100 <= single_investor_max_holding_ratio;fin_market_price缺失或过期则拒绝买入(docs/00 §6.6 红线)。
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. 变更流程
任何新增或修改接口必须同时更新:
- 本文对应章节和第 19 节目录。
- OpenAPI 机器可读定义。
- 权限码、审计类别、幂等说明和错误码清单。
- 请求、响应、越权、重复提交、故障恢复和安全测试。
- 对应业务文档的入口索引;业务载荷不得复制到公共文档。
涉及内部契约时,先修改权威源文档,再更新本文索引。禁止只修改 OpenAPI 或只修改某个业务文档造成第二权威源。