Files
th-hotel-simple/docs/import/20260710/归档/skills/booking-desk-event/references/00-output-contract.md
2026-07-12 09:57:54 +08:00

14 KiB
Raw Blame History

输出契约

用途

定义 booking-desk-event 的统一 JSON 输出,以及 Main Agent 的 S10/S99 源邮件查看通知结果。所有业务事件都先是候选 MessageEvent,不是系统事实,不是真实 TaskCard。

输出交付形式

  • 最终输出必须是当前调用直接返回的结构化 JSON 参数对象,不是 JSON 字符串或结果文件。
  • JSON 根对象必须直接使用本契约定义的顶层结构,不得增加 booking_datafilefilenameartifactdownload_url 或其他文件包装层。
  • 不得创建、写入、上传、附加或返回 booking_data.json 或任何其他结果 JSON 文件。
  • 不得用结果文件名、文件路径、下载链接、artifact 或文件引用代替最终 JSON 参数对象。
  • 最终返回值不得使用 Markdown 代码块,也不得在 JSON 前后附加解释性文字。
  • 不得为交付形式增加 output_modefilename 等非业务字段。
  • 输入附件引用仍可保留在事件的 attachmentsfile_references 中,但只能作为输入证据,不能替代最终 JSON 参数对象。

Source Message Identity

  • 所有合规的业务输出、S10S99 都必须包含 source_message
  • source_message.source_message_id 必须是上游提供的非空值,用于通知系统关联和展示原邮件;不得猜测、生成或从其他编号替代。
  • subject、from、cc、received_at 等其他元数据不可得时使用 null 或空数组。
  • 上游没有提供 source_message_id 时属于本业务契约之外的输入或基础设施错误,不能产生一个声称合规的 S10S99

Main Agent Notification Outcome

S10S99 共用以下源邮件查看通知结构:

{
  "source_message": {
    "source_message_id": "<required>",
    "subject": null,
    "from": null,
    "cc": [],
    "received_at": null,
    "source_channel": "Email"
  },
  "route_code": "S10 | S99",
  "handler_type": "main_agent_outcome",
  "result_type": "source_message_review_notification",
  "current_or_history": "current",
  "agent_assessment": {
    "status": "no_booking_action_detected | material_package_unavailable",
    "reason_code": "",
    "automation_action": "none"
  },
  "notification": {
    "required": true,
    "notification_type": "source_message_review",
    "show_source_message": true,
    "requires_user_decision": true,
    "visible_message": ""
  },
  "manual_review": null
}
  • S10 固定使用 status=no_booking_action_detectedreason_code=no_booking_action_detectedmanual_review=null。为保持信息系统兼容,字段和值不变;其业务含义是输入可理解但未匹配当前 Agent 支持的业务事件,不表示用户无需查看、回复或处理源邮件。
  • S99 固定使用 status=material_package_unavailable;为保持信息系统兼容,字段和值不变。它表示当前输入不足、无法判断是否匹配支持业务事件;agent_assessment.reason_code 必须与 manual_review.reason_code 一致,manual_review.review_record_type=main_agent_entry_review
  • 两者均使用 requires_user_decision=true,不得增加 action_required 替用户判断是否介入。
  • S99 只用于输入不足、无法完成支持范围分类。已经匹配支持业务事件但参数或目标不安全时,使用业务事件 Need Manual Review

S99.manual_review 必须使用:

{
  "reason_code": "material_package_unavailable",
  "visible_reason": "当前输入不足,无法完成支持业务事件范围分类。",
  "review_record_type": "main_agent_entry_review",
  "missing_fields": [],
  "blocking_points": [],
  "conflicting_points": [],
  "suggested_human_actions": ["review_source_message"],
  "evidence_to_check": ["source_message"],
  "known_fields": {}
}

业务事件顶层结构

{
  "source_message": {
    "source_message_id": "<required>",
    "subject": null,
    "from": null,
    "cc": [],
    "received_at": null,
    "source_channel": "Email"
  },
  "message_events": [],
  "case_candidates": [],
  "extraction_warnings": [],
  "unhandled_current_intents": []
}

所有业务输出都必须固定包含以上五个顶层字段。没有未覆盖当前意图时,unhandled_current_intents 使用空数组。该字段只属于业务输出;S10S99 保持既有入口通知结构,不增加该字段。

Unhandled Current Intents

unhandled_current_intents 用于展示同一邮件中意图清楚、具有当前业务意义,但现有事件目录或任务卡无法承接的内容。它不是 MessageEvent,信息系统不得据此自动创建 TaskCard。

每项固定使用:

