8.9 KiB
Main Agent 到 Skill 的内部输入契约
用途
定义 Main Agent 交给 booking-desk-event 的素材包边界、粗候选结构、调用门槛和内部回传。这个接口只存在于 Main Agent 与 Skill 之间;candidate_events 和 internal_route 都不是最终对外输出。
Main Agent 负责入口校验、取得当前素材、OCR/表格原始抽取、current/history 分离、粗候选和未覆盖当前意图。Skill 对最终 event type、subtype、目标拆分、事件合并以及 linked/derived events 拥有唯一裁决权。
本接口完全属于内部处理。Main Agent 的素材包、candidate_events、Skill 业务根返回值以及任何 internal_route 在成为公开 final_result 前,都不得调用 th-hotel-simple-superagent_th_hotel_submit_task_res。只有最外层 finalizer 在完成公开结果的形成、校验和冻结后调用一次。
目录
- Step 0:Source Message Identity
- 事件集合
- Candidate Event Item
- 调用门槛
- Skill 最终裁决与内部回传
- 行级与目标级边界
Step 0:Source Message Identity
在读取正文、附件、OCR、历史或系统上下文前,先校验 source_message.source_message_id。缺失、null、空字符串或只包含空白时,不得建立素材包或调用 Skill,固定返回输出契约定义的:
{
"result_type": "infrastructure_input_error",
"error_code": "missing_source_message_id",
"retryable": true,
"missing_fields": ["source_message.source_message_id"]
}
该结果不是 S10、S99、业务事件或人工复核,不展示源邮件通知,不创建 TaskCard。不得猜测、生成、修剪后替换或从 confirmation/group/reservation number 推导 source_message_id。
事件集合
事件集合的唯一权威定义在 00-output-contract.md:
active_emittable_event_types:当前可以由新邮件生成的普通业务 event type。legacy_accepted_event_types:只用于读取历史兼容数据;不得进入candidate_events,不得由当前邮件新生成。business_review_outcomes:业务复核 outcome;不得进入candidate_events,也不能独立满足 Skill 调用门槛。
possible_event_types 只能使用 active_emittable_event_types 中的精确值。S10、S99、Need Manual Review、Note、Allotment Maintenance 或其他 legacy/review/入口值都不是合法粗候选类型。
Candidate Event Item
每个相互独立、由 current evidence 支持的业务信号形成一个粗候选:
{
"candidate_id": "C1",
"classification_status": "coarse_supported_signal",
"possible_event_types": ["Voucher Received", "Payment Evidence"],
"evidence_refs": [
{
"source": "current_attachments",
"index": 0
}
],
"target_hints": [
{
"case_keys": {
"group_code": null,
"confirmation_number": null,
"reservation_number": null,
"block_code": null
},
"target_locator_raw": null
}
],
"uncertainty_codes": ["document_subtype_unresolved"]
}
固定规则:
candidate_id必须匹配^C[1-9][0-9]*$,并在本素材包中唯一。classification_status固定为coarse_supported_signal,表示 Main Agent 没有作最终业务裁决。possible_event_types必须非空、去重,只能使用 active 集合精确值;可以保留多个候选类型。evidence_refs必须非空,只能引用 current 素材。source只能是body_current、current_attachments、current_tables、current_ocr或parent_child_split_evidence;index必须是存在于对应素材中的非负整数索引,body_current固定使用0。target_hints是非权威提示,可以为空或包含多个 item。每个 item 固定包含四键case_keys和原始 locator;不唯一时保持null,不得猜测。- Allotment / Control Block / Parent Group 的 target hint 使用同一对象语义:只识别到
group_code或block_code任一边时,归一后同时填入两边;两边同时出现但冲突时均保持null,并在target_locator_raw和 split evidence 中保留两个原始候选。Child/普通 Group Block 不做双 key 补齐。 uncertainty_codes可以为空;有不确定性时使用稳定 reason code,不用自然语言结论替代。- history-only 内容不得创建粗候选。历史只能在 current 粗候选已经存在后绑定目标、旧值或上下文。
- 每个相互独立的 current 信号都必须有自己的粗候选;同一行或同一目标中的主业务信号和补充 Trace 信号也分别建 candidate。Skill 再按最终目标和业务规则合并、拆分或建立 linked relationship。
- 一个粗候选不等于一个最终事件。Skill 可以拆成多个目标事件、合并同目标信号,或生成契约明确要求的 linked/derived events。
- 最终事件在
context_used.main_candidate_ids中记录所使用的candidate_id;一个事件可关联多个 candidate,一个 candidate 也可关联多个最终事件。最终输出只允许保留这些 ID 作为 provenance,不得复制candidate_eventsitem、possible_event_types、uncertainty_codes或任何internal_route。
调用门槛
完成全部 current 内容盘点后:
- 输入可理解,且没有任何 active 业务信号:Main Agent 输出 S10,不调用 Skill。
- 输入不足,无法判断是否存在任何 active 业务信号:Main Agent 输出 S99,不调用 Skill。
candidate_events至少有一个满足本契约的粗候选:Main Agent 调用 Skill,并同时传递unknowns。
仅有 unsupported/legacy 内容、unknowns 或 review outcome 不能满足调用门槛。正文只有泛化 see attached 且附件无法取得、方向不可识别时走 S99;动作方向已明确为 active 事件但必要附件不可读时,仍形成粗候选,由 Skill 生成业务复核结果。
Skill 最终裁决
- Skill 必须重新验证 current evidence,不得把
possible_event_types当作最终结论。 - event type 和 subtype 已知但字段、目标、映射或证据不安全时,保留该 active
event_type,并附非空manual_review;manual_review.missing_fields[]使用 RFC 6901 JSON Pointer。 - 只有 active 业务方向已确认,但最终 event type 或 subtype 仍无法确定时,才使用
business_review_outcomes中的Need Manual Review。 - 业务类型已知的 manual-review event 和 type-unknown
Need Manual Review都是业务输出,不得改成 S99。
如果 Skill 验证后确认所有粗候选都没有 active 事件,返回以下内部结果:
{
"internal_route": "no_supported_event",
"reason_code": "skill_validation_found_no_active_event",
"candidate_ids": ["C1"]
}
Main Agent 必须把该内部结果转换成正常 S10;不得把 internal_route 直接对外返回,也不得把它转换成 S99 或业务人工复核。
no_supported_event 本身不得调用或进入 mandatory submit。转换完成后的 S10 才是公开 final_result,由 Main Agent 提交一次并原样返回。
no_supported_event.candidate_ids 必须非空,列出本次已完成验证且均被否定的全部粗候选 ID。
如果素材包或 candidate item 违反本契约,Skill 返回内部 contract error:
{
"internal_route": "candidate_package_contract_error",
"reason_code": "invalid_candidate_package",
"candidate_ids": ["C1"],
"contract_errors": [
{
"path": "/candidate_events/0/possible_event_types/0",
"code": "not_active_emittable_event_type"
}
]
}
contract_errors[].path 使用 RFC 6901 JSON Pointer。该内部错误报告给编排层并停止本次业务处理;不得直接对外,不得映射为 S10、S99 或 Need Manual Review。
candidate_package_contract_error 本身不得调用或进入 mandatory submit。若编排层基于它形成正式公开错误对象,只提交该公开对象,不提交内部 disposition。
candidate_package_contract_error.contract_errors 必须非空。candidate_ids 保留仍可安全读取的候选 ID;如果连 ID 都不合法,使用空数组。
行级与目标级边界
QBD/LianTai 当前有效行必须独立处理,不能把不同 current rows 合并成一个主事件。这里的“一行”是隔离边界,不是绝对事件数量:
- 普通情况下,一个 current row × 一个目标产生一个主事件。
- 同一行含多个目标时由 Skill 按目标拆分。
- Parent-to-child split 的 linked parent
Cancel Allotment、linked Trace、TA Recorder 和其他契约明确的 derived event 可以在同一行主事件之外额外产生。 parent_child_split_evidence必须保留 parent code 的来源、完整释放/不保留余量证据、child code 有序列表、显式 cancel(如有)及其目标、parent original room summary 和关系来源;Main Agent 不自行去重或决定最终事件。- Main Agent 只保留行、highlight、目标提示和不确定点;最终拆分由 Skill 完成。