补齐C1正文资料交付和C2配额分类规则,完善Proposal人工任务、固定图片过滤及邮件附件展示。 修正失败终态与恢复上限,增加关闭状态的通知组件,永久保留处理历史并完善筛选分页。 同步相关页面修复、迁移、测试和项目记录。 验证:后台复用同源码clean verify结果1155通过/10条件跳过;前端262项及生产构建通过;敏感资料和提交路径检查通过。
58 KiB
TH Hotel SuperAgent API 对接契约
2026-09-10 Parsing正文资料可选关联(待统一加载)
Parsing返回candidate_facts[]可增加body_binding对象,包含source_unit_ref、source_segment_ref、room_item_ref(日期项为null);值为Agent自建正文局部标记,随target及material_state区分修改前后、日期和房型。省略/为null保持旧返回兼容;不修改Parser事实或最终业务契约。当前正文来源和正文目标通过原受控Provider接收与逐项验收,不新增端点。新Skill须配合更新接收/归并/投影程序使用;Main Prompt保持已修复直接规则入口。详情见专项交付。
文档信息
| 项目 | 内容 |
|---|---|
| 文档版本 | 0.17 |
| 日期 | 2026-08-17 |
| 状态 | 当前代码契约已支持 V4 订单任务 + 多卡入站、V4 S10/S99 来源通知、REST 历史兼容、M011 Booking Excel 预处理和单酒店 hotel_id 解析;MCP submit 已收口为 M002 V4-only;M012另有相互隔离且默认关闭的Field Recovery、fixed-channel Parsing Agent与Booking Business Agent出站边界,其中Parsing/Booking主线调用已强制接收安全公开Trace,运行开关仍默认关闭 |
| 适用范围 | SuperAgent 调用本系统查询上下文、查询邮件会话、提交 AI 任务结果 |
| 主要读者 | SuperAgent 对接方、后端、测试、运维 |
联调参数区
以下参数供 SuperAgent 联调时手动修改。该区块只用于 dev/test 联调,不作为生产 Secret 管理方式。
| 参数 | 当前联调值 | 中文说明 |
|---|---|---|
TH_HOTEL_API_BASE_URL |
http://8.138.234.141:18087 |
本系统后端基础地址;本地联调用 8080,部署环境改为实际网关或服务地址。 |
SYSTEM_HOTEL |
后端平台酒店表唯一 ACTIVE 酒店 |
SuperAgent 不需要配置或传入 hotel_id;单酒店阶段由 TH Hotel 后端从 platform_hotel 解析。 |
SUPERAGENT_CLIENT_ID |
superagent-debug |
SuperAgent 调用方 ID,对应 Header X-TH-Hotel-SuperAgent-Client-Id。 |
SUPERAGENT_HMAC_SECRET |
th-hotel-superagent-debug-20260709-change-before-prod |
dev/test 联调临时 HMAC 密钥;生产上线前必须更换为新的高强度随机密钥。 |
生产注意:
- 生产环境必须更换
SUPERAGENT_HMAC_SECRET,不得继续使用上述联调临时密钥。 - 生产密钥不得写入 SuperAgent skill 文件、仓库文档、前端代码、镜像或普通日志,只能通过部署 Secret / 环境变量注入。
- 本系统后端按 profile 优先读取环境专属密钥:dev 使用
SUPERAGENT_DEV_TASK_RESULT_HMAC_SECRET,test 使用SUPERAGENT_TEST_TASK_RESULT_HMAC_SECRET,prod 使用SUPERAGENT_PROD_TASK_RESULT_HMAC_SECRET;旧通用变量SUPERAGENT_TASK_RESULT_HMAC_SECRET仅作为兼容兜底。当前查询接口和任务结果通知接口共用同一个 HMAC secret。
1. 基础约定
请求地址先使用占位符:
{TH_HOTEL_API_BASE_URL}
上线或联调时由环境提供实际域名,例如 UAT、生产内网域名或 API Gateway 地址。本文所有接口均为 SuperAgent 到本系统的服务到服务调用,不给前端直接调用。
2. 通用 HMAC 鉴权
查询接口和任务结果通知接口使用同一套 HMAC-SHA256 规则。
2.1 通用 Header
| Header | 是否必填 | 中文说明 |
|---|---|---|
Content-Type |
是 | 查询接口固定 application/json;任务结果通知接口支持 application/json 或 text/plain |
X-TH-Hotel-SuperAgent-Client-Id |
是 | SuperAgent 调用方客户端 ID |
X-TH-Hotel-SuperAgent-Timestamp |
是 | UTC ISO-8601 时间,例如 2026-07-08T01:30:00Z |
X-TH-Hotel-SuperAgent-Nonce |
是 | 每次请求唯一随机值,用于防重放 |
X-TH-Hotel-SuperAgent-Signature |
是 | HMAC 签名,格式 sha256=<lowercase-hex> |
X-TH-Hotel-Request-Id |
否 | 调用方请求 ID,用于日志串联 |
X-TH-Hotel-AI-Trace-Id |
否 | AI 运行链路 ID,查询接口会原样带回 trace_id |
2.2 签名串
签名串使用接口 path,不包含域名、query string 或 fragment。
POST
<request_path>
<X-TH-Hotel-SuperAgent-Timestamp>
<X-TH-Hotel-SuperAgent-Nonce>
<X-TH-Hotel-SuperAgent-Client-Id>
<lowercase-hex-sha256-of-raw-body>
签名算法:
signature = HMAC_SHA256(SUPERAGENT_HMAC_SECRET, canonical_string)
Header 写法:
X-TH-Hotel-SuperAgent-Signature: sha256=<lowercase-hex-signature>
2.3 服务端校验顺序
- 校验请求体大小。
- 查询接口校验
Content-Type是否为application/json;任务结果通知接口校验是否为application/json或text/plain,不支持的媒体类型不消耗 nonce。 - 校验 HMAC 相关 Header 是否存在。
- 校验 timestamp 是否在允许时间窗口内。
- 计算原始请求体 SHA-256。
- 使用共享 secret 重新计算 HMAC。
- 常量时间比较签名。
- 校验并记录
client_id + nonce,防止重放。 - 鉴权和协议校验通过后再解析业务 JSON、V4 包、结构化 S10/S99、V3 业务根或 S000/S999 文本结果。
3. SourceMessage ID 口径
本系统存在两个容易混淆的 ID:
| 名称 | 中文说明 | 使用位置 |
|---|---|---|
| 外部来源消息 ID | AgentBus 邮件 payload 中的 source.external_message_id,SuperAgent / Main Agent 在最终 JSON 中原样带回为 source_message_id |
SuperAgent 任务结果通知接口入参和响应回显 |
| 内部 SourceMessage Inbox ID | platform_source_message_inbox.id,本系统数据库内部主键 |
workflow_* 表的 source_message_id 外键、前端和运维排查 |
SuperAgent 不应知道或依赖内部 SourceMessage Inbox ID,也不需要为任务结果通知传数据库层 provider/channel。任务结果通知接口收到外部 source_message_id 后,后端先解析系统酒店,再使用 hotel_id + external_message_id 反查唯一 Inbox 记录,最后用内部 ID 写入业务表;真实 provider/channel 以 SourceMessage Inbox 入库值为准。
查询接口 1、2 在 SuperAgent 查询阶段不依赖当前邮件是否已经入库。若请求体兼容旧契约传入 source_message_id 或 source_event_index,第一版后端会接收但忽略,不校验它们的格式,也不把它们作为查询边界。
查询接口 3、4 面向已经入库的邮件会话:缺省酒店由后端解析,external_conversation_id 最终仍按 hotel_id + source_provider + source_channel + external_conversation_id 查询;source_message_id 表示外部来源消息 ID,可作为锚点反查该邮件所属会话。
3.1 M002 V3 / V4 迁移提醒
2026-07-11 起,项目需求基线已确认采用 docs/project/requirements/M002-order-task-workflow-v3.md;2026-07-12 起,Parent Group / Allotment 路由采用 docs/project/requirements/M002-v3-p0.1-parent-group-routing-update.md:
- 新入口结果将从旧文本
S000/S999迁移为结构化S10/S99。 - 新业务输出将从旧
ai_task_results[]迁移为source_message + message_events[] + case_candidates[] + extraction_warnings[] + unhandled_current_intents[]。 - 后端会完整保存 AI 三元组、
route_code和系统处理分类;S10/S99仍以只读源邮件通知卡展示,任务列表可见,订单列表不可见。 - 旧
S000/S999数据继续兼容展示,语义上分别映射到S10/S99。 - 完整 Parent split 的父事件必须使用
Cancel Allotment + cancel_allotment_control_block;relationship_type=linked_parent_release_after_child_split只用于关联和 Preflight,不再作为独立任务 subtype。 - 当前新入站不接受
Cancel Booking + linked_parent_release_after_child_split作为合法业务任务;该组合仅允许历史数据只读兼容。
2026-07-18 起,M002 V4 以 docs/project/requirements/M002-v4-agent-callback-field-contract.md 和 docs/project/requirements/M002-v4-order-task-card-domain-model-cp2.md 为当前有效业务入站契约:
- V4 普通业务包使用
route_code=null、source_message、order_contexts[]和message_events[]。 source_message.source_message_id是外部来源消息 ID,对应 SourceMessage Inbox 的external_message_id,不是本系统内部数据库 ID。- 普通业务按
source_message + order_ref创建 V4 订单任务,并在订单任务下创建来源消息只读卡、Basic Information 卡和业务事件卡;V4 后新业务主线不再创建旧workflow_reservation_task。 - Basic Information 必须先确认;业务卡逐卡确认或复核解阻,确认后永久锁定;V4 第一版不提供前端草稿。
route_code=S10/S99使用 V4 来源通知模型,不创建隐藏技术订单,不进入订单详情时间线,不阻塞普通订单;前端只展示和 ack。- Account / Market / Source、Room Type、Rate Code 以本系统数据库目录稳定代码为准;SuperAgent 不应输出显示文案作为业务判断依据。
- Rate Code 第一阶段按当前酒店级
RATE_CODE目录校验;M012 v20260810 的新输出固定为 21 个基础 code,旧组合码只在后端输入兼容时规范化,绝不作为新候选返回。暂不按basic_information.account_code+ eventtarget_order.booking_type(GROUP / FIT)限定候选。SuperAgent 仍只输出稳定rate_code,不输出价格、显示名或目录对象。 - Room Information 卡的 Nights、Breakfast、Breakfast Restaurant、Group Booking Status、当前值 / 最终值 / 差异摘要由本系统后端展示模型提供;SuperAgent 不输出这些展示派生字段。
开发阶段不维护 V2/V3 旧任务兼容,测试数据可重建;该策略仅限开发 / 测试阶段,不代表生产迁移方案。生产数据迁移策略不在当前 checkpoint 处理,后续上线前另开迁移方案。
当前后端仍兼容 M002 V3 CP1-CP6 历史入口代码路径,但不作为开发阶段新业务验收重点:
- 已建立 40 条 P0.1 路由枚举 / 稳定配置;
route_code保持历史稳定,不按总数连续重编号,R41/R42仍可能出现在响应和历史 transition 中。 - 已支持结构化
S10/S99历史入站兼容;当前 V4 新入站使用来源通知模型。 - 已支持 V3 业务根
source_message + message_events[]的基础解析;可派生到现有任务模型的 event 会创建业务任务,无法派生、显式契约错误或基础 manual_review / parent split 结构不完整的 event 只落adapter_contract_errortransition,不创建业务任务。 - 已支持
unhandled_current_intents[]最小落库:只写UNHANDLED_CURRENT_INTENTtransition,不创建业务任务,也不按 adapter 契约错误返回。 - 已在
workflow_reservation_ai_transition保存route_code、system_process_category、adapter_error_code和adapter_error_message。 - 已支持 type-known manual review 同卡解阻、当前订单归属确认、P0 fixtures 回归测试和 V3 typed
infrastructure_input_error响应。
尚未完成:真实 OPERA / OHIP、普通任务切换订单、历史旧 Parent Cancel Booking payload 批量迁移、真实 PMS / OPERA / OHIP 目录同步和 SuperAgent 目录机器接口。
3.2 M011 Booking Excel 预处理输入增强
M011 已在 Debug EML 和 AgentBus 自动分发链路中接入 Booking Excel 附件预处理。该能力发生在 TH Hotel 后端调用 SuperAgent Open API 前,不属于 SuperAgent 调本系统的 task-results 请求体字段,但会影响 SuperAgent 实际看到的邮件 payload。
Debug EML 是人工调试入口,不进入 AgentBus 生产 dispatch。M002 V4 smoke 下,Debug EML 默认使用实时 AgentBus V4 Open API subject,期望 SuperAgent 后续按本契约调用 task-results 或 MCP 写入 V4 业务结果;历史 Debug V2/V3 profile 只能显式配置用于旧链路排查,不得作为 V4 smoke 默认入口。
处理边界:
- 后端只处理邮件附件中的
.xls/.xlsx,识别并排除PASSENGER_ROSTER人员名单类 Excel。 - 对
BOOKING_UPDATE和BOOKING_SURCHARGE类 Excel,按最近 6 个月候选窗口选择文件内实际存在的最新 3 个业务月,并抽取有背景色标记的业务行。 - 非空结果追加到 AgentBus Outlook-like payload 的
attachment_extractions[]字段,供 SuperAgent 作为证据输入。 attachment_extractions[]只增强 SuperAgent 判断上下文,不直接创建订单、订单任务、任务卡、客户回复或 OPERA / OHIP 操作。- 测试机 AgentBus 增强已开启;生产 AgentBus 增强默认关闭。只有
reservation.booking-excel-extraction.enabled和 AgentBus dispatch include 开关同时开启时才会追加该字段。
字段契约、抽取规则和安全边界以 docs/project/requirements/M011-booking-excel-pre-superagent-enrichment-v1.md 为准。SuperAgent 生成最终 V4 结果时,仍必须按本文第 8 节的 source_message + order_contexts[] + message_events[] 契约回调本系统。
3.3 M012 Layer 3 字段 Recovery 出站说明
2026-08-10 起,Booking PostgreSQL 主线具备一条默认关闭的字段 Recovery 出站 Adapter。它由 TH
Hotel 后端创建 SuperAgent session、发送最小 RecoveryRequestSet 并在有界 deadline 内等待完整 SSE
结果,返回值必须严格反序列化为 JSON-only RecoveryPatchSet,再由本地规则校验和组装。
真实 Open Agent API 契约如下:
- Base URL 为
https://superagent.nianxx.cn,会话接口为POST /api/open/agent-sessions,消息接口为POST /api/open/agent-sessions/{session_id}/messages/stream。 - 认证使用外部应用创建的
df_open_...Bearer token;公开请求不传profile_id。外部应用策略绑定 Profile 时固定调用该 Profile 的已发布版本,未绑定时才回退组织默认 Profile;目标 Profile 必须已发布 并开启 API exposure。 external_subject_id表示调用方外部用户/会话主体,不是 Agent 或 Profile ID。Recovery 以source_message_id的 SHA-256 派生稳定、非明文 subject;session/message 幂等键继续由 Recovery idempotency key 派生。- Recovery 使用
booking.field-recovery.open-api.*专属连接与 Secret,不回退全局 Debug/AgentBus key。 通用 client factory 也被 Booking Business Agent 使用,但两个 Agent 各自拥有独立外部应用、token、 wrapper/config 与审计,不能互相回退。 - 当前服务端要求 Bearer 鉴权请求同时携带临时 CSRF double-submit header/cookie;项目 client 已实现, Secret、CSRF 与 raw answer 均不得落日志或持久化。
- 解析 Agent 外部应用当前禁用公开 Trace,Recovery 的
include-trace默认 false。无 Trace SSE 从 coremessage.final读取最终文本,必须收到顶层end,随后查询 run status;只有status=success才接受, 并从 run metadata 补齐实际resolved_profile_id/resolved_profile_version_id。这是已被新 Parsing Agent 取代的 legacy Recovery 兼容边界;自 2026-08-17 起,当前 Parsing Agent 与 Booking Business Agent 主线各自 强制include_trace=true,不受该例外影响。
2026-08-10 已完成一次合成、隐私最小化的真实 transport/Profile-routing smoke:session 创建、无 Trace
SSE、最终事件、结束事件和 run success 均通过;未保存或输出 raw answer/key。该证据不覆盖完整
Recovery JSON contract、PostgreSQL V3 或 MANUAL_EML 端到端验收。
该链路不是本文其余章节描述的“SuperAgent 回调 TH Hotel”接口:它不使用 HMAC task-results,不使用
MCP submit,也不复用 M007 AgentBus dispatch。当前只从 MANUAL_EML 触发;AGENTBUS 必须在 Booking
下游 worker 化后才能启用等待。详细契约、开关、持久化和验收见
docs/project/requirements/M012-layer3-field-recovery-superagent-integration-change-request-v1.md。
3.4 M012 Layer 5 Booking Business Agent 出站说明
2026-09-09补充:系统随业务输入附加的说明要求先读取已配置的booking-desk-event Skill、其必需业务规则和输出Schema,
工具调用仅限这些规则文件的读取;不得使用笼统的“禁止所有工具”阻断规则加载。附件读取、数据库查询、命令执行与
外部业务操作仍不允许,输入投影、结果Schema及本地严格校验不变。该修复已进入正式项目,并按用户最新授权于2026-09-09单独加载当前5178/8082本地测试环境;真实邮件结果待复验。
2026-08-10 建立的专用 transport 已在 2026-08-14 接入 V2 durable runtime。当前权威路径不再使用旧
BookingAgentContinuationDispatcher 同步链:后端先在短 PostgreSQL 事务中提交最终 Layer 3、Layer 4、
canonical BookingDecisionInputV2、唯一 booking_agent_execution 与 AWAITING_BOOKING_AGENT,再由 V11
worker claim lease/fence,并在无数据库事务时发送受控 BookingBusinessAgentInputV1、等待完整
SSE/Provider run。严格 Candidate 单独提交后,由后续 claim 恢复 Layer 6。它不在保存 Parsing 结果的事务、
HTTP/AgentBus WebSocket callback 中等待,也不新增浏览器、MCP 或第三方入口。
- Business 使用
booking.agent.open-api.*和TH_HOTEL_BOOKING_BUSINESS_AGENT_OPEN_API_*专属配置; API Key 只能通过专用部署 Secret 注入,不回退 Recovery、Debug EML、AgentBus 或全局 Open API key。 - 公开请求同样不传
profile_id,由 Business token 对应的外部应用策略选择已发布 Profile。 external_subject_id由source_message_id的 SHA-256 派生为th-hotel-booking-business-<hash>,不再由部署提供固定主体,也不承担 Profile 路由。- Business 必须使用
include-trace=true,初始消息请求固定为messages/stream?include_trace=true;显式配置 false 时在调用 Provider 前 fail closed。Trace 成功必须同时 收到公开run.completed(status=success)与顶层end,coremessage.final不能替代完成证据。 - 平台公开 Trace 经安全投影进入
public_trace_events供 invocation audit/回放使用;message.delta/message.final的文本只在内存中参与最终回答组装,不复制到公开轨迹。URL、Secret、 Authorization、Cookie 与 CSRF 脱敏并限长;V2 raw answer 和完整 request 仍不落库。 - Provider 输出仍只是候选。JSON-only、contract/profile/run/source/revision/input hash、evidence 和引用闭包均
由本地严格 decoder 校验,随后必须经过 Layer 6;不得直接创建任务。耗尽或不可重试错误形成安全
FAIL_CLOSEDRisk,不回退本地业务分类。 booking.postgres.enabled、booking.agent.enabled、booking.agent.provider-enabled和booking.agent.worker-enabled四门同时成立才启动真实 worker;默认 false,production profile 显式固定 false。- V11 execution 提供稳定 input-hash 幂等、有限重试/退避、重启恢复和 Candidate apply-once;每个 Provider attempt 写受控 audit。V2 raw answer、完整 request、邮件正文与 Secret 不落审计。
2026-08-10 首轮真实合成 smoke 只验证了 Business token 的 session scope,message stream 当时因 Profile
API exposure 未开启返回 HTTP 403。2026-08-11 用户启用外部 API/流式接口并发布后,no-Trace 复测已通过
session/stream 200、非空 message.final、end、无 failure event 和 run success;实际
resolved_profile_id=85ab8334-4e1c-4716-8ec0-9c3c099cec9b,
resolved_profile_version_id=1711d4ed-8d0d-46fa-9d1f-4bb2d61fde23。测试期间未输出或保存 API
Key/raw answer。
上段是 2026-08-11 的历史 transport 证据,其占位 Prompt 结论已被 2026-08-14 CP5 取代:测试平台后来发布
正式 Booking v7(version 9fed48c0-1f53-4d5a-8ba0-52865c738d83),并有一次正式
CandidateDecisionV2→严格 decoder→Layer 6 的合成真实 smoke。当前实现环境没有专用 key/PG/live flags,未重新
查询平台或执行 QBD/LianTai 八场景与 V1–V11 smoke,因此部署时仍须复核当前 resolved Profile/version;历史
CP5不能作为自动 runtime/production 放行。详细变更与放行清单见
docs/project/requirements/M012-booking-business-agent-superagent-integration-change-request-v1.md与ADR-015。
2026-08-14 后续 RC6 发布/绑定后的单项合成 Trace smoke 已完成当前身份复核:resolved Profile 仍为
85ab8334-4e1c-4716-8ec0-9c3c099cec9b,发布 version ID 为
b91686f4-b8b8-4ac0-aeb4-b7a2f54a0a41。严格 Candidate/Layer 6 验证 1/1 通过;默认 expected version gate
同步,但自动 runtime、完整场景矩阵和 production 仍关闭。
3.5 M012 Fixed-Channel Parsing Agent v1 出站说明
2026-08-12 起,代码中具备一条默认/production关闭、CP4已完成内部主链与fake验收的fixed-channel Parsing Agent v1边界。它面向QBD/LIANTAI共用v1契约,不复用旧Field Recovery PatchSet或Booking Business CandidateDecision;SourceMessage loader、公共Parser、durable execution/worker、local merge和Context已接通, 真实scheduler/Provider仍受CP5开关关闭。
- 使用
booking.parsing-agent.*和TH_HOTEL_BOOKING_PARSING_AGENT_*专属配置;API key不回退任何现有 Agent/global key。只有Booking PostgreSQL和Parsing Agent两个开关同时开启时才注册wrapper/adapter。 - 公开请求仍不传
profile_id;专属token对应external app选择已发布Profile。信息系统要求返回的实际 Profile ID与expected-profile-id精确一致,否则整份结果拒绝;实际发布version只进入运行审计,不参与放行。 - Current source message ID只以SHA-256派生external subject和metadata hash;稳定v1 request ID同时作为
session/message幂等根与
X-Request-ID。完整AgentRequest JSON作为message唯一业务payload,History不截断。 - request/message/response均有UTF-8 bytes上限,超限不裁剪;外呼在独立有界executor中等待整体deadline,
队列满、超时或不可用均fail closed。Parsing Agent 必须使用
include_trace=true,显式 false 在调用前拒绝; 完整message.final + run.completed(status=success) + end由共享 Open API transport保证。 - 平台公开轨迹通过既有安全 DTO 进入 Parsing execution audit/回放;
message.delta/message.final文本不进入 可持久轨迹,URL/Secret/Cookie/CSRF脱敏并限长,raw answer与完整request继续不保存。 - Adapter只返回raw JSON给本地strict decoder/semantic validator;Provider不能直接形成effective facts。 已返回但因Profile/大小/metadata被拒绝时,只审计response SHA-256和安全session/run/Profile/model/token metadata,不保存raw answer、完整request、Secret、Cookie、CSRF、附件或隐藏推理。
booking.parsing-agent.enabled/provider-enabled/worker-enabled默认false,application-prod.yml显式固定false。真实Profile/app/token、 独立Main Prompt SHA、Skill package SHA/version、API exposure与合成smoke均属于CP5独立放行Gate。
详细运行契约见
docs/project/requirements/M012-fixed-channel-parsing-agent-v1-runtime-integration-change-request-v1.md。
4. 接口 1:查询订单上下文
4.1 请求
| 项目 | 内容 |
|---|---|
| Method | POST |
| URL | {TH_HOTEL_API_BASE_URL}/api/ai-query/v1/case-context |
| request_path | /api/ai-query/v1/case-context |
| Content-Type | application/json |
| 业务动作 | 只读查询,不创建任务、不修改订单、不写 OPERA |
4.2 请求体
{
"group_code": "GRP-001",
"confirmation_number": null,
"reservation_no": null,
"object_type_hint": "group_block",
"target_key_source": "body_current",
"body_thread_used_only_as_evidence": false
}
字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
hotel_id |
否 | 酒店上下文 ID;SuperAgent 默认不传,后端按平台酒店表唯一 ACTIVE 酒店解析。若兼容旧契约传入,单酒店阶段必须与系统酒店一致。 |
group_code |
条件必填 | Group / Allotment 查询 key |
confirmation_number |
条件必填 | FIT Confirmation Number 查询 key |
reservation_no |
条件必填 | OPERA reservation no;当前系统无可靠表源,只传该字段时会返回人工复核原因 |
object_type_hint |
否 | 调用方推测的对象类型,只作为提示 |
target_key_source |
否 | key 来源,例如 body_current、body_thread_evidence |
body_thread_used_only_as_evidence |
否 | 历史线程 key 是否仅作为证据 |
group_code、confirmation_number、reservation_no 至少一个非空。当前稳定查询能力优先支持 group_code 和 confirmation_number。
全局上下文查询最终依赖“后端解析出的酒店 ID + 业务 key”;source_message_id 和 source_event_index 不作为查询边界,传入时也不会影响查询结果。
4.3 成功响应
{
"success": true,
"request_id": "req-001",
"trace_id": "trace-001",
"data": {
"matched_order_records": [],
"pending_or_open_tasks": [],
"active_workflows": [],
"terminated_records": [],
"target_object_validation": {
"status": "none",
"matched_object_id": null,
"matched_object_type": null,
"can_create_new_booking_task": true,
"can_create_update_task": false,
"can_create_cancel_task": false,
"can_attach_voucher": false,
"can_attach_rooming_list": false,
"needs_manual_review_reason": null
},
"key_relationships": {
"group_code_and_confirmation_same_object": null,
"relationship_evidence": ""
}
},
"warnings": [],
"error": null
}
4.4 主要数据来源
| 返回字段 | 来源 |
|---|---|
matched_order_records[] |
workflow_reservation_order |
pending_or_open_tasks[] |
workflow_reservation_task + workflow_reservation_ai_transition |
terminated_records[] |
订单 ENDED / LOGIC_DELETED,任务 FAILED / COMPLETED |
active_workflows[] |
当前无独立 workflow 表,固定空数组 |
5. 接口 2:查询对象详情
5.1 请求
| 项目 | 内容 |
|---|---|
| Method | POST |
| URL | {TH_HOTEL_API_BASE_URL}/api/ai-query/v1/object-detail |
| request_path | /api/ai-query/v1/object-detail |
| Content-Type | application/json |
| 业务动作 | 只读查询对象详情,不创建任务、不修改订单、不写 OPERA |
5.2 请求体
{
"object_id": "ORDER:1900000000000000100",
"object_type": "group_block"
}
字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
hotel_id |
否 | 酒店上下文 ID;SuperAgent 默认不传,后端解析系统酒店。 |
object_id |
是 | 查询对象 ID,第一版只支持 ORDER:{order_id} |
object_type |
否 | 调用方对象类型提示,第一版不作为强校验 |
5.3 成功响应
{
"success": true,
"request_id": "req-002",
"trace_id": "trace-001",
"data": {
"object_id": "ORDER:1900000000000000100",
"object_type": "group_block",
"order_id": "1900000000000000100",
"order_key_type": "GROUP_CODE",
"group_code": "GRP-001",
"confirmation_number": null,
"reservation_no": null,
"block_id": null,
"temporary_order_code": "TMP-1900000000000000100",
"display_name": "GRP-001",
"status": "ACTIVE",
"source_message_id": "1900000000000000001",
"created_from_task_id": null,
"created_at": "2026-07-08T01:00:00Z",
"last_updated_at": "2026-07-08T01:10:00Z",
"arrival_date": null,
"departure_date": null,
"nights": null,
"guest_count": null,
"room_items": [],
"rate_code": null,
"rate_code_price": null,
"reservation_type": null,
"cancel_status": "not_cancelled",
"can_update": true,
"can_cancel": true,
"hard_validation_warnings": [
{
"code": "OPERA_PROJECTION_UNAVAILABLE",
"message": "当前系统尚未接入 OPERA 对象投影,日期、房型、房价等字段无法确认。"
}
]
},
"warnings": [],
"error": null
}
说明:接口 2 响应中的 source_message_id 当前是本系统内部 SourceMessage Inbox ID,用于对象溯源和排查;不要把该字段当作 SuperAgent 任务结果通知接口的外部 source_message_id 使用。
6. 接口 3:查询邮件会话下所有任务
6.1 请求
| 项目 | 内容 |
|---|---|
| Method | POST |
| URL | {TH_HOTEL_API_BASE_URL}/api/ai-query/v1/message-conversation/tasks |
| request_path | /api/ai-query/v1/message-conversation/tasks |
| Content-Type | application/json |
| 业务动作 | 只读查询邮件会话下任务,不创建任务、不修改订单、不写 OPERA |
6.2 请求体
按外部邮件会话 ID 查询:
{
"source_provider": "AGENTBUS",
"source_channel": "EMAIL",
"external_conversation_id": "thread-20260708-0001"
}
按外部来源消息 ID 作为锚点反查会话:
{
"source_provider": "AGENTBUS",
"source_channel": "EMAIL",
"source_message_id": "mail-20260708-0001"
}
字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
hotel_id |
否 | 酒店上下文 ID;SuperAgent 默认不传,后端解析系统酒店。 |
source_provider |
否 | 来源提供方,按会话 ID 查询和按 source_message_id 反查时都参与隔离,缺省为 AGENTBUS |
source_channel |
否 | 来源渠道,按会话 ID 查询和按 source_message_id 反查时都参与隔离,缺省为 EMAIL |
external_conversation_id |
条件必填 | 外部邮件会话 ID,对应 AgentBus source.external_conversation_id |
source_message_id |
条件必填 | 外部来源消息 ID,对应 AgentBus source.external_message_id,不是内部 Inbox ID |
external_conversation_id、source_message_id 至少一个非空。两者同时传入时,第一版以后端直接按 external_conversation_id 查询为准。
6.3 成功响应
{
"success": true,
"request_id": "req-003",
"trace_id": "trace-001",
"data": {
"hotel_id": "HOTEL-DEV",
"external_conversation_id": "thread-20260708-0001",
"task_count": 2,
"tasks": [
{
"task_id": "1900000000000000400",
"order_id": "1900000000000000300",
"external_source_message_id": "mail-20260708-0001",
"external_conversation_id": "thread-20260708-0001",
"source_received_at": "2026-07-08T01:00:00Z",
"source_event_index": 1,
"catalog_code": "S02",
"skill_id": "update_booking_amendment_skill",
"result_type": "normal_task",
"task_type": "Update Booking",
"system_task_type": "UPDATE_BOOKING",
"task_card_type": "UPDATE_BOOKING",
"task_subtype": "update_stay_dates",
"task_status": "PENDING_CONFIRM",
"queue_participation": true,
"execution_order": 1,
"parent_task_id": null,
"parent_source_event_index": null,
"linked_task_group_id": null,
"blocked_until_parent_completed": false,
"completed_at": null,
"task_created_at": "2026-07-08T01:01:00Z",
"task_updated_at": "2026-07-08T01:01:00Z"
}
]
},
"warnings": [],
"error": null
}
排序规则:
- 先按邮件
received_at正序。 - 同一封邮件下,再按任务
created_at正序。 - 若时间相同,再按
task_id正序稳定排序。
7. 接口 4:查询邮件会话下所有受控正文
7.1 请求
| 项目 | 内容 |
|---|---|
| Method | POST |
| URL | {TH_HOTEL_API_BASE_URL}/api/ai-query/v1/message-conversation/messages |
| request_path | /api/ai-query/v1/message-conversation/messages |
| Content-Type | application/json |
| 业务动作 | 只读查询邮件会话受控正文,不返回附件 URL 或原始未清洗 HTML |
7.2 请求体
请求体字段与接口 3 相同,可按 external_conversation_id 查询,也可按外部 source_message_id 锚点反查会话。
{
"source_provider": "AGENTBUS",
"source_channel": "EMAIL",
"source_message_id": "mail-20260708-0001"
}
7.3 成功响应
{
"success": true,
"request_id": "req-004",
"trace_id": "trace-001",
"data": {
"hotel_id": "HOTEL-DEV",
"external_conversation_id": "thread-20260708-0001",
"message_count": 2,
"messages": [
{
"external_source_message_id": "mail-20260708-0001",
"external_conversation_id": "thread-20260708-0001",
"sender_summary": "guest@example.test",
"subject": "Booking update",
"received_at": "2026-07-08T01:00:00Z",
"source_sent_at": "2026-07-08T00:59:00Z",
"text_body": "Please update arrival date...",
"html_body_sanitized": "<html><body>Please update arrival date...</body></html>",
"html_sanitize_required": true,
"html_render_mode": "SANITIZED_HTML"
}
]
},
"warnings": [],
"error": null
}
安全边界:
messages[]按邮件received_at正序返回。- 不返回
html_body原始未清洗 HTML。 - 不返回
attachments、inline_images、external_url、附件 URL 或 HTML 中的href/src外链属性。 - 后端读取正文时会写入 SourceMessage 原文访问审计。
8. 接口 5:SuperAgent 通知 AI 任务结果
8.1 请求
| 项目 | 内容 |
|---|---|
| Method | POST |
| URL | {TH_HOTEL_API_BASE_URL}/api/integrations/superagent/task-results |
| request_path | /api/integrations/superagent/task-results |
| Content-Type | application/json 或 text/plain |
| 业务动作 | 接收 AI 任务结果;V4 JSON 支持 S10/S99 和业务根入站基线,V3 / V2 JSON 继续兼容,旧 S000/S999 文本创建只读特殊任务 |
8.2 V4 JSON 请求体(当前推荐)
V4 普通业务包示例:
{
"route_code": null,
"source_message": {
"source_message_id": "mail-20260718-0001",
"conversation_id": "thread-001",
"subject": "Group booking and payment",
"sender": "agent@example.test",
"sent_at": "2026-07-18T02:10:00Z",
"body": "Please create group GRP-001 and note payment attached.",
"body_content_type": "text/plain",
"attachments": [
{
"id": "att-pay-1",
"name": "payment-slip.jpg",
"content_type": "image/jpeg",
"url": "https://oss.example.test/payment-slip.jpg",
"size": 251524
}
]
},
"order_contexts": [
{
"order_ref": "order-1",
"basic_information": {
"account_code": "QBD_TRAVEL",
"manual_review": null
}
}
],
"message_events": [
{
"order_ref": "order-1",
"event_type": "NEW_BOOKING",
"target_order": {
"booking_type": "GROUP",
"locator_type": "GROUP_CODE",
"locator_value": "GRP-001"
},
"arrival_date": "2026-07-26",
"departure_date": "2026-07-29",
"rate_code": "GRPA2",
"booking_scenario": "STANDARD",
"room_items": [
{
"room_type_code": "RM2",
"room_count": 2
}
],
"manual_review": null
},
{
"order_ref": "order-1",
"event_type": "PAYMENT",
"target_order": {
"booking_type": "GROUP",
"locator_type": "GROUP_CODE",
"locator_value": "GRP-001"
},
"attachment_ids": ["att-pay-1"],
"manual_review": null
}
]
}
V4 纯通知包示例:
{
"route_code": "S10",
"source_message": {
"source_message_id": "mail-20260718-0002",
"conversation_id": "thread-002",
"subject": "Thanks",
"sender": "guest@example.test",
"sent_at": "2026-07-18T02:10:00Z",
"body": "Noted with thanks.",
"body_content_type": "text/plain",
"attachments": []
},
"order_contexts": [],
"message_events": []
}
V4 字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
route_code |
是 | 普通业务固定为 null;入口通知第一版支持 S10/S99,当前新业务语义以 S10 为准,S99 仅作为兼容入口保留。 |
source_message.source_message_id |
是 | 外部来源消息 ID,对应 SourceMessage Inbox 的 external_message_id。 |
source_message.body_content_type |
是 | 只能是 text/plain 或 text/html。 |
source_message.attachments[] |
是 | 包级附件数组;每个附件必须有 id/name/content_type/url,size 可省略或为 null。 |
order_contexts[] |
普通业务必填 | 每个 order_ref 一项,第一版必须带 basic_information.account_code 和 basic_information.manual_review。 |
message_events[] |
普通业务必填 | 逐 event 入站,后端按数组顺序处理。 |
message_events[].event_type |
是 | 第一版支持 NEW_BOOKING、UPDATE_BOOKING、CANCEL_BOOKING、TRACE_RESERVATION_NOTES、ROOMING_LIST、PAYMENT。 |
message_events[].target_order |
是 | GROUP + GROUP_CODE,或 FIT + BOOKING_CODE / CONFIRMATION_NUMBER。 |
message_events[].rate_code |
NEW_BOOKING 必填,可为 null |
基础 Rate Code 稳定 code;第一阶段只要求属于当前酒店 ACTIVE 的 21 项 RATE_CODE 目录。历史组合码可由后端输入兼容规范为基础码,但新 Agent 不应输出。 |
message_events[].manual_review |
是 | 只能是 null 或布尔 true;true 必须能由当前对象中的未解决字段解释。 |
| Room Information 展示派生字段 | 不需要 | Nights、Breakfast、Breakfast Restaurant、Group Booking Status、Adult、Block ID、Confirmation Number、当前订单值和差异摘要均由本系统后端查询或派生;SuperAgent 不输出。 |
| New Booking 订单标识与真实姓名 | 不需要 | 信息系统对 FIT/GROUP 均投影独立 group_code 与 names_text。Group Code 来源别名或 GROUP_CODE locator 只能进入 group_code;guest_name 只能进入真实姓名。缺失保持空,FIT 的 Booking Code / Confirmation Number locator 不得补到任一字段;SuperAgent 原始 target_order.locator_value 不被用户回写。 |
TRACE_RESERVATION_NOTES.trace_items[].department_code |
Trace 必填 | 第一版固定为 FO / HSK / FO+HSK,不接受自由文本;正式 Department 目录后续再扩展。 |
ROOMING_LIST 专属业务字段 |
不需要 | 第一版只识别 Rooming List 事项并生成可确认任务卡;SuperAgent 不输出名单 rows、同住分组、附件 ID、Excel 或 PMS 导入参数。 |
PAYMENT.attachment_ids[] |
PAYMENT 必填 | 必须引用同包 source_message.attachments[].id;SuperAgent 不在 PAYMENT event 内复制附件名称、URL 或完整附件对象。第一版这些 ID 是只读业务事实,用户只确认卡片,不增删或替换附件集合;前端图片缩略图 / 大图预览和非图片下载由本系统根据这些 ID 匹配 SourceMessage 附件后提供。 |
当前已支持的 V4 行为:
- 命中 SourceMessage 后保存 AI batch / transition,并按
source_message + order_contexts[] + message_events[]处理。 - 普通业务包按
source_message + order_ref创建 V4 订单任务,并创建SOURCE_MESSAGE_DISPLAY、BASIC_INFORMATION和业务事件卡。 - Basic Information 必须先确认;业务卡逐卡确认或复核解阻,确认后永久锁定;V4 第一版不提供前端草稿。
ROOM_INFORMATION卡只由NEW_BOOKING、UPDATE_BOOKING、CANCEL_BOOKING触发;New / Update / Cancel 的最终值、差异、Nights、Breakfast、Breakfast Restaurant、Group Booking Status 和本地订单投影展示由本系统后端展示模型提供,不扩大 SuperAgent 输入契约。ROOMING_LIST卡第一版只做事项确认;用户点击“确认卡片”表示已人工处理,不代表名单已解析、Excel 已生成或 PMS 已导入。确认不修改 Group Booking Status 或同订单其他卡片,不要求 SuperAgent 在ROOMING_LISTevent 中额外输出字段。route_code=S10/S99创建 V4 来源通知,工作台可见,订单列表和订单详情不可见;来源通知只能 ack,不创建订单、不阻塞订单。- V4 包级结构错误如果仍能通过
source_message.source_message_id定位 SourceMessage,会返回成功接收并写入adapter_contract_errortransition;不创建订单任务、任务卡或来源通知。source_message_id缺失或找不到 SourceMessage 时仍返回明确错误。 PAYMENT.attachment_ids[]引用不存在的附件、UPDATE_BOOKING携带不允许字段、目录代码无法匹配当前酒店数据库目录,以及其他 V4 event 契约错误,只写adapter_contract_errortransition,不创建用户可处理业务任务。- 技术契约错误不会自动转为 S10/S99,也不会创建前端可处理业务任务。
当前仍未完成:真实 OPERA / OHIP、真实 PMS / OPERA / OHIP 目录同步、普通任务切换订单、SuperAgent 目录机器接口和生产目录迁移方案。
8.3 V3 S10/S99 结构化请求体
S10 示例:
{
"source_message": {
"source_message_id": "mail-20260708-0001",
"subject": null,
"from": null,
"cc": [],
"received_at": null,
"source_channel": "Email"
},
"route_code": "S10",
"handler_type": "main_agent_outcome",
"result_type": "source_message_review_notification",
"current_or_history": "current",
"agent_assessment": {
"status": "no_booking_action_detected",
"reason_code": "no_booking_action_detected",
"automation_action": "none"
},
"notification": {
"required": true,
"notification_type": "source_message_review",
"show_source_message": true,
"requires_user_decision": true,
"visible_message": "未匹配到当前 Agent 支持的业务事件类型,请查看原邮件并决定是否需要回复或进行其他处理。"
},
"manual_review": null
}
S99 与 S10 使用相同结构,但 route_code=S99,agent_assessment.status=material_package_unavailable。当前 V4 来源通知第一版不输出入口 manual_review 对象,manual_review 固定为 null;历史 V3 / 0711 入口复核对象只作为兼容资料,不作为 V4 新数据契约。
8.4 V3 业务根请求体
{
"source_message": {
"source_message_id": "mail-20260708-0002",
"subject": "New booking",
"from": null,
"cc": [],
"received_at": null,
"source_channel": "Email"
},
"message_events": [
{
"event_type": "New Booking",
"event_role": "travel_agent_request",
"source_event_index": "E1",
"current_or_history": "current",
"case_keys": {
"group_code": null,
"confirmation_number": "CNF-001",
"reservation_number": null,
"block_code": null
},
"relevant_message_excerpt": "Please create a new FIT reservation.",
"attachments": [],
"file_references": [],
"context_used": {},
"extracted_fields": {
"booking_object_type": "FIT Reservation",
"arrival_date": "2026-09-01",
"departure_date": "2026-09-03",
"room_quantity": 2,
"room_type": "Deluxe King",
"pms_room_type_code": "RM2"
},
"manual_review": null
}
],
"case_candidates": [],
"extraction_warnings": [],
"unhandled_current_intents": []
}
V3 字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
source_message.source_message_id |
是 | 外部来源消息 ID,对应 SourceMessage Inbox 的 external_message_id;缺失时返回技术错误且不落库 |
route_code |
S10/S99 必填 | 只允许 S10 或 S99,用于区分入口通知结果 |
result_type |
S10/S99 必填 | 固定为 source_message_review_notification |
message_events[] |
业务根必填 | SuperAgent 最终业务事件列表,本系统逐 event 派生路由 |
message_events[].event_type |
是 | V3 active event 或 Need Manual Review |
message_events[].event_role |
是 | 事件来源角色,第一版必须是非空字符串 |
message_events[].source_event_index |
是 | 可为 E1 或数字;后端会归一为数字序号 |
message_events[].current_or_history |
是 | 第一版只接受 current |
message_events[].case_keys |
是 | 必须包含 group_code、confirmation_number、reservation_number、block_code 四个字段,值为 string 或 null |
message_events[].relevant_message_excerpt |
是 | 当前事件的邮件证据摘录,必须是字符串 |
message_events[].attachments |
是 | 当前事件引用附件数组,无附件传空数组 |
message_events[].file_references |
是 | 当前事件引用文件数组,无文件传空数组 |
message_events[].context_used |
是 | 当前事件使用的上下文对象,无上下文传空对象 |
message_events[].extracted_fields |
是 | 业务字段主体和 subtype 判别字段,必须是对象 |
message_events[].manual_review |
否 | null 表示普通任务;对象表示 type-known manual review |
unhandled_current_intents[] |
否 | 第一版只保存 UNHANDLED_CURRENT_INTENT transition,不自动创建业务任务 |
当前已支持的 V3 行为:
- 仅 REST 历史兼容路径仍可接收 V3 业务根;MCP
th_hotel_submit_task_results已收口为 V4-only,旧 V3 payload 会返回MCP_SUBMIT_V4_REQUIRED。 - REST 历史兼容路径中,V3 event 的业务契约问题,例如 unsupported
event_type、不完整case_keys、不完整manual_review,继续由业务入站层保存为adapter_contract_errortransition。 - REST 历史兼容路径缺失
source_message.source_message_id或整个source_message时,保留业务入站层MISSING_SOURCE_MESSAGE_ID错误语义。 - 40 条 P0.1 路由进入后端枚举 / 稳定配置。
route_code是稳定代码,不因路由总数从 42 调整为 40 而重编号;联调方不要按数字连续性判断合法性。- V3 结构化
S10/S99兼容路径创建只读SOURCE_MESSAGE_ONLY任务,任务列表可见,订单列表不可见;V4 新入站不走该模型,改用来源通知。 - 业务 event 能派生到稳定路由时,复用现有订单 / 任务 / 任务卡创建链路。
- 完整 Parent split 父事件必须提交为
event_type=Cancel Allotment、extracted_fields.cancel_scope=entire_allotment_control_block、task_subtype=cancel_allotment_control_block,并保留relationship_type=linked_parent_release_after_child_split作为关系字段。 - 当前新入站若提交
event_type=Cancel Booking且relationship_type=linked_parent_release_after_child_split,写入adapter_contract_errortransition,不创建业务任务;旧 V2 兼容ai_task_results[]中的同等三元组按请求级ADAPTER_CONTRACT_ERROR拒绝。 - 同一个 Parent split cluster 重复提交 Parent 候选时,后续重复 Parent 写入
adapter_contract_errortransition,不创建第二张 Parent 业务任务。 - event 判别字段不完整、显式携带
contract_errors、根missing_fields、不完整manual_review或不完整 parent split 候选时,写入adapter_contract_errortransition,不创建订单和任务;同一邮件其他 sibling event 继续处理。 unhandled_current_intents[]写入UNHANDLED_CURRENT_INTENTtransition,不返回adapter_error_code。- V3
message_events[].relevant_message_excerpt入站后会归一化到任务卡 AI payload 根路径,供旧字段矩阵读取证据字段;SuperAgent 仍只需要按 V3 event 契约提供该字段。 - type-known manual review 第一版在同一业务任务卡解阻;New Booking 房型字段主路径已迁移为
room_items[0],例如/extracted_fields/room_items/0/pms_room_type_code。旧扁平字段仍可作为过渡提交 key,解阻接口也支持提交 P0 主field_path或旧扁平field_path,响应会归一化为 P0 主field_path。
source_message.source_message_id 缺失时返回 HTTP 400,响应体不使用通用错误包装:
{
"result_type": "infrastructure_input_error",
"error_code": "missing_source_message_id",
"retryable": true,
"missing_fields": [
"source_message.source_message_id"
]
}
8.5 V2 JSON 兼容请求体
{
"source_message_id": "mail-20260708-0001",
"ai_task_results": [
{
"source_event_index": 1,
"catalog_code": "S01",
"skill_id": "S01_new_booking_skill",
"result_type": "normal_task",
"task_type": "New Booking",
"task_subtype": "new_fit_reservation",
"current_or_history": "current",
"case_keys": {
"group_code": null,
"confirmation_number": null
},
"visible_reason": "邮件正文包含新建预订请求。",
"relevant_message_excerpt": "Please create a new booking...",
"attachments": [],
"file_references": [],
"context_used": {},
"extracted_fields": {},
"manual_review": null,
"informational_message": null,
"additional_operations": [],
"idempotency_key": null
}
],
"extraction_warnings": []
}
字段说明:
| 字段 | 是否必填 | 中文说明 |
|---|---|---|
hotel_id |
否 | 酒店上下文 ID;SuperAgent 默认不传,后端解析系统酒店后用于反查 SourceMessage Inbox 幂等键。若兼容旧契约传入,单酒店阶段必须与系统酒店一致。 |
source_message_id |
是 | SuperAgent / Main Agent 原样带回的外部来源消息 ID,对应 AgentBus source.external_message_id,一次请求只能有一个 |
source_provider |
否 | V2 兼容字段;通常不传。写入定位不使用该字段,真实 provider 以 SourceMessage Inbox 入库值为准 |
source_channel |
否 | V2 兼容字段;通常不传。写入定位不使用该字段,AgentBus 邮件真实入库渠道可能是 OUTLOOK |
ai_task_results[] |
是 | AI 拆分出的任务结果列表,必须保留数组顺序 |
ai_task_results[].source_event_index |
是 | AI current 事件序号 |
ai_task_results[].catalog_code |
是 | Skill 目录代码 |
ai_task_results[].skill_id |
是 | Skill 标识 |
ai_task_results[].result_type |
是 | 当前 REST 历史兼容契约接受 normal_task、manual_review;informational_message 仅历史兼容;MCP submit 已不接受 V2 ai_task_results[] |
ai_task_results[].task_type |
是 | AI 原始任务类型 |
ai_task_results[].task_subtype |
否 | 业务动作 subtype |
ai_task_results[].case_keys |
否 | 订单关联候选键 |
ai_task_results[].extracted_fields |
否 | 业务字段主体 |
正式联调时,SuperAgent 不需要传 hotel_id。后端通过系统酒店和外部 source_message_id 查找唯一 platform_source_message_inbox.external_message_id,真实 provider/channel 以 Inbox 入库值为准。如果没有找到,返回 SOURCE_MESSAGE_NOT_FOUND;如果同一系统酒店下匹配到多条,返回 SOURCE_MESSAGE_AMBIGUOUS。本节为 REST 历史兼容说明;MCP submit 已不接受顶层 source_message_id + ai_task_results[]。
informational_message 结构化任务仅用于历史兼容。新数据如果是纯信息类邮件或无法形成业务素材包,应优先使用 V4 S10/S99 来源通知;V3 结构化 S10/S99 和下面的 S000/S999 文本请求体仅作为旧联调或兼容路径。
8.6 S000/S999 文本请求体
纯信息类邮件:
S000,mail-20260708-0001
无法形成业务素材包:
S999,mail-20260708-0001
字段规则:
| 片段 | 中文说明 |
|---|---|
S000 |
纯信息类邮件,不需要形成业务任务。 |
S999 |
入口阶段无法形成业务素材包,不需要进入业务执行。 |
mail-20260708-0001 |
外部来源消息 ID,对应 SourceMessage Inbox 的 external_message_id。 |
S000/S999 不在 body 里传 hotel_id,后端使用平台酒店表唯一 ACTIVE 酒店和外部消息 ID 查询 SourceMessage Inbox。命中后创建 SOURCE_MESSAGE_ONLY 只读特殊任务:任务列表可见,订单列表不可见,不允许编辑、确认、转换订单、执行 OPERA 或重试 OPERA,也不参与同订单任务执行顺序阻塞。该文本格式仅为兼容路径;新数据优先使用 V4 S10/S99 来源通知。
8.7 成功响应
V4 普通业务包成功响应示例。注意:V4 新业务主线只写 V4 订单任务和任务卡,响应中的 task_id、task_status、execution_order 不再代表旧 workflow_reservation_task,因此返回 null;前端和后端内部处理应通过 V4 查询接口读取 order_task_id / card_id。
{
"request_id": "req-003",
"source_message_id": "mail-20260708-0001",
"batch_id": "1900000000000000200",
"idempotent_replay": false,
"accepted_count": 1,
"items": [
{
"source_event_index": 1,
"array_index": 1,
"ai_transition_id": "1900000000000000250",
"route_code": "R01_NEW_FIT_RESERVATION_NORMAL",
"system_process_category": "BUSINESS_TASK",
"adapter_error_code": null,
"order_id": "1900000000000000300",
"task_id": null,
"system_task_type": "NEW_BOOKING",
"task_card_type": "NEW_BOOKING",
"task_status": null,
"order_status": "ACTIVE",
"execution_order": null
}
],
"warnings": []
}
历史 V2/V3 兼容入口仍可能返回旧 task_id 和 execution_order;该路径仅作历史参考,不作为开发阶段 V4 新业务验收重点。
旧文本 S000/S999 成功响应示例:
{
"request_id": "req-004",
"source_message_id": "mail-20260708-0001",
"batch_id": "1900000000000000500",
"idempotent_replay": false,
"accepted_count": 1,
"items": [
{
"source_event_index": 1,
"array_index": 1,
"ai_transition_id": "1900000000000000550",
"route_code": "S10",
"system_process_category": "SOURCE_MESSAGE_NOTIFICATION",
"adapter_error_code": null,
"order_id": "1900000000000000600",
"task_id": "1900000000000000700",
"system_task_type": "SOURCE_MESSAGE_ONLY",
"task_card_type": "SOURCE_MESSAGE_ONLY",
"task_status": "COMPLETED",
"order_status": "TEMPORARY",
"execution_order": 1
}
],
"warnings": []
}
V3 adapter_contract_error 响应中的 items[] 不会包含 order_id / task_id:
{
"source_event_index": 2,
"array_index": 1,
"ai_transition_id": "1900000000000000800",
"route_code": null,
"system_process_category": "ADAPTER_CONTRACT_ERROR",
"adapter_error_code": "EVENT_ROUTE_UNSUPPORTED",
"order_id": null,
"task_id": null,
"system_task_type": "ADAPTER_CONTRACT_ERROR",
"task_card_type": "ADAPTER_CONTRACT_ERROR",
"task_status": null,
"order_status": null,
"execution_order": null
}
9. 错误响应
9.1 查询接口错误响应
{
"success": false,
"request_id": "req-001",
"trace_id": "trace-001",
"data": null,
"warnings": [],
"error": {
"code": "AUTH_SIGNATURE_INVALID",
"message": "签名校验失败。",
"details": {}
}
}
9.2 任务结果通知接口错误响应
{
"request_id": null,
"error_code": "AUTH_SIGNATURE_INVALID",
"message": "签名校验失败。",
"details": []
}
9.3 常见错误码
| 错误码 | HTTP 状态 | 中文说明 |
|---|---|---|
AUTH_HEADER_MISSING |
401 | HMAC 必要 Header 缺失 |
AUTH_HEADER_INVALID |
401 | HMAC Header 格式或长度无效 |
AUTH_TIMESTAMP_INVALID |
401 | timestamp 格式错误或超出时间窗口 |
AUTH_SIGNATURE_INVALID |
401 | 签名不匹配或服务端未配置 secret |
AUTH_NONCE_REPLAY |
409 | nonce 已被使用 |
REQUEST_BODY_TOO_LARGE |
413 | 请求体超过大小限制 |
REQUEST_CONTENT_TYPE_UNSUPPORTED |
415 | 查询接口 Content-Type 不是 application/json,或任务结果通知接口不是 application/json / text/plain |
REQUEST_BODY_INVALID |
400 | JSON 不合法,或 S000/S999 文本格式不符合 结果码,source_message_id |
QUERY_KEY_REQUIRED |
400 | 查询接口缺少可用业务 key |
MESSAGE_CONVERSATION_QUERY_KEY_REQUIRED |
400 | 会话查询缺少 external_conversation_id 或 source_message_id |
OBJECT_NOT_FOUND |
404 | 对象详情查询目标不存在 |
MESSAGE_CONVERSATION_NOT_FOUND |
404 | 外部邮件会话尚未写入 SourceMessage Inbox |
SYSTEM_HOTEL_NOT_CONFIGURED |
409 | 平台酒店表没有可用 ACTIVE 酒店 |
SYSTEM_HOTEL_AMBIGUOUS |
409 | 单酒店阶段平台酒店表存在多家 ACTIVE 酒店 |
HOTEL_ACCESS_DENIED |
403 | 显式传入的 hotel_id 与系统酒店或当前用户授权酒店不一致 |
SOURCE_MESSAGE_NOT_FOUND |
404 | 任务结果通知或会话锚点引用的外部来源消息尚未写入 SourceMessage Inbox |
SOURCE_MESSAGE_AMBIGUOUS |
409 | 任务结果通知的外部来源消息在同一系统酒店下匹配到多条 Inbox 记录,后端拒绝随机选择 |
missing_source_message_id |
400 | V3 请求缺少 source_message.source_message_id,响应体为 typed infrastructure_input_error |
MCP_SUBMIT_V4_REQUIRED |
200 tool error | MCP th_hotel_submit_task_results 收到的不是 M002 V4 根结构,例如旧 V2/V3 payload |
MCP_SUBMIT_PAYLOAD_INVALID |
200 tool error | MCP submit 已具备 V4 根字段,但 transport 字段类型、未知字段或 V4 source_message / attachments 结构无效 |
10. HMAC 上线配置
上线需要配置:
| 配置项 | 是否必填 | 中文说明 |
|---|---|---|
SUPERAGENT_DEV_TASK_RESULT_HMAC_SECRET |
dev 必填 | dev HMAC 共享密钥;查询接口和任务结果通知接口共用 |
SUPERAGENT_TEST_TASK_RESULT_HMAC_SECRET |
test 必填 | test HMAC 共享密钥;查询接口和任务结果通知接口共用 |
SUPERAGENT_PROD_TASK_RESULT_HMAC_SECRET |
prod 必填 | prod HMAC 共享密钥;生产不能为空,只能通过 Secret 注入 |
SUPERAGENT_TASK_RESULT_HMAC_SECRET |
兼容兜底 | 旧通用 HMAC 变量;优先使用环境专属变量 |
SUPERAGENT_TASK_RESULT_CLOCK_SKEW_SECONDS |
否 | 请求时间允许偏移,默认 300 秒 |
SUPERAGENT_TASK_RESULT_NONCE_TTL_SECONDS |
否 | nonce 防重放保存时间,默认 600 秒 |
SUPERAGENT_TASK_RESULT_MAX_BODY_BYTES |
否 | 请求体最大字节数,默认 1048576 |
SUPERAGENT_TEST_ALLOW_LEGACY_INTERNAL_SOURCE_MESSAGE_ID |
否 | 仅 test 本地旧夹具兼容内部 SourceMessage ID;正式 dev / test 联调和 prod 不应开启 |
上线注意事项:
- 本系统和 SuperAgent 必须配置同一个 HMAC secret。
- 生产 secret 只能放在部署平台 Secret 或环境变量中,不能写入仓库、镜像、前端配置或普通文档。
- SuperAgent 必须使用原始请求体计算 SHA-256,不能使用格式化后 JSON。
- HMAC canonical string 的第二行必须使用
request_path,例如/api/ai-query/v1/case-context。 - SuperAgent 每次请求必须生成全新的 nonce;同一个
client_id + nonce在 TTL 窗口内不能重复使用。 - 调用双方服务器时间必须同步,建议使用 NTP。
- 建议所有接口只暴露在 HTTPS 和可信网络边界内。
- 轮换 secret 时需要安排双写或短窗口切换;当前第一版后端只支持一个 secret,轮换窗口内需要协调发布顺序。