{
  "category": "unhandled_current_business_content",
  "current_or_history": "current",
  "reason_code": "requires_business_approval_or_unsupported_task_card",
  "text_raw": "<当前证据原文>",
  "visible_message": "当前邮件包含未被现有任务类型覆盖的业务意图:<忠实中文概述>。请查看原邮件并决定后续处理。",
  "requires_user_decision": true,
  "case_keys": {
    "group_code": null,
    "confirmation_number": null,
    "reservation_number": null,
    "block_code": null
  },
  "attachments": [],
  "file_references": []
}

固定规则:

  • 仅由当前正文、当前附件、当前 OCR、当前表格或当前继续处理指令产生history-only 内容不得进入。
  • text_raw 原样保留;visible_message 提供忠实中文说明,不得增加批准、拒绝、执行或业务结论。无法安全翻译时使用“当前邮件包含未被现有任务类型覆盖的业务意图,请查看原文并决定后续处理。”
  • requires_user_decision 固定为 true
  • case_keys 始终包含四个键。仅在当前证据或允许的历史证据唯一支持时填写;否则使用 null,不得猜测。
  • attachmentsfile_references 只保留当前证据引用;历史附件不得带入。
  • 一个独立意图一个 item按当前证据顺序输出连续多句组成同一请求时保持一个 item。
  • HTML/plain MIME alternatives、重复 OCR、quoted thread 和已被事件完整承接的内容不得重复输出。
  • 清楚但不支持的业务意图使用本字段;已匹配支持事件但参数或目标不安全时使用 Need Manual Review;内容不可读或抽取失败时使用 extraction_warnings 或相应人工复核。
  • extraction_warnings 只承载解析、OCR、抽取和证据质量问题不得用来承载未覆盖业务意图。
  • source_message_id 只保留在根 source_message,不得在 item 内重复。

详细覆盖顺序遵循 03-current-content-completeness.md

支持业务事件类型

  • New Booking
  • Update Booking / Amendment
  • Cancel Booking
  • Cancel Allotment
  • Voucher Received
  • Payment Evidence
  • Rooming List
  • Allotment Maintenance
  • AMEND GROUP CODE
  • Invoice Generation
  • Invoice Received
  • Payment Notice
  • Trace
  • Manual RateCode
  • TA RECORDER
  • Note

普通预订补充信息统一输出 TraceNote 暂时仅为旧契约兼容保留,不作为当前普通补充信息的路由结果,除非后续任务卡映射另有明确规则。

业务人工复核结果

  • Need Manual Review

单个事件

{
  "event_type": "",
  "event_role": "travel_agent_request",
  "current_or_history": "current",
  "source_event_index": "E1",
  "case_keys": {
    "group_code": null,
    "confirmation_number": null,
    "reservation_number": null,
    "block_code": null
  },
  "relevant_message_excerpt": "",
  "attachments": [],
  "file_references": [],
  "context_used": {},
  "extracted_fields": {},
  "manual_review": null
}

Case Key

  • case_keys.group_code 必须是单值或 null
  • 多个 group code 必须拆成多个事件。
  • U-<number> 是价格或 Rate Code marker绝不能写入 confirmation、reservation、booking reference 或 target key。
  • Parent allocation group code 是证据,不是 child event 的 case_keys.group_code

Date Evidence

涉及入住、离店或晚数时,extracted_fields 应保留:

{
  "arrival_date": "2026-05-14",
  "departure_date": "2026-05-15",
  "nights": 1,
  "date_evidence": {
    "hotel_date_raw": "14-15",
    "tour_date_raw": "2026/05/11\n2026/05/16",
    "action_date_raw": "11/05 AMD",
    "sheet_month_year": "BOOKING 05-2026",
    "date_inference_basis": "hotel_date_range_with_tour_date_context"
  }
}

日期识别必须遵循 54-stay-date-parsing.mdaction_date_raw 是动作日期证据,不是入住日期。

Trace Contract

Trace 用于当前邮件中能绑定具体预订对象、但不属于主任务核心参数的补充业务信息。要求、安排、备注和包含具体预订事实的单纯告知都可以触发 Trace不要判断发件人是否明确要求酒店记录、执行或转交。

同一封邮件、同一目标对象只输出一个 Trace。多条补充信息按当前证据顺序合并

