Files
SuperBizAgent-java/mvp/issues/active/ISS-011-chat-diagnosis-stategraph-orchestration.md
T

1039 lines
48 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ISS-011 Chat 诊断 StateGraph 编排改造
**状态**:待实现
**严重程度**:高
**发现时间**:2026-07-16
**来源**:OnCall / Agent 编排模拟面试、当前 Chat 复杂诊断调用链复核
**预计实施周期**:2–3 个工作日
---
## 1. 背景
当前复杂 Chat 诊断在 `ChatService.executeChatComplex(...)` 中采用两层编排:
```text
SequentialAgent
-> Planner
-> Executor
-> Verifier
ChatService 外层循环
-> 解析 Verifier PASS / LOW_CONFID / REJECT
-> 决定 Composer、补证据或安全降级
```
这种实现已经具备 Planner、Executor、Gatekeeper、Verifier、Composer 的职责拆分,但流程控制分散在:
- `SequentialAgent` 固定顺序。
- `VerifierInputHook` 内的 Gatekeeper。
- `ChatService` 外层最多两轮循环。
- Composer 和固定降级逻辑。
随着 no-evidence、工具能力阻断、Executor 非法输出、Gatekeeper REJECT、Verifier LOW_CONFID 等状态增加,当前高层 Flow 抽象已经无法清晰表达阶段短路和定向重试。
---
## 2. 当前问题
### 2.1 Executor 语义失败后仍可能继续 Pipeline
如果 Executor 抛出异常,当前外层 `catch` 可以终止 Run;但如果 Executor 正常返回一段错误文本、非法结构或工具阻断结果,`SequentialAgent` 仍会继续调用 Verifier。
这会造成:
- Verifier 消费无效输入。
- 增加无意义模型调用和 Token。
- Trace 中难以区分执行失败与证据不足。
- 最终降级发生得过晚。
### 2.2 不能按失败阶段精确重试
当前 LOW_CONFID 重试会重新运行:
```text
Planner -> Executor -> Verifier
```
但真实需求可能是:
| 失败位置 | 期望恢复位置 |
|---|---|
| Planner 输出非法 | 重试 Planner |
| Executor 输出结构非法 | 不重试 Executor,直接进入固定安全降级 |
| Gatekeeper 引用验真失败 | 直接进入固定安全降级 |
| Verifier LOW_CONFID | 从 `facts_checked` 提取 `evidence_gaps`,返回 Planner 进行一次有限补证据 |
| 工具权限或能力阻断 | 不重试,直接降级 |
当前 `SequentialAgent + 外层 round` 无法自然表达这些回边。
### 2.3 Gatekeeper 藏在 Verifier Hook 中
当前链路是:
```text
Executor
-> VerifierInputHook
-> ExecutorGatekeeperService
-> Verifier
```
Hook 适合加工和拦截 Verifier 输入,但不适合根据 Gatekeeper 结果跳回 Executor。Gatekeeper 作为诊断质量门禁,应该成为显式编排节点。
### 2.4 编排逻辑已经形成隐式状态机
`ChatService` 当前同时负责:
- 构建 Agent。
- 执行 SequentialAgent。
- 控制 LOW_CONFID 轮次。
- 构造 retry context。
- 调用 Composer。
- 固定模板降级。
- 持久化 Run、self_evaluation 和汇总指标。
继续增加 `if/else` 会进一步扩大 `ChatService` 职责,降低流程可读性和可测试性。
---
## 3. 改造目标
使用 Spring AI Alibaba `StateGraph` 接管跨 Agent 的状态转换,现有 ReactAgent、Prompt、工具、证据协议和持久化能力继续复用。
目标职责:
```text
StateGraph
-> 控制顺序、条件边、重试、终止和降级
ReactAgent
-> 完成 Planner、Executor、Verifier、Composer 节点内部语义任务
Java Node
-> 完成 Gatekeeper、重试判断、固定降级等确定性任务
```
本次不使用 SupervisorAgent 替代固定诊断 Pipeline。SupervisorAgent 留给未来多个专科 SubAgent 之间的动态路由。
---
## 4. 目标流程
```mermaid
flowchart TD
Start["START"] --> Planner["Planner"]
Planner -- "COMPLETED" --> Executor["Executor"]
Planner -- "INVALID_OUTPUT / RETRYABLE_FAILED 且本阶段未重试" --> Planner
Planner -- "NON_RETRYABLE_FAILED 或再次失败" --> Fallback["Fallback"]
Executor -- "COMPLETED" --> Gatekeeper["Gatekeeper"]
Executor -- "INVALID_OUTPUT / TOOL_BLOCKED / FAILED" --> Fallback
Gatekeeper -- "PASS" --> VerifiedInput["Build Verified Verifier Input"]
Gatekeeper -- "LOW_CONFID 且存在已验真 binding" --> VerifiedInput["Build Verified Verifier Input"]
Gatekeeper -- "LOW_CONFID 且零条已验真 binding" --> Fallback
Gatekeeper -- "REJECT" --> Fallback
VerifiedInput --> Verifier
Verifier -- "PASS" --> Composer["Composer"]
Verifier -- "REJECT" --> Composer
Verifier -- "LOW_CONFID 且存在有效 evidence_gaps" --> EvidenceRetry["Prepare Evidence Retry"]
Verifier -- "LOW_CONFID 且无有效 evidence_gaps 或已补查" --> Composer
Verifier -- "INVALID_OUTPUT / RETRYABLE_FAILED 且未重试" --> Verifier
Verifier -- "NON_RETRYABLE_FAILED 或再次失败" --> Fallback
EvidenceRetry --> Planner
Composer -- "COMPLETED" --> End["END"]
Composer -- "INVALID_OUTPUT / RETRYABLE_FAILED 且未重试" --> Composer
Composer -- "NON_RETRYABLE_FAILED 或再次失败" --> Fallback
Fallback --> End
```
### 4.1 本期只保留 Verifier LOW_CONFID 诊断补证据
Gatekeeper REJECT 本期不重试,直接进入 Fallback。
Verifier LOW_CONFID 保留当前有限补证据能力:
```text
目标:补充缺失证据
返回:Planner
默认上限:1 次
```
只有同时满足以下条件时才允许补证据:
- Verifier 返回 LOW_CONFID,且编排层能够从现有 `facts_checked` 中提取至少一个关键证据缺口。
- LOW_CONFID 不是由 Gatekeeper verdict ceiling 导致。
- 本 Run 尚未执行过补证据轮次。
Verifier 不新增 `missing_evidence`、`suggested_tool` 等输出字段,也不负责规划补查方式。Prepare Evidence Retry Node 由代码实现,从 `facts_checked` 中提取 `no_evidence` 或只有 `indirect_support` 的关键事实,并整理为受限 retry context:
```json
{
"mode": "EVIDENCE_GAP_ONLY",
"prior_verified_output": {},
"prior_verified_evidence": [],
"evidence_gaps": [
{
"claim_id": "claim-2",
"fact": "库存服务响应时间升高",
"verification": "no_evidence",
"reason": "缺少数据库和下游依赖证据"
}
],
"completed_queries": [],
"constraints": {
"max_retry": 1,
"do_not_repeat_successful_queries": true,
"only_execute_incremental_queries": true,
"preserve_prior_verified_claims": true
}
}
```
如果 LOW_CONFID 无法提取出有效 `evidence_gaps`,则不触发补查。工具选择、查询范围和工具可用性判断继续由第二轮 Planner / Executor 负责,Verifier 只判断证据是否支持结论。
Planner 第二轮使用 `EVIDENCE_GAP_ONLY` 模式,只读取 `evidence_gaps`、`completed_queries` 和必要的已确认事实摘要,生成增量补证据计划,不允许重新开始完整诊断、扩大服务范围或重复已经成功执行的查询。基础 Planner Prompt 和 Verifier 输出协议保持不变,Planner Adapter 允许注入这段编排模式约束。
第二轮 Executor 使用“增量执行、完整输出”策略:
- `prior_verified_output` 和 `prior_verified_evidence` 作为只读可信输入传给 Executor。
- Executor 只执行 Planner 新增的查询,不重复 `completed_queries`。
- Executor 最终输出完整 `executor_evidence_v2` 快照,包含应保留的第一轮可信 claims 和本轮新增 claims,而不是只输出本轮增量。
- Gatekeeper 对第二轮完整快照中的全部 binding 重新验真,Verifier 只消费新一轮生成的完整 `verified_executor_output` 和 `verified_evidence`。
- Java 编排层不对两轮 claim 文本做语义合并,避免通过代码错误处理重复、冲突和包含关系。
### 4.2 Planner 只允许一次无副作用技术重试
Planner 不调用工具,因此模型超时或输出格式非法时,允许使用相同业务输入进行一次技术重试。技术重试不代表重新诊断,也不允许改变问题范围。
Planner 状态定义:
| 状态 | 含义 | 路由 |
|---|---|---|
| `COMPLETED` | 输出符合 Planner JSON 契约 | Executor |
| `INVALID_OUTPUT` | 输出为空、JSON 非法或缺少必要计划结构 | 本 Planner 阶段首次出现时重试一次,否则 Fallback |
| `RETRYABLE_FAILED` | 模型超时或明确的临时调用失败 | 本 Planner 阶段首次出现时重试一次,否则 Fallback |
| `NON_RETRYABLE_FAILED` | 配置、认证或其他明确不可重试失败 | 直接 Fallback |
约束:
- 每次进入 Planner 阶段最多进行一次技术重试。
- 从 Prepare Evidence Retry Node 重新进入 Planner 时,开始新的 Planner 阶段,并重置当前阶段的 `planner_retry_count`。
- Planner 技术重试使用原始输入和固定格式提醒,不注入新的诊断事实。
- `planner_retry_count` 与 `evidence_retry_count` 分开维护和审计。
- Planner 不因计划“看起来不够好”进行语义重试;只有明确执行失败或输出契约失败才能重试。
### 4.3 Verifier 与 Composer 各允许一次无副作用技术重试
Verifier 和 Composer 都不调用工具,且重试输入可以固定,因此允许对模型临时失败或输出格式非法进行一次技术重试:
```text
Verifier INVALID_OUTPUT / RETRYABLE_FAILED
-> 使用相同 verified_executor_output + verified_evidence 重试一次
-> 不重新执行 Gatekeeper、Executor 或工具
Composer INVALID_OUTPUT / RETRYABLE_FAILED
-> 使用相同 effective_verdict + allowed claims 重试一次
-> 不重新执行 Verifier 或前序节点
```
第二次技术失败或 `NON_RETRYABLE_FAILED` 的处理:
- Verifier 进入前置验证无法完成的固定 Fallback,不输出未经 Verifier 允许的 Executor claim。
- Composer 使用已经过 Verifier 允许的材料进入确定性安全模板。
`verifier_retry_count`、`composer_retry_count` 和 `evidence_retry_count` 分开维护,技术重试不得增加补证据轮次。
---
## 5. Gatekeeper REJECT 策略
**决策状态**:已确认,2026-07-16。
本期不增加 EvidenceRepairNode,也不让 Gatekeeper REJECT 返回 Executor 重试。任何 Gatekeeper REJECT 都直接进入固定安全降级。
原因:
- 第一版先验证显式 Graph 编排和阶段短路,不同时引入新的模型节点。
- 证据引用错误不一定可以安全修复,自动重新绑定可能制造第二次幻觉。
- 当前最重要的是保证不可信 Executor 输出不能进入 Verifier,而不是提高 REJECT 的自动恢复率。
- 直接 Fallback 的状态语义简单,便于先建立稳定的路由和测试基线。
处理流程:
```text
Executor
-> Gatekeeper
-> PASS:构造已验真 Verifier 输入后进入 Verifier
-> LOW_CONFID 且存在通过 binding:过滤失败 binding,构造已验真 Verifier 输入后进入 Verifier
-> REJECT:直接 Fallback
```
Executor 输出尚未经过 Verifier 时,如果因为 `INVALID_OUTPUT`、Gatekeeper REJECT 或零条可信 binding 进入 Fallback,固定表达不得输出任何 Executor claim。即使 Gatekeeper 结果中同时存在少量通过的 binding,也不能假设整段 claim 文本都被这些 binding 支撑。
此前置验证失败 Fallback 只保留:
- 当前诊断未通过结构或证据引用校验。
- 工具调用成功、失败和阻断情况的代码汇总,不包含工具原文。
- 当前无法给出可信根因。
- 建议人工查看 Trace 或补充证据。
示例:
```text
本次诊断已完成部分证据采集,但诊断结果未通过证据引用校验,
当前无法给出可信根因。建议结合 Trace 中的工具调用记录进行人工复核。
```
Composer 在已经取得 Verifier 允许材料后执行失败,仍可使用现有基于 VerifierDecision 的安全模板降级;它不属于上述“未经过 Verifier 的前置验证失败”。
---
### 5.1 Executor INVALID_OUTPUT 策略
**决策状态**:已确认,2026-07-16。
`INVALID_OUTPUT` 定义为 Executor Agent 调用已经返回,但无法解析为最小 `executor_evidence_v2` 结构。它对应当前解析状态中的 `missing` 或 `malformed`,包括:
- 输出为空。
- 输出不是 JSON。
- JSON 被截断或语法非法。
- JSON 根节点不是对象。
- `claims` 不是数组。
以下情况不属于 `INVALID_OUTPUT`:
- 合法的空 claims 和 missing info。
- 合法 no-evidence。
- 结构可解析但 evidence binding 错误,此类进入 Gatekeeper。
- 引用真实但证据无法支持 claim,此类进入 Verifier。
本期处理方式:
```text
Executor INVALID_OUTPUT
-> 不重试 Executor
-> 不调用 Gatekeeper
-> 不调用 Verifier
-> 不调用模型 Composer
-> 固定安全 Fallback
```
原因:
- 当前没有可信结构化结果可供后续门禁消费。
- 重试有工具权限的 Executor 可能重复调用工具并产生第二套证据。
- 本期优先建立清晰、可验证的控制流,不同时引入格式修复模式。
Trace 至少记录:
- `executor_status = INVALID_OUTPUT`。
- missing / malformed 及解析错误摘要。
- 当前 Run 已发生的工具调用数量和成功情况。
- 跳转 Fallback 的原因。
- Gatekeeper、Verifier 未执行的原因。
Executor 原始输出只允许保留在受控审计中,不得直接作为用户答案。固定 Fallback 不得从无法解析的 Executor 输出中提取或展示任何 claim。
#### 5.1.1 Executor 状态边界
Executor 状态表达是否完成输出契约,不表达所有工具调用是否成功:
| 状态 | 定义 | 路由 |
|---|---|---|
| `COMPLETED` | 返回合法 `executor_evidence_v2`,包括合法 no-evidence 或工具限制说明 | Gatekeeper |
| `INVALID_OUTPUT` | Agent 已返回,但输出为空或无法解析为最小结构 | 固定 Fallback |
| `TOOL_BLOCKED` | 工具层明确返回无权限、工具不存在或能力禁止,并且 Executor 未形成合法结构化输出 | 固定 Fallback |
| `FAILED` | 模型调用、Agent 框架或其他非工具阻断异常,并且未形成合法结构化输出 | 固定 Fallback |
边界规则:
- 工具查询返回空数据属于合法 no-evidence,不是 `TOOL_BLOCKED`。
- 单次或多次工具超时、报错后,只要 Executor 最终输出合法结构,状态仍为 `COMPLETED`,工具失败作为证据限制进入 Gatekeeper / Verifier。
- 多个工具失败但 Executor 能合法表达 no-evidence 和诊断限制时,状态仍为 `COMPLETED`。
- 只有工具层明确阻止执行且没有合法 Executor 输出时,才标记 `TOOL_BLOCKED`。
- `INVALID_OUTPUT`、`TOOL_BLOCKED` 和 `FAILED` 本期均不重试 Executor。
---
### 5.2 Gatekeeper LOW_CONFID 策略
**决策状态**:已确认,2026-07-16。
Gatekeeper LOW_CONFID 表示 Executor 输出存在非致命结构或引用缺口,但不代表所有 evidence binding 都不可信。本期按已验真 binding 数量处理:
```text
Gatekeeper LOW_CONFID
-> 至少一条 checked binding 为 pass
-> 代码过滤失败 binding
-> 构造 verified executor output
-> Verifier
-> 最终 verdict 最高为 LOW_CONFID
-> 零条 checked binding 为 pass
-> 固定 Fallback
```
Verifier Input Builder 必须:
- 只保留 Gatekeeper `checked_bindings.status=pass` 对应的 evidence binding。
- 删除失败 binding。
- 没有有效 binding 的 claim 不得作为确认性 claim 进入 Verifier。
- 不向 Verifier 传递 Executor 未经验真的自由文本作为事实来源。
- 从通过的 `checked_bindings` 中提取 `claim_id`、`source_invocation_id`、`tool_name`、`raw_path` 和 `matched_text`,构造 `verified_evidence`。
- 不向 Verifier 传递当前 run 的完整 `tool_trace_summary`;Verifier 只能读取 `verified_evidence`。
- Gatekeeper PASS 时将 `verifier_verdict_ceiling` 设置为 `PASS`;Gatekeeper LOW_CONFID 时设置为 `LOW_CONFID`。
即使模型 Verifier 返回 PASS,编排层也必须将 `effective_verdict` 限制为 LOW_CONFID。
LOW_CONFID 进入 Verifier 的目标是保留部分真实证据,而不是让 Verifier 修复 Gatekeeper 失败。
Gatekeeper PASS 也必须经过 Verifier Input Builder。PASS 只表示所有 binding 的引用真实性检查通过,不代表 Verifier 可以跳过证据投影或查看未被 Executor 引用的其他工具结果。
### 5.3 Gatekeeper 与 Verifier 状态标准化
Gatekeeper 原始审计结果和 Graph 路由状态分开保存:
```text
gatekeeper_result.status=pass
-> gatekeeper_status=PASS
gatekeeper_result.status=fail + severity=low_confid
-> gatekeeper_status=LOW_CONFID
gatekeeper_result.status=fail + severity=reject
-> gatekeeper_status=REJECT
```
Gatekeeper 原始结果缺失、无法识别或发生内部错误时,按安全默认映射为 `REJECT`。
Verifier 同样分离执行状态和诊断结论:
- `verifier_status` 使用 COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED,表示节点是否正常完成输出契约以及失败是否可进行一次技术重试。
- `verifier_model_verdict` 保存模型原始 PASS / LOW_CONFID / REJECT。
- `effective_verdict` 应用 `verifier_verdict_ceiling` 后生成,并作为 Graph 路由和 Composer 的唯一 verdict 输入。
- 任何执行失败状态都只能出现在 `verifier_status`,不得作为诊断 verdict。
例如模型返回 PASS,但 Gatekeeper LOW_CONFID 将 ceiling 设置为 LOW_CONFID 时:
```text
verifier_model_verdict=PASS
verifier_verdict_ceiling=LOW_CONFID
effective_verdict=LOW_CONFID
```
持久化时,现有 `self_evaluation.verifier_evaluation.verdict` 继续保存 `effective_verdict`;模型原始 verdict 可作为 `model_verdict` 审计字段保存,不参与下游路由。
---
## 6. Graph State 最小契约
Graph State 保存跨节点需要的结构化状态,不复制完整工具原文和模型思考过程。
| 状态 | 作用 | 策略 |
|---|---|---|
| `diagnosis_context` | 当前 Query、history、sessionId/runId 等统一上下文 | Replace |
| `planner_plan` | Planner 结构化计划 | Replace |
| `planner_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `planner_retry_count` | 当前 Planner 阶段的技术重试次数;进入补证据 Planner 阶段时重置 | Replace |
| `planner_mode` | NORMAL / EVIDENCE_GAP_ONLY | Replace |
| `executor_output` | `executor_evidence_v2` | Replace |
| `executor_status` | COMPLETED / INVALID_OUTPUT / TOOL_BLOCKED / FAILED | Replace |
| `gatekeeper_result` | 当前轮验真结果 | Replace |
| `gatekeeper_status` | PASS / LOW_CONFID / REJECT | Replace |
| `verified_executor_output` | 只保留 Gatekeeper 通过 binding 的 Verifier 输入 | Replace |
| `verified_evidence` | 从通过 binding 的 `matched_text` 构造的最小证据集合 | Replace |
| `verified_binding_count` | 当前可供 Verifier 使用的 binding 数量 | Replace |
| `verifier_verdict_ceiling` | PASS 或 LOW_CONFID | Replace |
| `verifier_output` | Verifier 结构化结果 | Replace |
| `verifier_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `verifier_retry_count` | Verifier 固定输入技术重试次数 | Replace |
| `verifier_model_verdict` | Verifier 模型原始 PASS / LOW_CONFID / REJECT | Replace |
| `effective_verdict` | 应用 Gatekeeper ceiling 后的 PASS / LOW_CONFID / REJECT | Replace |
| `composer_output` | Composer 结构化输出 | Replace |
| `composer_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `composer_retry_count` | Composer 固定输入技术重试次数 | Replace |
| `evidence_retry_count` | 补证据轮次 | Replace |
| `retry_context` | 从 `facts_checked` 提取的 `evidence_gaps` 和补查约束 | Replace |
| `orchestration_events` | 节点执行结果、稳定 reason code 和 attempt 的有界运行时事件 | Append |
| `final_answer` | 最终用户表达 | Replace |
| `failure_reason` | 当前确定性失败原因 | Replace |
说明:
- `agent_step` 和 `tool_invocation` 继续作为完整 Trace 数据源。
- Graph State 只保存控制流程所需的最新状态。
- `orchestration_events` 是例外的有界追加状态,用于保留 Java Node 和 Agent Node 的实际执行路径;它不包含 Prompt、工具原文或模型输出。
- `no_evidence` 属于合法 Executor 输出,不等于 `FAILED`,仍然进入 Gatekeeper 和 Verifier。
---
## 7. 与当前代码的关系
### 7.1 继续复用
- Planner、Executor、Verifier、Composer Prompt。
- Skill Registry、Planner Skill metadata 和 Executor `read_skill`。
- `ExecutorGatekeeperService` 现有规则。
- `ToolTraceSummaryService`。
- Executor、Verifier、Composer 结构化解析逻辑。
- `diagnosis_run`、`agent_step`、`tool_invocation` 和 `self_evaluation`。
- Token、耗时和工具调用数回填。
- 当前 API 请求和响应协议。
### 7.2 需要调整
- `ChatService.executeChatComplex(...)` 不再创建 `SequentialAgent`。
- Gatekeeper 从 `VerifierInputHook` 的隐式执行迁为显式 Graph Node。
- LOW_CONFID 外层 `for round` 迁入 Graph 条件边。
- Composer 与固定 Fallback 成为独立节点。
- ChatService 只负责 Run 生命周期和调用 Graph,不继续承载细粒度状态机。
### 7.3 ReactAgent 接入策略
第一阶段使用适配 Node 显式调用当前 ReactAgent,不直接全面使用 `ReactAgent.asNode(...)`。
原因:
- 当前 Agent 根据 history 和 retry context 动态构造 Prompt。
- 当前使用自定义 outputKey 和解析逻辑。
- Hook、ThreadLocal 和父子 Graph `messages` 需要先验证。
Graph State 和 Agent 输入契约稳定后,再评估直接使用 `asNode(false, false)`。
### 7.4 已确认:父子状态使用输入白名单隔离
**决策状态**:已确认,2026-07-16。
外层 Graph 维护完整工作流状态,但每个 ReactAgent 不直接接收 `parentState.data()`。每个 Adapter Node 必须完成一次显式状态投影:
```text
父 Graph Shared State
-> Adapter Node 选择允许字段
-> Agent 专用 Input DTO
-> ReactAgent 私有执行上下文
-> Parser 提取标准输出
-> 只更新父 Graph 指定状态
```
各节点输入边界:
| 节点 | 允许读取 | 不允许直接读取 |
|---|---|---|
| Planner | query、history、retry context、Skill metadata | Executor、Gatekeeper、Verifier 的历史输出 |
| Executor | query、planner plan、selected skill、executor retry context;补证据阶段可读取 prior verified output / evidence | Verifier 自由推理文本、失败 binding、其他轮次未筛选 messages |
| Gatekeeper | executor structured output、当前 run 的 tool invocation | Planner 思考、其他 run 工具记录 |
| Verifier | query、verified executor output、gatekeeper result、verified evidence | Planner 计划、Executor 思考、完整 tool trace、未经 Gatekeeper 验真的自由文本 |
| Composer | allowed claims、missing info、recommended actions | 原始工具结果、Executor 原始答案和未允许 claims |
实现约束:
- 第一阶段不使用 `asNode(true, true)`。
- `asNode(false, false)` 也不作为严格隔离手段,因为它主要减少 `messages` 传播,不能替代字段白名单。
- 每个 Adapter Node 使用专用 Input DTO,不复用一个包含所有字段的通用 AgentInput。
- ReactAgent 只向父 Graph 返回结构化 Node Output,不回传内部完整 `messages` 和推理过程。
- 子 Agent 的执行标识按 `runId + agentName + attempt` 隔离,避免不同 Agent 和重试轮次复用内部状态。
- 数据隔离由代码保证,Prompt 约束只作为补充。
### 7.5 已确认:编排审计使用独立 `orchestration_trace`
**决策状态**:已确认,2026-07-16。
Graph 路由记录不写入 `self_evaluation`。本期在 `diagnosis_run` 新增 nullable JSON 字段 `orchestration_trace`,用于保存当前 run 的紧凑编排摘要。数据库列允许 nullable 仅用于安全执行增量迁移,所有新 StateGraph Chat run 在应用契约上必须写入非空值。
职责边界:
```text
self_evaluation
-> 结果质量、证据可信度以及 Gatekeeper / Verifier 等评估结果
orchestration_trace
-> 节点跳转、条件边原因、重试、降级和终止摘要
agent_step
-> 真实模型 Agent 调用
tool_invocation
-> 真实工具调用
```
最小结构:
```json
{
"version": "stategraph-v1",
"transitions": [
{
"from": "gatekeeper",
"to": "fallback",
"reason_code": "gatekeeper_reject",
"attempt": 1
}
],
"final_node": "fallback",
"termination_reason": "gatekeeper_reject",
"degraded": true,
"evidence_retry_count": 0
}
```
约束:
- 只写入 `diagnosis_run`,不写入会话级 `diagnosis_session`,因为 Graph 执行边界是 `runId`。
- 使用稳定的 `reason_code`,不保存完整 Prompt、模型思考、工具原文或 Graph State 快照。
- `transitions` 受 Graph 最大循环次数约束,不作为无限增长的事件日志。
- Trace API 只在 `run.orchestrationTrace` 返回解析后的 JSON 对象,不在顶层或兼容 `session` 投影中重复返回,也不增加 raw 字段。
- 本期不为历史 run 回填或设计兼容读取行为;新 StateGraph Chat run 的 `run.orchestrationTrace` 必须非空。
- 第一版不新增 orchestration 明细表,后续只有在需要跨 run 检索单次节点事件时再单独评估。
运行时来源:
```text
每个 Graph Node 完成或捕获可处理失败
-> 向 orchestration_events 追加 node / outcome / reason_code / attempt
-> Graph 正常结束或进入外层异常处理
-> 按事件顺序生成 transitions、final_node 和 termination_reason
-> 持久化 diagnosis_run.orchestration_trace
```
事件最小结构:
```json
{
"node": "gatekeeper",
"outcome": "REJECT",
"reason_code": "gatekeeper_reject",
"attempt": 1
}
```
实现约束:
- 使用 Graph State 的追加策略保存事件,不通过应用日志反推路径。
- 每个节点每次 attempt 最多追加一条终态事件;事件总数同时受一次补查上限和 Graph recursion limit 约束。
- 节点 Adapter 需要捕获可处理异常并追加失败事件;外层异常处理对已产生的事件进行 best-effort 持久化。
- 最终 `transitions` 由相邻事件推导,不在 State 中同时维护第二份重复路径结构。
---
## 8. 分阶段实施计划
## 阶段 0:设计冻结
**预计时间**:1–2 小时
**目标**:完成讨论,不修改运行时实现。
任务:
- 确认 Graph State 最小契约。
- 确认所有条件边和最大重试次数。
- 确认 Fallback 用户表达。
- 确认旧 Sequential 测试的替换范围。
完成标准:
- 本 issue 中所有“待讨论决策”已有明确结论。
- 不存在未定义的循环和终止路径。
## 阶段 1:Graph 骨架和路由测试
**预计时间**:2–3 小时
**目标**:使用 Fake Node 验证 Graph API 和所有路径,不接真实模型。
任务:
- 创建诊断 Graph State 和状态常量。
- 创建 Graph 拓扑。
- 创建 `orchestration_events` 追加策略和最终 trace 构造器。
- 创建 Fake Planner、Executor、Gatekeeper、Verifier、Composer。
- 为所有条件边编写路由测试。
完成标准:
- Planner INVALID_OUTPUT / RETRYABLE_FAILED 在当前 Planner 阶段最多重试一次。
- Planner NON_RETRYABLE_FAILED 或第二次技术失败直接进入 Fallback。
- Verifier 和 Composer 的 INVALID_OUTPUT / RETRYABLE_FAILED 各最多技术重试一次。
- Verifier 和 Composer 的 NON_RETRYABLE_FAILED 或第二次技术失败进入各自安全降级路径。
- Executor FAILED 后不调用 Gatekeeper、Verifier。
- Executor INVALID_OUTPUT 直接进入固定 Fallback,不触发任何模型重试。
- Executor TOOL_BLOCKED 只有在工具层明确阻断且没有合法结构化输出时成立,并直接进入 Fallback。
- 工具空结果或工具失败后仍形成合法结构时,Executor 状态为 COMPLETED 并继续 Gatekeeper。
- 任意 Gatekeeper REJECT 直接进入 Fallback,不调用 Verifier。
- Executor INVALID_OUTPUT、Gatekeeper REJECT 和零条可信 binding 的 Fallback 不输出任何 Executor claim。
- LOW_CONFID 只允许一次 Planner 补证据。
- Graph 不存在无限循环。
- 每条测试路径生成与实际节点顺序一致的 orchestration events 和 transitions。
## 阶段 2:接入真实节点
**预计时间**:3–4 小时
**目标**:将现有 Agent 和代码服务接入 Graph。
任务:
- 创建 Planner、Executor、Verifier、Composer Node Adapter。
- Planner Adapter 解析现有 Planner JSON 契约,并区分 INVALID_OUTPUT、RETRYABLE_FAILED 和 NON_RETRYABLE_FAILED。
- 创建显式 Gatekeeper Node。
- Gatekeeper Node 保留原始 result,并标准化生成 PASS / LOW_CONFID / REJECT 路由状态。
- 创建 Verifier Input Builder Node,过滤未通过的 binding,并仅从通过 binding 的 `matched_text` 构造 `verified_evidence`。
- 创建 Evidence Retry Prepare Node,从现有 `facts_checked` 提取结构化 `evidence_gaps`。
- 创建固定 Fallback Node,并区分前置验证失败与 Composer 已取得 Verifier 安全材料后的降级输入。
- 保持现有基础 Prompt、工具和证据协议不变;允许 Planner Adapter 注入 `EVIDENCE_GAP_ONLY` 编排约束。
完成标准:
- Agent Hook 和 ToolCallback 正常工作。
- Gatekeeper 只执行一次,不再由 Verifier Hook 重复触发。
- no-evidence 继续进入 Gatekeeper 和 Verifier。
- Gatekeeper PASS 和可继续的 LOW_CONFID 都必须经过 Verifier Input Builder。
- Gatekeeper LOW_CONFID 只向 Verifier 提供已验真 binding,并限制 verdict 上限。
- Verifier 不再接收完整 `tool_trace_summary`,只能接收 `verified_executor_output` 和 `verified_evidence`。
- Verifier Adapter 分开输出 `verifier_status`、`verifier_model_verdict` 和应用 ceiling 后的 `effective_verdict`。
- Verifier 和 Composer Adapter 使用固定输入实现各一次技术重试,且不得重新执行任何前序节点。
- Verifier LOW_CONFID 只有能够从 `facts_checked` 提取有效 `evidence_gaps` 时才返回 Planner。
- 第二轮 Planner 只生成 `EVIDENCE_GAP_ONLY` 增量计划。
- 第二轮 Executor 只执行增量查询,但输出包含第一轮可信 claims 和新增 claims 的完整 `executor_evidence_v2` 快照。
- 第二轮 Gatekeeper 对完整快照中的全部 binding 重新验真,不复用第一轮 Gatekeeper verdict。
## 阶段 3:替换 ChatService 编排
**预计时间**:2–3 小时
**目标**:复杂 Chat 诊断正式调用 StateGraph。
任务:
- 将 `executeChatComplex(...)` 改为构造初始 Graph State 并执行 CompiledGraph。
- 使用 `runId` 作为 Graph `threadId`,`sessionId` 作为 metadata。
- 增加数据库迁移,为 `diagnosis_run` 添加 nullable JSON 字段 `orchestration_trace`。
- 将 Graph 的节点跳转、reason code、重试和终止摘要持久化到当前 run。
- 保留 Run 创建、状态更新、耗时、Token、工具数和 Eval 调用。
- 将 Graph 最终状态映射为现有 `ChatResult`。
- 按执行生命周期回填 `diagnosis_run.status`,不使用 status 表达诊断置信度。
完成标准:
- `/api/chat` 请求和响应协议不变。
- `diagnosis_run.agent_flow` 仍为 `CHAT`。
- Trace 明细继续归属于当前 runId。
- Trace API 在 `run.orchestrationTrace` 返回当前 run 的非空编排摘要,不在其他层级重复返回。
- 正常结束和可处理异常路径都能持久化已产生的 orchestration events 摘要。
- Composer、LOW_CONFID、Verifier REJECT 和固定安全 Fallback 只要成功生成安全响应,Run 终态均为 SUCCESS;只有无法生成安全响应的未处理失败才为 FAILED。
- Executor 失败路径不产生 Verifier Agent step。
## 阶段 4:创建新测试体系
**预计时间**:3–4 小时
**目标**:以 Graph 路径和外部行为为中心创建测试,不迁移旧固定顺序断言。
新测试:
- `DiagnosisGraphWorkflowTest`:纯路由测试。
- `DiagnosisGraphNodeContractTest`:节点输入输出契约。
- `ChatServiceGraphIntegrationTest`:ChatService、Run、Trace、自评估集成。
必须覆盖:
- PASS 正常路径。
- Planner 失败。
- Planner INVALID_OUTPUT / RETRYABLE_FAILED 技术重试后成功。
- Planner NON_RETRYABLE_FAILED 和第二次技术失败直接降级。
- Verifier INVALID_OUTPUT / RETRYABLE_FAILED 技术重试后成功。
- Verifier 第二次技术失败或 NON_RETRYABLE_FAILED 进入无 Executor claim 的固定 Fallback。
- Composer INVALID_OUTPUT / RETRYABLE_FAILED 技术重试后成功。
- Composer 第二次技术失败或 NON_RETRYABLE_FAILED 使用 Verifier 安全材料进行确定性模板降级。
- Executor FAILED / TOOL_BLOCKED / INVALID_OUTPUT。
- 工具返回空数据但 Executor 合法输出 no-evidence。
- 工具调用失败但 Executor 仍形成合法结构并继续 Gatekeeper。
- 合法 no-evidence。
- Gatekeeper REJECT 直接降级。
- Gatekeeper REJECT 降级不展示部分通过 binding 对应的 Executor claim。
- Gatekeeper LOW_CONFID 且存在已验真 binding。
- Gatekeeper LOW_CONFID 且不存在已验真 binding。
- Gatekeeper PASS 路径同样只向 Verifier 提供已引用且验真的 evidence。
- Verifier 输入不包含未被通过 binding 引用的工具结果。
- Gatekeeper 原始结果缺失或无法识别时安全映射为 REJECT。
- Verifier 执行失败只写入 `verifier_status`,不得把任何失败状态写成诊断 verdict。
- Verifier LOW_CONFID 补证据。
- 补证据第二轮不重复成功查询,并保留第一轮可信 claims 进入最终完整快照。
- 第二轮完整快照重新经过 Gatekeeper,失败 binding 不因第一轮已通过而跳过校验。
- Gatekeeper ceiling 导致的 LOW_CONFID 不触发补证据。
- LOW_CONFID 无法从 `facts_checked` 提取有效 `evidence_gaps` 时不触发补证据。
- 第二次 LOW_CONFID 不再补证据。
- Verifier REJECT 安全表达。
- Composer 技术重试耗尽后固定降级。
- 同 session 多 run 隔离。
旧测试处理:
- `ChatServiceSequentialAgentTest` 不作为迁移约束,可以由新测试整体替换。
- `VerifierInputHookTest` 根据 Gatekeeper 迁移结果删除或改写。
- `ExecutorGatekeeperServiceTest`、Controller、Trace 和 Eval 契约测试继续保留。
## 阶段 5:回归、清理和文档
**预计时间**:1–2 小时
**目标**:完成行为确认并删除旧编排结构。
任务:
- 运行新的单元和集成测试。
- 运行相关 diagnosis eval baseline。
- 对比关键 Trace 路径。
- 删除 `SequentialAgent` 复杂诊断编排和旧外层 round 状态机。
- 删除不再需要的 Gatekeeper Hook 隐式执行逻辑。
- 更新架构文档和 issue 状态。
完成标准:
- 新测试全部通过。
- 关键 Eval 没有非预期退化。
- ChatService 不再维护隐式诊断状态机。
- 不存在新旧两套长期并行的重复实现。
---
## 9. 测试策略
本改造允许忽略并替换与 SequentialAgent 强绑定的历史测试,但不允许丢失已经建立的安全边界。
测试分层:
```text
Graph 路由测试
-> 不调用模型,验证条件边和循环上限
Node 契约测试
-> 验证 Agent / Java Node 的状态映射
Chat 集成测试
-> 验证外部协议、Run、Trace、orchestration_trace 和 self_evaluation
Eval baseline
-> 验证最终证据表达没有退化
```
不再把“所有 Agent 固定按顺序调用”作为正确性标准。正确性标准改为:
> 根据当前节点状态进入预期路径,并且所有安全门禁和外部协议保持成立。
---
## 10. 行为与协议影响
### 外部协议
保持不变:
- `/api/chat` 请求和响应结构。
- `sessionId/runId` 语义。
- `executor_evidence_v2`。
- Verifier 和 Composer 输出契约。
### Trace API 加法式变化
- Trace 聚合响应的 `run` 对象新增 `orchestrationTrace` 字段。
- 新 StateGraph Chat run 必须返回非空的解析后 JSON 对象;不增加顶层、`session` 投影或 raw 重复字段。
- 本期不为历史 run 回填数据,也不增加历史兼容读取分支。
- 这是有意的内部审计持久化和 Trace 查询协议扩展,不影响 `/api/chat` 消费方。
### 明确的内部行为变化
- Executor 失败后不再调用 Verifier。
- Executor INVALID_OUTPUT 不重试,直接进入固定 Fallback。
- Agent 调用顺序不再固定。
- Gatekeeper REJECT 直接安全降级,不进行自动修复和重试。
- Gatekeeper LOW_CONFID 只在存在已验真 binding 时进入 Verifier,且 verdict 最高为 LOW_CONFID。
- LOW_CONFID 根据从 `facts_checked` 提取的 `evidence_gaps` 返回 Planner,而不是无差别完整重跑。
- 第二轮 Planner 使用增量补证据模式,不重新执行完整 Playbook。
- Agent step 数量、Token 和耗时可能减少。
- Trace 需要能解释条件边选择和终止原因。
### Run 状态与诊断质量分离
`diagnosis_run.status` 只表达执行生命周期,不表达结论可信度:
| 场景 | Run status | 质量表达 |
|---|---|---|
| Graph 正常到达 Composer | SUCCESS | Verifier verdict |
| LOW_CONFID 或 Verifier REJECT 后生成安全答案 | SUCCESS | Verifier verdict |
| 按设计进入固定 Fallback 并成功生成安全答案 | SUCCESS | `orchestrationTrace.degraded=true` 和 termination reason |
| Graph 未处理异常、持久化失败或无法生成任何安全响应 | FAILED | failure reason 和已有 orchestration events |
本期不新增 `DEGRADED` Run status,避免将执行状态和诊断质量混在同一个字段中。
这些是有意的编排行为变化,不是对外协议变化。
---
## 11. 验收标准
### 编排
- [ ] 每次进入 Planner 阶段时,INVALID_OUTPUT / RETRYABLE_FAILED 最多触发一次技术重试。
- [ ] Planner NON_RETRYABLE_FAILED 或当前阶段第二次技术失败直接进入 Fallback。
- [ ] Planner 技术重试不增加 `evidence_retry_count`,补证据重新进入 Planner 时重置当前阶段的 `planner_retry_count`。
- [ ] Executor FAILED / TOOL_BLOCKED 后不会执行 Gatekeeper 和 Verifier。
- [ ] Executor INVALID_OUTPUT 不重试,不执行 Gatekeeper、Verifier 和模型 Composer。
- [ ] TOOL_BLOCKED 只用于工具层明确阻断且不存在合法 Executor 输出的场景。
- [ ] 工具空结果或工具失败后仍形成合法 Executor 输出时状态为 COMPLETED,并继续 Gatekeeper。
- [ ] Executor 合法 no-evidence 会继续执行 Gatekeeper 和 Verifier。
- [ ] Gatekeeper REJECT 直接进入 Fallback,不执行 Verifier。
- [ ] Gatekeeper LOW_CONFID 且零条已验真 binding 时直接进入 Fallback。
- [ ] Gatekeeper LOW_CONFID 且存在已验真 binding 时,Verifier 只接收通过校验的 binding。
- [ ] Gatekeeper PASS 和可继续的 LOW_CONFID 都经过 Verifier Input Builder。
- [ ] Verifier 只接收通过 binding 对应的 `verified_evidence`,不接收完整 `tool_trace_summary`。
- [ ] 未被 Executor 引用或未通过 Gatekeeper 的工具结果不能进入 Verifier 输入。
- [ ] Gatekeeper LOW_CONFID 路径的 `effective_verdict` 不得升级为 PASS。
- [ ] Gatekeeper 原始 pass/fail + severity 正确标准化为 PASS / LOW_CONFID / REJECT,未知状态安全映射为 REJECT。
- [ ] Verifier 执行状态与诊断 verdict 分离,任何失败状态不得出现在 model/effective verdict 中。
- [ ] Composer 和 Graph 条件边只读取 `effective_verdict`。
- [ ] Verifier INVALID_OUTPUT / RETRYABLE_FAILED 使用相同 verified input 最多技术重试一次,且不重新执行 Gatekeeper、Executor 或工具。
- [ ] Composer INVALID_OUTPUT / RETRYABLE_FAILED 使用相同安全输入最多技术重试一次,且不重新执行 Verifier 或前序节点。
- [ ] Verifier 第二次技术失败或 NON_RETRYABLE_FAILED 的 Fallback 不输出 Executor claim。
- [ ] Composer 第二次技术失败或 NON_RETRYABLE_FAILED 使用确定性安全模板。
- [ ] `verifier_retry_count`、`composer_retry_count` 和 `evidence_retry_count` 互相独立。
- [ ] Verifier LOW_CONFID 最多触发一次 Planner 补证据。
- [ ] LOW_CONFID 补证据循环受一次补查上限和 Graph recursion limit 限制。
- [ ] Gatekeeper verdict ceiling 导致的 LOW_CONFID 不触发补证据。
- [ ] 无法从 `facts_checked` 提取有效 `evidence_gaps` 时不触发补证据。
- [ ] 第二轮 Planner 只输出增量计划,不扩大诊断范围或重复成功查询。
- [ ] 第二轮 Executor 只执行增量查询,但输出完整 `executor_evidence_v2` 快照,而不是仅输出新增片段。
- [ ] 第二轮完整快照包含需要保留的第一轮可信 claims,并由 Gatekeeper 对全部 binding 重新验真。
- [ ] Java 编排层不对两轮 claim 文本进行语义合并。
- [ ] Composer 技术重试耗尽或不可重试失败时使用固定模板结束。
### 证据和安全
- [ ] Gatekeeper 规则语义不放宽。
- [ ] Verifier 只消费已验真证据。
- [ ] no-evidence 不得表达为已排除或问题不存在。
- [ ] REJECT 降级不泄漏 Executor 原始答案和未验证根因。
- [ ] Executor INVALID_OUTPUT、Gatekeeper REJECT 和零条可信 binding 的固定 Fallback 不输出任何 Executor claim。
- [ ] 前置验证失败 Fallback 只展示校验状态、工具执行概况、诊断限制和人工复核建议。
### 数据与审计
- [ ] Graph 使用 runId 作为 threadId。
- [ ] Agent step、tool invocation 和 self_evaluation 仍绑定正确 runId。
- [ ] `orchestration_trace` 只写入当前 diagnosis run,不污染其他 run 或 session 级数据。
- [ ] `orchestration_trace` 不包含 Prompt、模型思考、工具原文和 Graph State 快照。
- [ ] `orchestration_trace.transitions` 由有界 `orchestration_events` 生成,与实际节点执行顺序一致。
- [ ] 可处理异常发生时,已经产生的 orchestration events 能够 best-effort 写入当前 run。
- [ ] Trace 能展示实际节点路径、重试原因和终止原因。
- [ ] 每个新 StateGraph Chat run 的 `run.orchestrationTrace` 非空,且顶层和兼容 `session` 投影不重复该字段。
- [ ] Run 最终状态、答案、耗时、Token 和工具调用数正确回填。
- [ ] 所有成功生成安全响应的终止路径将 Run 标记为 SUCCESS,并通过 verdict 或 `orchestrationTrace.degraded` 表达质量。
- [ ] 只有未处理异常、持久化失败或无法生成安全响应时将 Run 标记为 FAILED。
### 工程质量
- [ ] 新 Graph 测试覆盖所有分支。
- [ ] `ChatServiceSequentialAgentTest` 已由新测试替换。
- [ ] 不保留长期重复的 Sequential 和 Graph 两套实现。
- [ ] 数据库 schema 仅新增 `diagnosis_run.orchestration_trace` nullable JSON 字段。
- [ ] `/api/chat` 和证据协议不变;Trace API 仅在 `run` 对象新增必有的 `orchestrationTrace` 字段。
---
## 12. 风险与缓解
### ReactAgent 父子 Graph 状态污染
风险:直接使用 `asNode(...)` 可能导致 `messages`、outputKey 或 checkpoint 传播不符合预期。
缓解:第一阶段使用适配 Node 显式调用 Agent;完成契约测试后再考虑直接子图节点。
### Gatekeeper 重复执行
风险:显式 Gatekeeper Node 与现有 `VerifierInputHook` 同时执行。
缓解:迁移时明确 Gatekeeper 只有一个入口;Verifier Hook 只负责构造输入或被替换。
### LOW_CONFID 循环失控
风险:Verifier LOW_CONFID 持续返回 Planner,形成重复规划和工具调用。
缓解:保留当前最多一次补证据约束,并设置 Graph recursion limit 作为最终保险。
### Trace 与 Graph Checkpoint 语义混淆
风险:把当前数据库 Trace 当作 Graph 恢复检查点,或把 `MemorySaver` 当成持久化。
缓解:本期 Graph 只负责控制流程,不声明跨重启恢复;HITL 和持久 Checkpointer 单独立项。
---
## 13. Out of scope
本 issue 暂不包含:
- AIOps 迁移到公共 Graph。
- Chat 和 AIOps 入口统一。
- SupervisorAgent 和专科 SubAgent。
- 人工中断、审批和恢复。
- 持久化 Checkpointer。
- 并行工具或并行 Agent。
- EvidenceRepairNode 和 Gatekeeper REJECT 自动修复。
- Gatekeeper REJECT 返回 Executor 的重试回边。
- 除 Planner Adapter 注入 `EVIDENCE_GAP_ONLY` 编排约束外,修改 Prompt 核心业务语义。
- 修改 `executor_evidence_v2`、Verifier、Composer 协议。
- 除 `diagnosis_run.orchestration_trace` 外的其他数据库表或字段。
这些能力应在本 issue 完成后根据实际收益单独讨论。
---
## 14. 已冻结决策
以下决策均已确认,不再作为开放问题:
- 第一阶段保留现有 ReactAgent,通过 Adapter Node 调用。
- 父 Graph State 不直接传给 ReactAgent,使用每个 Agent 独立的 Input DTO 做白名单投影。
- 第一阶段不直接依赖 `ReactAgent.asNode(...)` 实现父子编排。
- Planner 仅对 INVALID_OUTPUT 或 RETRYABLE_FAILED 进行每阶段最多一次技术重试;NON_RETRYABLE_FAILED 和第二次技术失败直接 Fallback,且该计数与补证据轮次隔离。
- Gatekeeper REJECT 本期不重试,直接进入 Fallback。
- 本期不增加 EvidenceRepairNode。
- Executor INVALID_OUTPUT 本期不重试,直接进入固定 Fallback。
- Executor 状态按输出契约定义:合法结构统一为 COMPLETED;只有明确工具阻断且无合法输出为 TOOL_BLOCKED,其他无合法输出的执行异常为 FAILED,三类失败均不重试。
- Executor INVALID_OUTPUT、Gatekeeper REJECT 或零条可信 binding 进入前置验证失败 Fallback 时,不展示任何 Executor claim;部分通过 binding 不用于拼接用户答案。
- Gatekeeper LOW_CONFID 有已验真 binding 时进入 Verifier,零条时直接 Fallback。
- Gatekeeper LOW_CONFID 路径的最终 verdict 上限为 LOW_CONFID。
- Gatekeeper 原始 result 与标准化 `gatekeeper_status` 分开保存;Verifier 使用 `verifier_status`、`verifier_model_verdict` 和 `effective_verdict` 分离执行状态、模型结论和编排生效结论,任何执行失败状态都不作为诊断 verdict。
- Verifier 和 Composer 对 INVALID_OUTPUT / RETRYABLE_FAILED 各允许一次固定输入技术重试;不得重新执行前序节点,第二次失败或 NON_RETRYABLE_FAILED 进入对应安全降级,并与 `evidence_retry_count` 分开计数。
- Gatekeeper PASS 和可继续的 LOW_CONFID 都先经过 Verifier Input Builder;Verifier 只接收通过 binding 对应的 `matched_text` 所构成的 `verified_evidence`,不再接收完整 `tool_trace_summary`。
- Verifier LOW_CONFID 的补证据路径返回 Planner,并使用 `EVIDENCE_GAP_ONLY` 增量规划模式。
- Gatekeeper ceiling、无法从 `facts_checked` 提取有效缺口或已经补查时不触发 LOW_CONFID 重试。
- Verifier 不新增 missing evidence 或工具规划字段;Prepare Evidence Retry Node 将现有 `facts_checked` 转换为结构化 `evidence_gaps`,第二轮 Planner 决定工具和增量查询计划。
- 补证据采用“Planner 增量规划、Executor 增量查询但完整输出”的策略;第一轮已验证材料作为只读输入传给第二轮 Executor,Java 不做 claim 语义合并,第二轮完整快照重新经过 Gatekeeper 和 Verifier。
- Graph 路由摘要写入独立的 `diagnosis_run.orchestration_trace`,不耦合进 `self_evaluation`。
- Trace API 只通过 `run.orchestrationTrace` 暴露解析后的编排摘要,不复制到顶层或兼容 `session` 投影;本期不处理历史 run 回填和兼容读取。
- `diagnosis_run.status` 只表达执行生命周期:安全 Fallback 仍为 SUCCESS 并设置 `orchestrationTrace.degraded=true`;只有无法生成安全响应的未处理失败才为 FAILED,不新增 DEGRADED 状态。
- Graph State 使用有界追加的 `orchestration_events` 作为路由事实来源,结束时压缩为 `orchestration_trace`,不通过日志反推路径。
- 不保留 Sequential / StateGraph 双链路配置开关;在专用 Git 分支完成实现和验收后,直接以 StateGraph 替换旧复杂诊断编排。
- 实现期间允许代码处于分支内的阶段性状态,但合并前必须删除旧 Sequential 编排和不再使用的迁移代码,不形成长期双轨维护。
---
## 15. 相关文件
- `src/main/java/com/superbiz/agent/service/ChatService.java`
- `src/main/java/com/superbiz/agent/service/ExecutorGatekeeperService.java`
- `src/main/java/com/superbiz/agent/hook/VerifierInputHook.java`
- `src/main/java/com/superbiz/agent/service/ToolTraceSummaryService.java`
- `src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java`
- `src/test/java/com/superbiz/agent/service/ChatServiceSequentialAgentTest.java`
- `src/test/java/com/superbiz/agent/service/ExecutorGatekeeperServiceTest.java`
- `src/test/java/com/superbiz/agent/hook/VerifierInputHookTest.java`
- `mvp/architecture/agent-orchestration.md`
- `mvp/architecture/harness-quality-gates.md`
- `knowledge_20260716_Spring_AI_Alibaba_Graph_诊断编排改造/`
## 16. 参考文档
- https://java2ai.com/docs/frameworks/graph-core/core/core-library
- https://java2ai.com/docs/frameworks/graph-core/quick-start
- 当前依赖:`spring-ai-alibaba-graph-core:1.1.2.0`
- 当前依赖:`spring-ai-alibaba-agent-framework:1.1.2.0`