实现SuperAgent特殊入口结果处理

This commit is contained in:
andy
2026-07-10 12:05:57 +08:00
parent 9de4f0e7b6
commit 74e429a2cb
29 changed files with 1121 additions and 97 deletions

View File

@@ -4,8 +4,8 @@
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.2 |
| 日期 | 2026-07-07 |
| 文档版本 | 0.3 |
| 日期 | 2026-07-10 |
| 状态 | 第二版需求与后端阶段实现记录 |
| 适用范围 | SourceMessage 之后的 AI 过渡层、订单挂靠、任务卡、人工确认、OPERA 模拟操作主流程 |
| 主要读者 | 产品、后端、前端、测试、后续协作 agent |
@@ -14,17 +14,18 @@
本文是 `M002-order-task-workflow-v1.md` 的第二版修正,目标是把本项目已经讨论确认的订单任务主流程,与 2026-07-06 导入的 AI 任务卡契约对齐。
本文定义业务边界、数据语义和后续实现约束。当前后端已经按拆分 checkpoint 实现了 AI 结果接收、订单任务基础流转、任务草稿保存、最终确认、审计列表、OPERA 模拟骨架、SuperAgent 查询上下文接口 1、2 的最小字段版,以及前端 P0 任务列表 / 订单详情查询接口;前端页面、真实 OPERA、普通任务切换订单、查询接口 3 和查询接口 4 仍未实现。
本文定义业务边界、数据语义和后续实现约束。当前后端已经按拆分 checkpoint 实现了 AI 结果接收、S000/S999 特殊入口结果、订单任务基础流转、任务草稿保存、最终确认、审计列表、OPERA 模拟骨架、SuperAgent 查询上下文接口 1、2 的最小字段版,以及前端 P0 任务列表 / 订单详情查询接口;前端页面、真实 OPERA、普通任务切换订单、查询接口 3 和查询接口 4 仍未实现。
## 2. 本版核心修正
相对 V1本版有以下修正
- 增加 `AI 过渡层`:系统必须先保存 AI 原始输出,再生成订单、任务和任务卡。
- 不再使用 `EXCEPTION` 作为底层结果类型,AI 第一版结果类型统一以 `normal_task``manual_review``informational_message` 为准
- 系统主任务类型收敛为 `NEW_BOOKING``UPDATE_BOOKING``CANCEL_BOOKING``MANUAL_REVIEW`,另保留 `INFORMATIONAL_MESSAGE` 作为不参与执行队列的只读提醒任务
- 不再使用 `EXCEPTION` 作为底层结果类型,SuperAgent 结构化 JSON 新入口只使用 `normal_task``manual_review``informational_message` 仅保留历史兼容
- 新增 SuperAgent 纯文本入口结果 `S000,source_message_id``S999,source_message_id`:两者都生成只读 `SOURCE_MESSAGE_ONLY` 特殊任务,任务列表可见,订单列表不可见
- 系统主任务类型收敛为 `NEW_BOOKING``UPDATE_BOOKING``CANCEL_BOOKING``MANUAL_REVIEW`,另保留历史 `INFORMATIONAL_MESSAGE`,并新增 `SOURCE_MESSAGE_ONLY` 用于 S000/S999 特殊入口结果。
-`New Booking``Cancel Booking``Fallback/manual_review` 外,其他业务处理类卡片原则上都归到 `UPDATE_BOOKING` 下的不同任务卡。
- `Message Notification` 也挂到临时订单下面,便于归档和详情查看,但不参与订单任务执行队列,不阻塞其他任务,也不被其他任务阻塞
- `Message Notification` / `INFORMATIONAL_MESSAGE` 只作为历史兼容路径;新数据中的纯信息类邮件由 `S000` 表达
- 任务卡后端完整规则以 `任务卡展示编辑矩阵.xlsx` 为权威来源,不在代码里随意扩展或重命名字段路径。
- 前端展示 / 编辑白名单以最新导入的 `任务卡前端展示字段表 3.0.xlsx` 为准;该文件只约束前端展示和可编辑范围,不替代后端完整校验、确认写入和 OPERA 映射规则。
- 系统必须同时保存 AI 原始 `task_type`、系统主任务类型、任务卡类型和业务动作 subtype。
@@ -69,16 +70,27 @@ AgentBus / 未来其他入口
→ 系统保存每条模拟操作结果、失败原因和重试记录
```
特殊分支:
```text
SuperAgent 返回 S000,source_message_id 或 S999,source_message_id
→ 本系统按默认酒店 + external_message_id 反查 SourceMessage Inbox
→ 创建隐藏技术订单 + SOURCE_MESSAGE_ONLY 只读任务
→ 任务列表可见,订单列表不可见
→ 不允许编辑、确认、转换、OPERA 模拟或重试
```
中文说明:
- `SourceMessage Inbox` 是来源事实层,不表达订单、任务或业务结论。
- AI 只输出 JSON不直接写数据库、不直接创建真实任务卡、不直接写 OPERA。
- 本系统负责保存 AI 原始 JSON、创建任务卡、接收用户修改、生成确认后的 payload、执行 OPERA 模拟并记录结果。
- SuperAgent 不直连本系统数据库,只能通过本系统后端接口查询已有订单和任务上下文。
- S000/S999 不是业务任务,也不是人工复核任务,只是来源邮件入口处理结论。
## 5. AI 输出接收边界
导入文档已经定义了 SuperAgent / Main Agent 应输出的核心业务结构,但还没有定义完整 HTTP 接口契约
导入文档已经定义了 SuperAgent / Main Agent 应输出的核心业务结构。当前正式 HTTP 接口同时支持结构化 JSON 和 S000/S999 纯文本入口结果
AI 聚合输出的顶层结构应包含:
@@ -88,14 +100,14 @@ AI 聚合输出的顶层结构应包含:
| `ai_task_results[]` | AI 拆分出的一个或多个任务结果,顺序必须保留 |
| `extraction_warnings[]` | 抽取警告,不直接等同于业务任务 |
`ai_task_results[]` 中关键字段包括:
结构化 JSON 的 `ai_task_results[]` 中关键字段包括:
| 字段 | 中文说明 |
| --- | --- |
| `source_event_index` | AI 拆分出的 current 事件序号,同一次来源消息内用于排序 |
| `catalog_code` | Skill 目录代码,例如 S01、S02 |
| `skill_id` | 具体 Skill 标识 |
| `result_type` | AI 结果类型,第一版只使用 `normal_task``manual_review``informational_message` |
| `result_type` | AI 结果类型,新入口只使用 `normal_task``manual_review``informational_message` 仅历史兼容 |
| `task_type` | AI 原始任务类型,例如 `New Booking``Voucher Received` |
| `task_subtype` / 业务动作 | 更细的业务动作,用于任务卡字段路由 |
| `current_or_history` | 当前事件还是历史证据 |
@@ -106,12 +118,27 @@ AI 聚合输出的顶层结构应包含:
| `context_used` | AI 使用的上下文摘要 |
| `extracted_fields` | 业务字段主体 |
| `manual_review` | 人工复核结构化原因和证据 |
| `informational_message` | 信息提醒内容 |
| `informational_message` | 信息提醒内容,仅历史兼容 |
| `additional_operations` | AI 建议的附加动作 |
| `idempotency_key` | 幂等键,最终来源和生成规则待确认 |
HTTP 契约已在 `docs/project/requirements/M002-superagent-task-result-api-contract.md``docs/project/integrations/superagent-api-contract.md` 中补充。正式契约要求任务结果通知携带 `hotel_id + source_message_id`,其中 `source_message_id` 是外部来源消息 ID后端会反查内部 SourceMessage Inbox ID 后再写入 `workflow_*` 表。
纯文本入口结果格式:
```text
S000,source_message_id
S999,source_message_id
```
中文说明:
- `S000` 表示纯信息类邮件,不形成业务素材包。
- `S999` 表示入口阶段无法形成业务素材包。
- `source_message_id` 是外部来源消息 ID对应 AgentBus `source.external_message_id`
- 第一版使用系统默认酒店反查 SourceMessage Inbox。
- 命中 SourceMessage 后创建 `SOURCE_MESSAGE_ONLY` 只读任务,并挂到 `order_visibility=HIDDEN_SYSTEM` 的技术订单下。
## 6. AI 过渡层数据要求
系统接收 AI 输出后,应先写入 AI 过渡层,再创建任务卡。过渡层用于追溯、幂等、筛选、人工确认和 OPERA 参数组装。
@@ -124,7 +151,7 @@ HTTP 契约已在 `docs/project/requirements/M002-superagent-task-result-api-con
| `case_keys_json` | AI 给出的订单关联候选键 |
| `extracted_fields_json` | AI 抽取的业务字段 |
| `manual_review_json` | 人工复核信息 |
| `informational_message_json` | 信息提醒内容 |
| `informational_message_json` | 信息提醒内容,仅历史兼容 |
| `attachments_json` | 附件和文件引用 |
| `context_used_json` | AI 使用的上下文 |
| `confirmed_payload_json` | 用户修改并确认后的最终参数 |
@@ -137,9 +164,9 @@ HTTP 契约已在 `docs/project/requirements/M002-superagent-task-result-api-con
| `source_event_index` | AI 事件序号 |
| `catalog_code` | Skill 目录代码 |
| `skill_id` | Skill 标识 |
| `result_type` | AI 结果类型 |
| `result_type` | AI 结果类型S000/S999 内部保存为 `source_message_only` |
| `ai_task_type` | AI 原始任务类型 |
| `system_task_type` | 系统主任务类型 |
| `system_task_type` | 系统主任务类型S000/S999 为 `SOURCE_MESSAGE_ONLY` |
| `task_card_type` | 任务卡类型 |
| `task_subtype` | 业务动作 subtype |
| `current_or_history` | 当前或历史标识 |
@@ -159,15 +186,17 @@ HTTP 契约已在 `docs/project/requirements/M002-superagent-task-result-api-con
### 7.1 AI 结果类型
AI 第一版结果类型只接受:
AI 新入口结构化 JSON 结果类型只接受:
| `result_type` | 中文说明 | 是否可直接 OPERA 模拟 |
| --- | --- | --- |
| `normal_task` | 可生成业务任务卡的正常任务 | 需用户确认后才允许 |
| `manual_review` | 需要人工复核的结构化任务 | 不允许直接写 OPERA |
| `informational_message` | 只读信息提醒 | 不允许写 OPERA |
| `informational_message` | 只读信息提醒,仅历史兼容 | 不允许写 OPERA |
不使用 `exception_task``no_action`。原来讨论中的异常任务,在本版统一落为 `manual_review`;没有业务动作的信息提醒,统一落为 `informational_message`
不使用 `exception_task``no_action`。原来讨论中的异常任务,在本版统一落为 `manual_review`;没有业务动作的信息类邮件,新入口不再生成 `informational_message` JSON而是返回 `S000,source_message_id`
S000/S999 不属于结构化 `result_type`,它们是纯文本入口结果,系统内部保存为 `source_message_only` 过渡记录和 `SOURCE_MESSAGE_ONLY` 只读任务。
### 7.2 系统主任务类型
@@ -179,7 +208,8 @@ AI 第一版结果类型只接受:
| `UPDATE_BOOKING` | 更新订单任务,下面承载多个不同任务卡 |
| `CANCEL_BOOKING` | 取消订单任务 |
| `MANUAL_REVIEW` | 人工复核或 Fallback 任务 |
| `INFORMATIONAL_MESSAGE` | 信息提醒任务,只归档展示,不参与执行队列 |
| `INFORMATIONAL_MESSAGE` | 信息提醒任务,只归档展示,不参与执行队列,仅历史兼容 |
| `SOURCE_MESSAGE_ONLY` | S000/S999 来源消息入口结果任务,只读展示,不参与执行队列 |
### 7.3 AI 任务类型到系统任务和卡片的映射
@@ -193,16 +223,38 @@ AI 第一版结果类型只接受:
| `Trace / Reservation Notes` | `UPDATE_BOOKING` | `TRACE_RESERVATION_NOTES` | Trace 或备注卡,可作为联动任务 |
| `TA Recorder` | `UPDATE_BOOKING` | `TA_RECORDER` | TA Recorder 维护卡,通常由 Rooming List 派生 |
| `Cancel Booking` | `CANCEL_BOOKING` | `CANCEL_BOOKING` | 取消 FIT、Group Block、Allotment / Control Block |
| `Message Notification` | `INFORMATIONAL_MESSAGE` | `MESSAGE_NOTIFICATION` | 挂临时订单,只读展示,不参与执行队列 |
| `Message Notification` | `INFORMATIONAL_MESSAGE` | `MESSAGE_NOTIFICATION` | 历史兼容路径;新纯信息类邮件改用 S000 |
| `Fallback` | `MANUAL_REVIEW` | `FALLBACK_REVIEW` | 人工复核任务 |
| `S000` 文本结果 | `SOURCE_MESSAGE_ONLY` | `SOURCE_MESSAGE_ONLY` | 纯信息类邮件,任务列表可见,订单列表不可见 |
| `S999` 文本结果 | `SOURCE_MESSAGE_ONLY` | `SOURCE_MESSAGE_ONLY` | 无法形成业务素材包,任务列表可见,订单列表不可见 |
系统不得丢弃 AI 原始 `task_type`。任务落库时应同时保存 AI 原始任务类型、系统主任务类型、任务卡类型和业务动作 subtype。
## 8. Message Notification 处理规则
## 8. S000/S999 和历史 Message Notification 处理规则
### 8.1 S000/S999 处理规则
`S000` / `S999` 是 SuperAgent 入口阶段返回的纯文本结果,不是结构化任务 JSON。
本系统处理规则:
- `S000` 表示纯信息类邮件。
- `S999` 表示无法形成业务素材包。
- 两者都按外部 `source_message_id` 反查 SourceMessage Inbox。
- 第一版使用系统默认酒店,不要求请求体携带 `hotel_id`
- 创建 `SOURCE_MESSAGE_ONLY` 只读任务,`task_subtype` 分别为 `S000``S999`
- 创建 `order_visibility=HIDDEN_SYSTEM` 的技术订单,仅用于满足任务归属,不进入订单列表和订单详情。
- 任务状态为 `COMPLETED``queue_participation=false`
- 任务列表可见;订单列表不可见。
- 任务详情可查看来源邮件、会话、附件和 SuperAgent 原始返回。
- 不允许保存草稿、最终确认、人工转换、普通切换订单、执行 OPERA 模拟或重试 OPERA。
- 不阻塞任何订单任务,也不被任何订单任务阻塞。
### 8.2 历史 Message Notification 处理规则
`Message Notification` 用于感谢、知会、已收到、转发说明、信息同步等没有明确业务执行动作的消息。
本系统处理规则:
该路径仅为历史兼容,新数据应由 SuperAgent 返回 `S000,source_message_id`。历史数据处理规则:
- 创建临时订单作为归档容器。
- 创建只读信息提醒任务卡。