{
  "event_type": "Trace",
  "extracted_fields": {
    "trace_subtype": "extra_bed | general_request",
    "trace_text": "<按当前证据顺序合并的完整补充信息原文>",
    "trace_items": [
      {
        "category": "extra_bed | room_preference | room_setup | meeting | function | meal | transport | payment_information | general_information",
        "text_raw": "<单条原文>",
        "service_date": "YYYY-MM-DD | null",
        "service_period_raw": "<原始时段或 null>",
        "pax": null,
        "notify_departments": []
      }
    ],
    "notify_departments": []
  }
}
  • trace_text 必须保留完整原文,结构化字段不能替代原文。
  • trace_items 的顺序必须与 trace_text 一致。
  • category 必须使用固定枚举banquet 归入 function,无法归入更具体类别时使用 general_information
  • service_dateservice_period_rawpax 只有在证据明确时填写,否则为 null
  • item 的 notify_departments 只保留明确或规则唯一支持的部门;事件级 notify_departments 是 item 已知部门的去重合集。
  • 部门不清时使用空数组,不得仅因此输出人工复核。
  • 全部 item 都是 extra bed 时使用 trace_subtype=extra_bed;其他情况使用 general_request
  • Trace 包含 extra bed item 时,继续在事件级 extracted_fields 保留原有 occupancy_updaterequires_rate_updaterate_adjustment_formula,不得移动到 item 或删除。
  • 主事件已完整承接的核心参数不得重复生成 Trace。
  • 不同目标对象必须拆成不同 Tracecase_keys.group_code 仍为单值。
  • payment_information 只表示已经确定、需要随预订保留的补充付款安排付款凭证、到账结果、Payment Notice、Invoice、催款或付款条件审批询问不得改名为 Trace。

FYI guide will arrive at 20:00 等具体预订告知可以触发 Trace只有 ThanksNotedReceived、裸 FYI 等没有具体业务信息的文字不能触发 Trace。需要酒店进行价格、退款、账期、付款政策、合同条件或其他业务审批的询问也不能伪装成 Trace。

不属于 Trace 但具有当前业务意义的内容必须原样保留在 Main Agent 素材包的 unknowns 中。只要同邮件存在至少一个支持事件,业务 skill 就按 03-current-content-completeness.md 将其一对一输出到顶层 unhandled_current_intents;不得静默忽略或改成 Trace。

人工复核

{
  "manual_review": {
    "reason_code": "",
    "visible_reason": "",
    "review_record_type": "business_event_review",
    "missing_fields": [],
    "blocking_points": [],
    "conflicting_points": [],
    "suggested_human_actions": [],
    "evidence_to_check": [],
    "known_fields": {}
  }
}

派生事件

派生或关联事件使用:

{
  "related_source_event_index": "",
  "related_source_event_indices": [],
  "related_event_type": "",
  "relationship_type": "",
  "requires_downstream_hard_validation": true
}

related_source_event_index 用于单一关联事件;一个派生事件关联多个来源事件时使用 related_source_event_indices

典型场景:

  • New/Update/Amend Group Code 同事件出现 extra bed、Meeting、meal、arrival notice 或其他预订补充信息,按目标派生一个 linked Trace
  • Rooming List 按每个目标 group 派生 TA RECORDER
  • Parent-to-child allocation creation 必须派生独立的 parent release/cancel 候选 message_event,不得只放进 child New Booking.extracted_fields

Parent-To-Child Parent Candidate

当 current evidence 确认 parent group 拆成 child group codes且 parent group code 清楚时,必须额外输出一个 parent release/cancel candidate

{
  "event_type": "Cancel Booking",
  "event_role": "travel_agent_request",
  "current_or_history": "current",
  "source_event_index": "E_PARENT_RELEASE",
  "case_keys": {
    "group_code": "<parent_group_code>",
    "confirmation_number": null,
    "reservation_number": null,
    "block_code": null
  },
  "relevant_message_excerpt": "<parent line + split evidence>",
  "attachments": [],
  "file_references": [],
  "context_used": {
    "source": "current parent-to-child allocation evidence"
  },
  "extracted_fields": {
    "parent_release_or_cancel_candidate": true,
    "release_reason": "parent_to_child_allocation_split",
    "parent_group_code": "<parent_group_code>",
    "child_group_codes": ["<child_group_code>"],
    "allocation_split_from_parent": true,
    "parent_original_room_summary": null
  },
  "related_source_event_indices": ["E1"],
  "related_event_type": "New Booking",
  "relationship_type": "linked_parent_release_after_child_split",
  "requires_downstream_hard_validation": true,
  "manual_review": null
}

该事件是候选事件,不代表 PMS 已取消成功,不创建真实 TaskCard不写外部系统。

禁止输出

不得输出真实 TaskCard ID、最终 Case 状态、Payment 确认、Block Status 自动转换、Receipt、Invoice 文件、Opera/PMS 写入结果。

不得生成或返回结果 JSON 文件、结果文件引用、结果下载链接或 artifact。该限制只针对最终处理结果不禁止下载、读取和解析输入附件也不禁止在事件中保留输入附件证据。