修复MCP任务结果提交契约校验
This commit is contained in:
@@ -134,6 +134,8 @@ REST request
|
||||
|
||||
M002 V3 后,写入工具优先接收结构化 `S10/S99` 或 `source_message + message_events[]` 业务根。`message_events[].source_event_index` 可以是 SuperAgent 内部事件 ID,例如 `E_CHILD_1`;MCP adapter 会在提交前按数组顺序映射为本系统一基数字索引,并校验跨事件关系是否悬空或重复。详细映射规则见 `submit-payload-mapping.md`。
|
||||
|
||||
V3 业务根写入成功时,MCP tool result 会返回 `mapping_diagnostics.source_event_index_mapping[]`,用于联调排查原始事件 ID 到本系统索引的映射;该字段不是业务任务字段,不会写入 TH Hotel 业务 payload。
|
||||
|
||||
## 9. 当前 checkpoint
|
||||
|
||||
当前 checkpoint:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 文档版本 | 0.1 |
|
||||
| 文档版本 | 0.2 |
|
||||
| 日期 | 2026-07-12 |
|
||||
| 状态 | 已落地第一版 |
|
||||
| 适用范围 | `th_hotel_submit_task_results` 的 V3/P0.1 payload adapter、schema validator 和一次提交规则 |
|
||||
@@ -34,13 +34,15 @@ server/src/main/java/cn/nianxx/thhotel/integrations/mcp/superagent/service/impl/
|
||||
|
||||
| 形态 | 判断方式 | 处理方式 |
|
||||
| --- | --- | --- |
|
||||
| V3 业务根 | 同时包含 `source_message` 和 `message_events` | 先校验根结构、source message、event 必填字段和关系索引,再按 `message_events[]` 顺序映射 `source_event_index` |
|
||||
| V3 S10/S99 入口通知 | 同时包含 `source_message` 和 `route_code` | 校验 S10/S99 根字段和 source message 后透传给业务入站服务 |
|
||||
| V2 兼容任务结果 | 包含 `ai_task_results` | 保留旧 `source_message_id + ai_task_results[]` 兼容路径 |
|
||||
| V3 业务根 | 包含 `message_events` | 校验根结构、source message、event transport 字段和关系索引,再按 `message_events[]` 顺序映射 `source_event_index`;event 业务合法性仍交给业务入站层落 `adapter_contract_error` |
|
||||
| V3 S10/S99 入口通知 | 包含 `route_code` 或入口通知 `result_type` | 校验 S10/S99 根字段和 source message 后透传给业务入站服务 |
|
||||
| V2 兼容任务结果 | 包含 `ai_task_results` | 保留旧 `source_message_id + ai_task_results[]` 兼容路径,并在 MCP 层校验完整 item schema |
|
||||
|
||||
未知根字段会在 MCP 层被拒绝,错误码为 `MCP_SUBMIT_PAYLOAD_INVALID`。
|
||||
|
||||
`source_message_id` 缺失属于既有基础设施输入错误,MCP adapter 不改写该错误通道;业务入站服务会返回 `MISSING_SOURCE_MESSAGE_ID`。
|
||||
`source_message_id` 缺失或整个 `source_message` 缺失属于既有基础设施输入错误,MCP adapter 不改写该错误通道;业务入站服务会返回 `MISSING_SOURCE_MESSAGE_ID`。
|
||||
|
||||
V3 业务根和 S10/S99 如果携带 MCP schema 中的兼容字段 `hotel_id`、`source_provider`、`source_channel`,adapter 会接受并在转交业务入站层前移除。业务定位仍以系统酒店和 `source_message.source_message_id` 为准。
|
||||
|
||||
## 4. source_message_id 定义
|
||||
|
||||
@@ -72,10 +74,25 @@ MCP adapter 按 `message_events[]` 数组顺序生成一基数字索引:
|
||||
- `parent_source_event_index` 输出为数字。
|
||||
- `related_source_event_indices[]` 输出为字符串数字数组,保持原顺序。
|
||||
- 悬空引用、重复引用、缺失事件 ID 都在 MCP 层拒绝。
|
||||
- MCP tool result 会返回 `mapping_diagnostics.source_event_index_mapping[]`,记录原始事件 ID 到本系统索引的映射;该诊断不写入 `workflow_reservation_ai_transition.ai_payload_json`。
|
||||
|
||||
## 6. ai_task_results[] 兼容 item schema
|
||||
|
||||
V2 兼容路径仍保留,`ai_task_results[]` item 以 REST 总契约为准,第一版 MCP schema 只暴露 object,但业务入站会校验核心字段。
|
||||
V2 兼容路径仍保留,`ai_task_results[]` item 以 REST 总契约为准。当前 MCP `tools/list` 已暴露 item schema,adapter 也会在提交业务层前校验必填字段、字段类型、允许 `result_type`、未知字段和根级 `extraction_warnings`。
|
||||
|
||||
必填字段:
|
||||
|
||||
- `source_event_index`
|
||||
- `catalog_code`
|
||||
- `skill_id`
|
||||
- `result_type`
|
||||
- `task_type`
|
||||
|
||||
允许的 `result_type`:
|
||||
|
||||
- `normal_task`
|
||||
- `manual_review`
|
||||
- `informational_message`,仅历史兼容
|
||||
|
||||
建议 item 结构:
|
||||
|
||||
@@ -216,6 +233,30 @@ MCP adapter 进入业务层前会把父事件关系映射为:
|
||||
}
|
||||
```
|
||||
|
||||
MCP tool result 同时返回非业务诊断:
|
||||
|
||||
```json
|
||||
{
|
||||
"mapping_diagnostics": {
|
||||
"mapping_policy": "message_events_array_order_1_based",
|
||||
"source_event_index_mapping": [
|
||||
{
|
||||
"original_source_event_index": "E_CHILD_1",
|
||||
"mapped_source_event_index": 1
|
||||
},
|
||||
{
|
||||
"original_source_event_index": "E_CHILD_2",
|
||||
"mapped_source_event_index": 2
|
||||
},
|
||||
{
|
||||
"original_source_event_index": "E_PARENT",
|
||||
"mapped_source_event_index": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 成功示例:跨 Child Trace
|
||||
|
||||
当 Trace 覆盖完整 Parent split 的全部 Child 时,不能只绑定第一个 Child。业务结果应保留全部 Child 引用:
|
||||
@@ -300,9 +341,14 @@ MCP adapter 会把它映射为:
|
||||
覆盖内容:
|
||||
|
||||
- `tools/list` 暴露 V3 submit schema。
|
||||
- 缺失 `source_message_id` 保持既有 `MISSING_SOURCE_MESSAGE_ID` 错误。
|
||||
- `tools/list` 暴露 V2 `ai_task_results[]` item schema 和 V3 `relationship_type`。
|
||||
- 缺失 `source_message_id` 或整个 `source_message` 保持既有 `MISSING_SOURCE_MESSAGE_ID` 错误。
|
||||
- 未知根字段在业务层前被拒绝。
|
||||
- V2 item 缺必填字段在业务层前被拒绝。
|
||||
- 悬空 `related_source_event_indices` 在业务层前被拒绝。
|
||||
- 重复 `related_source_event_indices` 在业务层前被拒绝。
|
||||
- `E_CHILD_1/E_CHILD_2/E_PARENT` 按数组顺序映射为 `1/2/3`。
|
||||
- 跨 Child Trace 关系映射为完整 `["1", "2"]`,不压缩到第一个 Child。
|
||||
- S10/S99 可通过 MCP 写入工具创建只读来源消息任务。
|
||||
- V3 event 业务契约错误由业务入站层保存为 `adapter_contract_error` transition。
|
||||
- 合法 Parent split 只创建一个 AI batch,并返回 `accepted_count=3`。
|
||||
|
||||
@@ -99,6 +99,11 @@
|
||||
| MCP-T05-013 | V3 多事件关系重复 | `related_source_event_indices=["E_CHILD_1","E_CHILD_1"]` | 返回 `MCP_SUBMIT_PAYLOAD_INVALID`,不写 AI batch、订单或任务 |
|
||||
| MCP-T05-014 | V3 根节点未知字段 | 根节点存在 `unexpected_root` | 返回 `MCP_SUBMIT_PAYLOAD_INVALID`,不调用业务写入 Service |
|
||||
| MCP-T05-015 | V3 跨 Child Trace | Trace event 关联全部 Child event | `related_source_event_indices[]` 保留全量关系并映射为真实索引,不压缩到第一个 Child |
|
||||
| MCP-T05-016 | V3 缺失整个 source_message | 业务根或 S10/S99 没有 `source_message` | 返回既有 `MISSING_SOURCE_MESSAGE_ID` typed infrastructure error |
|
||||
| MCP-T05-017 | V2 item 缺必填字段 | `ai_task_results[]` item 缺 `task_type` 等必填字段 | 返回 `MCP_SUBMIT_PAYLOAD_INVALID`,不调用业务写入 Service |
|
||||
| MCP-T05-018 | V3 event 业务契约错误 | event_type unsupported 但 transport 字段完整 | MCP adapter 不整批拒绝,业务入站层保存 `adapter_contract_error` transition |
|
||||
| MCP-T05-019 | V3 S10 入口通知 | `route_code=S10` | 通过 MCP 写入只读 `SOURCE_MESSAGE_ONLY` 任务 |
|
||||
| MCP-T05-020 | V3 S99 入口通知 | `route_code=S99` 且 `manual_review` 完整 | 通过 MCP 写入只读 `SOURCE_MESSAGE_ONLY` 任务 |
|
||||
|
||||
写入验证:
|
||||
|
||||
@@ -108,6 +113,8 @@
|
||||
- MCP endpoint 不能在日志输出完整 `extracted_fields` 中的敏感内容。
|
||||
- 失败响应应保留后端错误码和 message。
|
||||
- MCP adapter 校验失败时不进入业务写入 Service,且不自动重试。
|
||||
- V3 成功响应返回 `mapping_diagnostics.source_event_index_mapping[]`,但 AI transition 业务 payload 不包含该诊断字段。
|
||||
- V3 `relationship_type` 可在 event 根节点透传,也可在 `extracted_fields` 中作为业务关系字段;MCP adapter 不据此派生业务含义。
|
||||
|
||||
## 9. MCP 鉴权和开关测试
|
||||
|
||||
@@ -136,7 +143,9 @@
|
||||
- 5 个工具正常成功调用。
|
||||
- 查询接口错误 envelope 不丢失。
|
||||
- 任务结果写入成功和幂等重放正常。
|
||||
- V3 submit payload adapter 的事件索引映射、悬空关系拒绝、重复关系拒绝和未知字段拒绝正常。
|
||||
- V3 submit payload adapter 的事件索引映射、mapping 诊断、悬空关系拒绝、重复关系拒绝和未知字段拒绝正常。
|
||||
- V2 `ai_task_results[]` item schema 和 adapter 校验正常。
|
||||
- S10/S99 结构化入口通知可通过 MCP 写入工具。
|
||||
- provider/channel 隔离正常。
|
||||
- 受控正文不返回附件 URL。
|
||||
- MCP auth 失败不进入业务 Service。
|
||||
|
||||
@@ -347,7 +347,7 @@ POST /api/ai-query/v1/message-conversation/messages
|
||||
|
||||
### 7.4 输入 Schema
|
||||
|
||||
当前 MCP tool 已支持三种输入形态:
|
||||
当前 MCP tool 已支持三种输入形态,真实机器可读 schema 以 `/mcp` 的 `tools/list` 返回为准:
|
||||
|
||||
1. V3 业务根:`source_message + message_events[]`。
|
||||
2. V3 S10/S99 入口通知:`source_message + route_code`。
|
||||
@@ -355,6 +355,15 @@ POST /api/ai-query/v1/message-conversation/messages
|
||||
|
||||
MCP 层会先调用 `SuperAgentMcpSubmitPayloadAdapter` 做提交前校验和事件索引映射。`E1`、`E_CHILD_1`、`E_PARENT` 等 Agent 内部事件 ID 不会直接进入业务层;adapter 会按 `message_events[]` 顺序生成本系统一基数字 `source_event_index`,并同步映射 `related_source_event_index`、`parent_source_event_index` 和 `related_source_event_indices[]`。
|
||||
|
||||
补充规则:
|
||||
|
||||
- V3 业务根或 S10/S99 如果携带 `hotel_id`、`source_provider`、`source_channel`,MCP adapter 会接受这些兼容字段,但转交业务入站层前会移除;业务定位仍以系统酒店和外部 `source_message_id` 为准。
|
||||
- 缺失 `source_message.source_message_id` 或整个 `source_message` 时,MCP adapter 不改写错误,业务入站层返回 `MISSING_SOURCE_MESSAGE_ID`。
|
||||
- V3 event 业务合法性问题,例如 unsupported `event_type`、不完整 `case_keys`、不完整 `manual_review`,由业务入站层保存为 `adapter_contract_error` transition;MCP adapter 只拦 transport 必需问题,包括未知字段、`source_event_index` 缺失/重复、关系悬空/重复。
|
||||
- V2 `ai_task_results[]` item 已在 MCP schema 和 adapter 中完整校验,必填字段为 `source_event_index`、`catalog_code`、`skill_id`、`result_type`、`task_type`。
|
||||
|
||||
下面 JSON 是关键结构节选;不要手工复制为最终 schema,联调时应以 `tools/list` 实时返回为准。
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
@@ -458,7 +467,27 @@ MCP 层会先调用 `SuperAgentMcpSubmitPayloadAdapter` 做提交前校验和事
|
||||
"type": "array",
|
||||
"description": "V2 兼容字段:AI 拆分出的任务结果,必须保留数组顺序",
|
||||
"items": {
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["source_event_index", "catalog_code", "skill_id", "result_type", "task_type"],
|
||||
"properties": {
|
||||
"source_event_index": {
|
||||
"type": ["integer", "string"]
|
||||
},
|
||||
"catalog_code": {
|
||||
"type": "string"
|
||||
},
|
||||
"skill_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"result_type": {
|
||||
"type": "string",
|
||||
"enum": ["normal_task", "manual_review", "informational_message"]
|
||||
},
|
||||
"task_type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"extraction_warnings": {
|
||||
@@ -469,7 +498,18 @@ MCP 层会先调用 `SuperAgentMcpSubmitPayloadAdapter` 做提交前校验和事
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
"required": [],
|
||||
"oneOf": [
|
||||
{
|
||||
"required": ["source_message", "message_events", "case_candidates", "extraction_warnings", "unhandled_current_intents"]
|
||||
},
|
||||
{
|
||||
"required": ["source_message", "route_code", "handler_type", "result_type", "current_or_history", "agent_assessment", "notification", "manual_review"]
|
||||
},
|
||||
{
|
||||
"required": ["source_message_id", "ai_task_results"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -499,6 +539,7 @@ POST /api/integrations/superagent/task-results
|
||||
- `items[].order_id`:订单 ID。
|
||||
- `items[].task_id`:任务 ID。
|
||||
- `items[].task_status`:任务状态。
|
||||
- `mapping_diagnostics`:仅 MCP 写入工具在 V3 业务根映射时返回,记录 Agent 原始事件 ID 到本系统一基索引的映射;不写入业务 JSON。
|
||||
|
||||
完整字段以 `superagent-api-contract.md` 第 8 节为准。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user