View File

@@ -4,15 +4,15 @@
| 项目 | 内容 |
| --- | --- |
| 文档版本 | 0.2 |
| 日期 | 2026-07-07 |
| 文档版本 | 0.3 |
| 日期 | 2026-07-10 |
| 状态 | 后端接口契约草稿 |
| 适用范围 | SuperAgent / Main Agent 调用本系统提交 AI 任务结果 |
| 主要读者 | 后端、SuperAgent 对接方、测试、后续协作 agent |
## 1. 文档定位
本文定义 SuperAgent / Main Agent 向本系统提交 `ai_task_results[]`第一版后端接口契约。
本文定义 SuperAgent / Main Agent 向本系统提交 `ai_task_results[]` 结构化结果,以及提交 S000/S999 特殊入口结果的后端接口契约。
本文承接 `M002-order-task-workflow-v2.md`,只定义本系统入站接口、鉴权、幂等、请求响应和技术校验边界,不定义 SuperAgent 内部 prompt、Skill 实现、OPERA 真实接口或前端展示细节。
@@ -22,17 +22,19 @@
| --- | --- |
| Method | `POST` |
| Path | `/api/integrations/superagent/task-results` |
| Content-Type | `application/json` |
| Content-Type | `application/json``text/plain` |
| 响应格式 | `application/json` |
| 一次请求范围 | 只能包含一个 `source_message_id` |
| 业务动作 | 接收 AI 结果、写入 AI 过渡层、生成订单 / 任务 / 任务卡 |
| 业务动作 | 接收 AI 结果或入口结果、写入 AI 过渡层、生成订单 / 任务 / 任务卡 |
| 鉴权方式 | HMAC-SHA256 签名 |
中文说明:
- 该接口是服务到服务的入站接口,不给前端直接调用。
- SuperAgent 不直连数据库,只能通过本接口提交任务结果。
- SuperAgent 不直连数据库,只能通过本接口提交任务结果或入口处理结果
- 本接口只做技术校验和系统接收,不替代用户确认和 OPERA 模拟操作。
- `application/json` 用于 `normal_task` / `manual_review` 结构化任务。
- `text/plain` 用于 `S000,source_message_id` / `S999,source_message_id` 特殊入口结果。
### 2.1 SourceMessage ID 口径
@@ -114,13 +116,16 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
4. 计算原始请求体 SHA-256。
5. 使用 HMAC secret 重新计算签名。
6. 使用常量时间比较签名。
7. 鉴权通过后再解析 JSON
7. 校验 `Content-Type` 是否为 `application/json``text/plain`,避免不支持的媒体类型消耗 nonce
8. 鉴权通过后再按 body 内容解析 JSON 或 S000/S999 文本。
日志和错误响应不得输出 secret、签名原文、完整请求体、邮件正文、附件 URL 或个人敏感信息。
## 4. 请求体
请求体沿用 AI 导入文档定义的聚合结构。
### 4.1 JSON 结构化任务请求体
JSON 请求体沿用 AI 导入文档定义的聚合结构。
```json
{
@@ -155,7 +160,7 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
}
```
### 4.1 顶层字段
### 4.2 顶层字段
| 字段 | 是否必填 | 中文说明 |
| --- | --- | --- |
@@ -166,16 +171,16 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
| `ai_task_results[]` | 是 | AI 拆分出的任务结果列表,必须保留数组顺序 |
| `extraction_warnings[]` | 否 | 抽取警告;不直接等同于业务任务 |
第一版要求 `ai_task_results[]` 至少包含一条记录。没有业务动作时应由 AI 输出 `Message Notification``Fallback/manual_review`,而不是提交空数组
第一版要求 `ai_task_results[]` 至少包含一条记录。没有业务动作的纯信息类邮件不要提交空数组,也不要新生成 `informational_message`;应改用 `S000,source_message_id` 文本结果
### 4.2 `ai_task_results[]` 字段
### 4.3 `ai_task_results[]` 字段
| 字段 | 是否必填 | 中文说明 |
| --- | --- | --- |
| `source_event_index` | 是 | AI current 事件序号,建议从 1 开始 |
| `catalog_code` | 是 | Skill 目录代码,例如 S01、S02 |
| `skill_id` | 是 | Skill 标识 |
| `result_type` | 是 | 只接受 `normal_task``manual_review``informational_message` |
| `result_type` | 是 | 新入口只接受 `normal_task``manual_review``informational_message` 仅历史兼容 |
| `task_type` | 是 | AI 原始任务类型 |
| `task_subtype` | 否 | 业务动作 subtype有则用于任务卡路由 |
| `current_or_history` | 否 | 当前或历史标识 |
@@ -186,10 +191,42 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
| `context_used` | 否 | AI 使用的上下文 |
| `extracted_fields` | 否 | 业务字段主体 |
| `manual_review` | 条件必填 | `result_type=manual_review` 时应提供 |
| `informational_message` | 条件必填 | `result_type=informational_message` 时应提供 |
| `informational_message` | 条件必填 | 仅历史兼容;新数据不再生成 |
| `additional_operations` | 否 | 附加动作建议 |
| `idempotency_key` | 否 | 可忽略;本系统第一版自行生成幂等键 |
### 4.4 S000/S999 文本结果请求体
当 SuperAgent 入口阶段没有结构化任务 JSON 时,可以直接提交纯文本 body
```text
S000,mail-20260708-0001
```
或:
```text
S999,mail-20260708-0001
```
字段说明:
| 片段 | 中文说明 |
| --- | --- |
| `S000` | 纯信息类邮件,不形成业务素材包 |
| `S999` | 入口阶段无法形成业务素材包 |
| `source_message_id` | 逗号后面的值,外部来源消息 ID对应 AgentBus `source.external_message_id` |
处理规则:
- 第一版使用系统默认酒店反查 SourceMessage Inbox不要求文本 body 携带 `hotel_id`
- 后端按 `默认酒店 + AGENTBUS + EMAIL + external_message_id` 查询 SourceMessage。
- 命中后创建 `SOURCE_MESSAGE_ONLY` 只读任务。
- 任务列表可见,订单列表不可见。
- 不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA。
- 同一 SourceMessage 重复提交相同文本 body 返回幂等重放。
- 同一 SourceMessage 已经存在不同 AI 结果请求时返回幂等冲突。
## 5. 技术校验边界
本接口只做技术校验,不做业务合法性判断。
@@ -198,12 +235,13 @@ X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
- 鉴权签名合法。
- 请求体大小不超过限制。
- JSON 可解析
- `hotel_id` 存在。仅本地旧夹具兼容缺少 `hotel_id``source_message_id` 为内部数字 ID 的调用。
- JSON body 可解析S000/S999 文本 body 必须符合 `结果码,source_message_id`
- JSON body 中 `hotel_id` 存在。仅本地旧夹具兼容缺少 `hotel_id``source_message_id` 为内部数字 ID 的调用。
- S000/S999 文本 body 第一版使用系统默认酒店,不读取 `hotel_id`
- 顶层只有一个 `source_message_id`
- `source_message_id` 对应的外部来源消息已经写入 SourceMessage Inbox。
- `ai_task_results[]` 是非空数组。
- `result_type` 属于允许值。
- JSON `result_type` 属于允许值。
- `task_type` 属于当前系统可识别的稳定值或可进入 Fallback 处理。
- 同一个请求内 `source_event_index` 和数组顺序可保存。
- 关键字符串长度不超过数据库限制。
@@ -246,6 +284,7 @@ sha256(
- 相同请求体重复提交时识别为幂等重放。
- 同一个外部 `source_message_id` 解析到的内部 SourceMessage 如果提交了不同请求体,不会被误认为同一个批次。
- S000/S999 文本 body 也使用同一批次幂等规则。
### 6.3 item 幂等键
@@ -296,7 +335,8 @@ sha256(
| `case_keys` | `case_keys_json` | 保存订单候选键 |
| `extracted_fields` | `extracted_fields_json` | 保存业务字段 |
| `manual_review` | `manual_review_json` | 保存人工复核结构 |
| `informational_message` | `informational_message_json` | 保存信息提醒 |
| `informational_message` | `informational_message_json` | 仅历史兼容的信息提醒结构 |
| `S000/S999` 文本结果 | `SOURCE_MESSAGE_ONLY` 只读特殊任务 | 保存入口阶段原始结果,不创建真实业务订单 |
系统主任务类型映射以 `M002-order-task-workflow-v2.md` 为准。
@@ -331,6 +371,35 @@ sha256(
}
```
S000 / S999 文本结果创建成功时,同样返回 `201 Created`。这类结果会创建只读特殊任务和隐藏技术订单,供任务列表展示和任务详情查看来源邮件;该隐藏技术订单不会出现在订单列表。
```json
{
"request_id": "req-20260707-0003",
"source_message_id": "mail-20260708-0001",
"batch_id": "1900000000000005001",
"idempotent_replay": false,
"accepted_count": 1,
"items": [
{
"source_event_index": 1,
"array_index": 1,
"ai_transition_id": "1900000000000006001",
"order_id": "1900000000000007001",
"task_id": "1900000000000008001",
"system_task_type": "SOURCE_MESSAGE_ONLY",
"task_card_type": "SOURCE_MESSAGE_ONLY",
"task_status": "COMPLETED",
"order_status": "TEMPORARY",
"execution_order": 1
}
],
"warnings": []
}
```
前端通过任务详情查看该类任务时,字段列表和 OPERA 操作列表为空,按钮应全部只读;`source_message_only_result` 会返回 `entry_result_code``entry_result_meaning``entry_result_description``entry_result_source_message_id``raw_answer`
### 8.2 幂等重放
相同请求体重复提交时返回 `200 OK`