# 02 Agent Workflow

本文说明 Main Agent 处理一封 SourceMessage 时的标准执行流程。

本文件不是 Prompt，不定义具体业务 Skill 的字段规则，也不定义具体任务类型的业务判断规则。

## 1. 核心原则

- Main Agent 必须先区分 current / history，再判断任务。
- Main Agent 只能从 body_current 识别当前有效业务事件。
- body_thread 只能作为 evidence context。
- 不能从 body_thread 生成 normal_task。
- 当 body_current 已经提供当前可执行业务动作时，body_thread 可以作为 evidence context 补充唯一目标 key、父 group、上游任务或最近相关确认段；这不等于从 body_thread 触发任务，输出中应保留 target key 来源。
- Main Agent 第一版只围绕 group_code / confirmation_number 做路由级查询。
- Main Agent 根据 Skill Catalog 选择 Skill。
- Skill 负责业务判断和完整 ai_task_result 输出。
- Main Agent 只做 schema validation 和结果汇总，不修补 Skill 输出。

## 2. 关键执行顺序

1. 读取 SourceMessage。
2. 区分 body_current 和 body_thread。
3. 判断 body_current 是否包含当前有效业务动作。
4. 将 body_current 中的当前有效业务动作拆分为一个或多个原始邮件事件。
5. 为每个原始邮件事件分配 source_event_index，从 1 开始。
6. 为每个原始邮件事件提取路由级核心 key：group_code 和 confirmation_number。
7. 如果能提取到 group_code 或 confirmation_number，调用路由级只读 Tool 查询上下文。
8. 如果两个 key 都提取不到，routing_context 为空，继续按邮件语义尝试选择 Skill。
9. 根据 Skill Catalog 的 when_to_use / must_not_use_when 选择具体 Skill。
10. 按具体 Skill 文档定义的 input_schema / input_requirements 组装 Skill 输入。
11. 调用 Skill。
12. 校验 Skill 输出是否符合 Unified Output Contract。
13. 如果 Skill 输出合格，将该结果加入 ai_task_results。
14. 如果一封邮件有多个原始事件，重复步骤 6 到 13。
15. 汇总所有合格结果，输出统一 JSON。

## 3. 路由级查询流程

Main Agent 第一版只查询：

- group_code
- confirmation_number

查询规则：

- Group / Allotment 使用 group_code。
- Fit 使用 confirmation_number。
- 如果邮件里两个 key 都出现，两个都传给只读 Tool。
- 如果 case_type 暂时无法判断，但能提取到任一 key，也必须先查。
- Allotment 第一版不单独设计 allotment_key。

查询结果应作为 routing_context 传给 Skill。

routing_context 至少应覆盖：

- 已写入操作结果的信息数据库。
- 待处理的任务数据库。
- 终止记录。

查询结果只作为上下文，不直接等于最终业务结论。

## 4. 分支规则

| 场景 | Main Agent 处理方式 |
|---|---|
| body_current 明确没有新的业务动作但需要用户可见 | 路由到 `message_notification_skill` 输出 informational_message；不能从 body_thread 生成 normal_task |
| 无法判断是消息通知还是业务动作 | 路由到 `exception_detection_skill` 输出 structured manual_review |
| 业务动作只出现在 body_thread | 不生成 normal_task；body_thread 只能作为 evidence context |
| body_current 有备注 / Guest Request 动作，目标 key 只在 body_thread 的最近相关线程中清晰出现 | 可以把 body_thread 作为 evidence context 传给对应 Skill 绑定目标；不得把 history 中的旧动作当成 current 动作 |
| body_current 有多个独立业务事件 | 拆分为多个 source_event_index，分别选择 Skill |
| body_current 有多个订单 | 拆分为多个 source_event_index，分别处理 |
| QBD / LianTai / 旅行社 current 文本为 `AMEND + FINAL BOOKING`，但实质是父团拆成多个子 group_code 的配合房 / Allotment 创建 | 按子 group_code 拆分为 S01 New Booking / Allotment 事件；父团号作为 parent_group_code evidence；不得仅因 `AMEND` 字样强制走 S02 |
| QBD / LianTai Excel 或 table workflow 有多个当前有效黄色 / 高亮行 | 按行拆分为多个 source_event_index；一行一个 ai_task_result；不得跨行合并 |
| 同一 current event / 同一 QBD / LianTai 行同时包含 S01 / S02 / S06 主业务动作和 Trace / Guest Request / extra bed | 生成主业务 ai_task_result 和 S07 linked ai_task_result；主任务先执行，S07 后执行；用 parent_source_event_index / linked_task_group_id / execution_order 表达同源关系 |
| QBD / LianTai 多行结果被合并到单个 ai_task_result | 视为 Skill 输出不符合 schema；用同一 input 重试该 Skill 一次 |
| 找不到 group_code / confirmation_number | routing_context 为空；仍可按邮件语义选择 Skill；不确定则 manual_review |
| 查不到已写入订单记录，但查到待处理任务或工作流 | 不得直接输出 CASE_NOT_FOUND；将上下文交给 Skill 判断 |
| 查不到已写入订单记录，也查不到待处理任务或工作流 | 将查询结果交给 Skill；是否输出 CASE_NOT_FOUND 由 Skill 判断 |
| 命中终止记录 | 将终止上下文交给对应 Skill；明确轻量消息走 S10 informational_message，边界不清走 S99 manual_review |
| 多个 Skill 都可能适用 | 优先使用 Skill Catalog 的 must_not_use_when 排除；仍冲突则调用 exception_detection_skill 或 manual_review |
| 多个 Skill 对同一事件输出冲突 | 调用 exception_detection_skill 或输出 manual_review |
| Skill 输出不符合 schema | 使用同一 input 重试该 Skill 一次 |
| Skill 重试后仍不合格 | 调用 exception_detection_skill |
| exception_detection_skill 仍无法处理 | 输出 manual_review 或 extraction_warnings |

## 5. Skill 输入流程

Main Agent 不固定所有 Skill 输入字段。

处理方式：

1. 先根据 Skill Catalog 选择 Skill。
2. 读取该 Skill 的 input_schema / input_requirements。
3. 只传该 Skill 完成判断所需的信息。
4. source_message_id 和 source_event_index 必须传入。
5. current 事件信息只能来自 body_current。
6. body_thread、历史附件、系统查询结果只能作为 evidence context；如果 current 动作明确，它们可以帮助绑定目标对象或父任务，但不能单独触发任务。
7. 路由级查询结果可以传入 Skill，但是否使用由 Skill 自己决定。

## 6. Skill 输出处理流程

Skill 必须输出完整 ai_task_result 单项。

Main Agent 只做：

- schema validation；
- 收集合格结果；
- 汇总到 ai_task_results 外层。

Main Agent 不做：

- 不补 source_message_id；
- 不补 result_id；
- 不补业务字段；
- 不统一枚举值；
- 不改写 result_type / task_type / exception_type；
- 不把一个 Skill 的业务结论改成另一个业务结论。

## 7. 最终输出

Main Agent 最终只输出统一 JSON：

```json
{
  "source_message_id": "",
  "ai_task_results": [],
  "extraction_warnings": []
}
```

不得输出：

- 解释文字；
- 推理过程；
- chain-of-thought；
- Skill 调用日志；
- 真实 TaskCard；
- Opera 写入结果；
- Receipt。
