# 2026-07-10 Multi-Agent 诊断当前设计

**状态**：当前实现设计快照
**基准**：`origin/main` 2026-07-10，约 `a9af4b3e`
**取代口径**：2026-05 的 multi-agent plan/work-summary，以及 2026-07-02 版本里的固定 `diagnosis-orchestrator -> evidence-agent -> diagnosis-analyst` 口径。

主要代码入口：

- `agentkit/config/investibook/agents/investigator.md`
- `agentkit/config/investibook/agents/evidence-agent.md`
- `agentkit/config/investibook/agents/diagnosis-analyst.md`
- `agentkit/skills/builtin/diagnosis-overview/SKILL.md`
- `agentkit/skills/builtin/tidb-clinic-diagnosis/`
- `agentkit/skills/builtin/tidb-clinic-diagnosis/scripts/write_evidence_agent_handoff.py`
- `agentkit/skills/builtin/tidb-clinic-diagnosis/scripts/write_analyst_report.py`
- `backend/investibook/core/acp.py`
- `backend/investibook/core/workspace_evidence_store.py`
- `backend/investibook/core/eval/`

## 1. 当前设计目标

当前 multi-agent 诊断不是简单增加 agent 数量，而是把诊断做成可控的 investigation loop：

- 先收集证据，再暴露异常，最后从异常推导根因。
- 用户断言、collector hints、agent hypotheses 都必须被验证，不能直接当结论。
- 子 agent 是 context firewall：吸收高噪声工具输出，只交回小型 JSON artifact。
- 简单清晰的 case 由 `investigator` 直接按 analyst contract 结论化。
- 复杂、多候选、争议、需要组件深诊断的 case 才派 `diagnosis-analyst`。
- Evidence collection 与 root-cause reasoning 分离；分析层不直接采集 Clinic/O11Y/Jira/DevOps 数据。
- 诊断输出以 `evidences/agent-runs/*.json` 和 `workspace_evidence_report.json` 为 contract，不以 child chat 文本为 contract。

## 2. 当前角色分工

| 角色 | 职责 | 可以做 | 不应做 | 关键输出 |
|---|---|---|---|---|
| `investigator` | 用户入口、调查负责人、最终结论 owner | intent gate、scope 保真、读取 workspace/context/catalog、验证用户 premise、调度子 agent、清晰 case 直接写 analyst contract | 不把未验证断言当结论；不直接运行 `collect_evidence.py`；不在 artifact 缺失时声称子任务完成 | 用户最终回复；必要时写 `evidences/agent-runs/diagnosis-analyst.json` |
| `evidence-agent` | 数据采集 specialist | sweep mode 跑标准 collector；targeted mode 按 hypothesis 查询指定数据；写 handoff | 不做最终根因判断；不加载 diagnosis reasoning skill；不输出用户诊断报告 | `evidences/agent-runs/evidence-agent.json` |
| `diagnosis-analyst` | 昂贵的深度根因推理 specialist | 读取已有 evidence、应用 diagnosis-overview 和 TiDB diagnosis subskills、写 analyst artifact 和 report analysis | 不调用 Clinic/O11Y/Jira/DevOps/GitHub；不运行 collector；不无限探索 | `evidences/agent-runs/diagnosis-analyst.json`，`workspace_evidence_report.json` |
| Backend/ACP | runtime 辅助层 | 初始化 workspace config/skills；pin session 到 `investigator`；collector 成功后自动写 handoff；eval/judge contract | 不成为诊断状态机 | workspace `.opencode/`、auto handoff、eval facts |

`diagnosis-orchestrator` 已不是当前主入口。当前入口 agent 是 `investigator`，它比旧 orchestrator 更主动：不仅调度，也负责 plan、premise verification、candidate weighing，并能在高置信清晰 case 中直接结论化。

## 3. Investigation Loop

```mermaid
flowchart TD
  U["User message"] --> I["investigator intent gate"]
  I -->|chat| C["reply directly"]
  I -->|ad-hoc lookup| L["investigator uses clinic-cli/time-conversion"]
  I -->|follow-up| R["read known workspace artifact"]
  I -->|root cause / impact / remediation| P["plan: scope + existing coverage + KB + diagnosis-overview"]
  P --> E{"valid evidence covers scope?"}
  E -- no --> EA["dispatch evidence-agent"]
  EA --> S{"mode"}
  S -- sweep --> COL["standard collector first"]
  S -- targeted --> TGT["named hypothesis/data fetch"]
  COL --> AH["backend/agent writes evidence-agent.json"]
  TGT --> AH
  E -- yes --> DP["deep plan: anomaly set + 2-3 hypotheses"]
  AH --> DP
  DP --> W{"clear enough?"}
  W -- yes --> DC["investigator writes analyst contract"]
  W -- needs data --> TE["targeted evidence-agent pass"]
  TE --> DP
  W -- hard reasoning --> DA["dispatch diagnosis-analyst"]
  DA --> AR["diagnosis-analyst.json + write_analyst_report.py"]
  DC --> AR
  AR --> F["investigator final answer from artifact"]
```

关键规则：

- 每次 diagnosis 都先读 workspace context、skill catalog、tier architecture、`incorrect-conclusions.json`、`diagnosis-overview`。
- `evidence-agent.json` / `diagnosis-analyst.json` 是子任务完成的证明；child chat 文本不算。
- 既有 evidence 覆盖 scope 时，不为了刷新历史窗口重复采集。
- 用户明确要求某类数据或要求跳过 broad sweep 时，优先 targeted mode。
- `needs_more_evidence=true` 最多触发一次 targeted collection + final analysis pass。
- 一旦有效 `diagnosis-analyst.json` 存在，`investigator` 读取它并立即答复，不再做额外扩展搜索。

## 4. Intent Gate

`investigator` 每条消息先分流：

| Intent | 当前路径 |
|---|---|
| 普通聊天、概念问答、讨论已有答案 | 直接回复，不用工具 |
| Ad-hoc lookup，例如列数据、排行、格式化指标，不问根因 | `investigator` 自己按 runtime triage 通过 builtin `clinic-cli` / `time-conversion` 执行，不派 subagent |
| 对已有结果追问，且能由一个 workspace 文件回答 | 读 `diagnosis-analyst.json`、`evidence_summary_for_agent.txt` 或用户点名文件 |
| 根因、影响、修复、诊断 | 进入 investigation loop |

这意味着 multi-agent 不再是所有诊断请求的固定第一步，而是调查过程中按成本和复杂度选择的执行策略。

## 5. Evidence Agent 当前设计

Evidence agent 现在有两种模式。

| 模式 | 触发 | 行为 | 退出条件 |
|---|---|---|---|
| Sweep | 默认，无具体 hypothesis/data directive | 尽快运行标准 collector，产出 root artifacts 和 anomaly hints | 写 `evidence-agent.json` 并返回一行 handoff |
| Targeted | `investigator` 指定 hypothesis 和要查的数据 | 只查指定组件、窗口、指标、日志、digest 或 raw evidence；记录 present/absent | 更新 evidence files 和 `evidence-agent.json` |

Sweep mode 的关键点：

- 不预先 broad scan、schema discovery 或 credential preflight。
- 优先运行第一个存在的 collector：
  - `.opencode/skills/builtin/tidb-clinic-diagnosis/scripts/collect_evidence.py`
  - `.opencode/.all-skills/builtin/tidb-clinic-diagnosis/scripts/collect_evidence.py`
- collector 成功后确认四个 root artifacts：
  - `evidences/evidence_summary_for_agent.txt`
  - `evidences/evidence_summary_for_agent.json`
  - `evidences/collection_errors.json`
  - `evidences/workspace_evidence_report.json`
- 不把 `metrics.json`、`logs.json`、`queries.json`、raw files 读入 chat context 做总结。
- 写 handoff 后立即返回，不做根因判断。

Runtime 层还有一个 fast path：`backend/investibook/core/acp.py` 会识别 `collect_evidence.py` 成功输出，并调用 `write_standard_collector_handoff()` 自动从 collector summary 写 `evidences/agent-runs/evidence-agent.json`。因此 handoff 现在是 backend/agent 双保险，不完全依赖 LLM 手写。

## 6. Diagnosis Overview 的新位置

`diagnosis-overview` 是当前流程新增的通用诊断纪律，不替代 `tidb-clinic-diagnosis`，而是规定如何从证据到结论：

- latency investigation 先看 TiDB query latency ladder 和 TiKV gRPC latency ladder。
- 每个 claim 必须在自己的维度验证：例如“慢”要看 latency，不用 CPU proxy 直接确认或否定。
- collector hints 是 leads，不是 verdict；必须回到 underlying artifact 确认。
- TopSQL rank 不等于 cause。
- co-occurring event 不等于 cause。
- capacity differential 优先于被 reduced capacity 承载的普通 query signals。
- 背景压力必须通过 throttle path 变成用户可见 latency，不能只说 compaction/GC debt。
- 结论必须包含 terminal mechanism、candidate weighing、known issue correlation、四个 horizon 的 remediation。

`investigator` 直接结论化和 `diagnosis-analyst` 深度分析都必须遵循这套 discipline。

## 7. Diagnosis Analyst 当前设计

`diagnosis-analyst` 是 expensive reasoning tier。默认进入 bounded fast diagnosis，而不是无限读文件：

1. 第一轮并行读取：
   - `evidences/agent-runs/evidence-agent.json`
   - `evidences/evidence_summary_for_agent.json` 或 `.txt`
   - `tier-architecture.json`
   - `incorrect-conclusions.json`
   - `diagnosis-overview/SKILL.md`
   - `tidb-clinic-diagnosis/SUBSKILLS_INDEX.md`
   - `tidb-clinic-diagnosis/root-cause-classification/SUBSKILL.md`
2. 默认不读大文件或 raw evidence。
3. 只有 load-bearing 问题需要时，才用 `read_raw_evidence.py` 过滤 raw matrices 或读具体 raw logs/events。
4. 将 abnormal signals 写成 `signal_tags`。
5. 用 root-cause classification subskill 生成 2-3 个候选 root-cause classes。
6. 读取 primary family subskill；最多再读一个会改变 remediation 的 contributing family subskill。
7. 写 `diagnosis-analyst.json`，再运行 `write_analyst_report.py`。

`write_analyst_report.py` 是 report merge 的收口工具：它会补齐可机械推导字段、检查 `KB Step B complete: Pitfall catalog loaded`、保留 collector-owned raw fields、替换 `analysis`、修复 time range contract 并验证 JSON。

## 8. Root-Cause Classification 当前口径

分类仍然是诊断中间层，而不是最终 prose 里的标签。

标准 root-cause class：

| Standard class | 适用范围 |
|---|---|
| `sql_plan_or_query` | SQL、执行计划、访问路径、SlowQuery、TopSQL 主因 |
| `transaction_or_lock_contention` | lock wait、deadlock、write conflict、transaction path |
| `tikv_hotspot_or_coprocessor` | TiKV hotspot、coprocessor、unified read、store-local skew |
| `storage_or_io_bottleneck` | Disk IO、RocksDB、raft/apply/propose、IO throttle |
| `memory_or_oom_pressure` | memory quota、heap pressure、memory tracker、OOM |
| `gc_or_allocator_pressure` | Go GC、allocation churn、allocator/profile-driven CPU 或 latency |
| `resource_control_or_capacity` | RU throttling、capacity loss、node count reduction、worker loss |
| `pd_tso_or_scheduling` | PD、TSO、scheduler、placement、region health、etcd |
| `cdc_or_replication_lag` | TiCDC lag、changefeed、owner/maintainer/dispatcher、sink |
| `network_or_connectivity` | 独立网络、gRPC/connectivity、cross-component communication |
| `component_failure_or_bug` | panic、restart、crash、known bug、component failure |

当前实现细节需要特别注意：

- `root-cause-classification/SUBSKILL.md` 要求先给 2-3 个 candidate，candidate `class` 建议用 standard class。
- `diagnosis-analyst-output.schema.json` 仍保留 legacy `primary_class` enum，并且 `candidates` 仍兼容 string 或 object。
- `standard_root_cause_class`、`classification_subskill_refs` 目前不是 schema 必填字段。
- Eval judge 当前主要校验 `signal_tags`、`fault_classification.primary_class`、`candidates`、`rejected_classes`、`classification_confidence`、`missing_evidence_for_higher_confidence`、`selected_diagnosis_skills`。

所以分类现在是“prompt/subskill 强约束 + schema 兼容 + judge 基础 contract 校验”的混合状态，不是完全 schema-hard 的状态。后续如果要继续治理分类稳定性，可以再把 `standard_root_cause_class` 和 family subskill refs 推到 schema/judge 硬约束。

## 9. 文件和 Schema 契约

核心 artifacts：

```text
evidences/
  evidence_summary_for_agent.txt
  evidence_summary_for_agent.json
  collection_errors.json
  workspace_evidence_report.json
  metrics.json
  workload.json
  resource_control.json
  component_health.json
  queries.json
  logs.json
  tikv_thread_cpu.json
  gate_checks.json
  links.json
  raw/
    manifest.jsonl
  agent-runs/
    evidence-agent.json
    diagnosis-analyst.json
```

Schema：

- `.opencode/investibook/schemas/evidence-agent-output.schema.json`
- `.opencode/investibook/schemas/diagnosis-analyst-output.schema.json`

`diagnosis-analyst.json` 可以由 `diagnosis-analyst` 写，也可以由 `investigator` 在清晰 case 中写；schema 的 `agent` 允许 `diagnosis-analyst` 和 `investigator`。

`workspace_evidence_report.json` 是前端展示和 eval 读取共用的 report。collector 先写 raw evidence 字段，analysis side 通过 `write_analyst_report.py` 只替换 `analysis`，并保留 `metadata`、`evidence`、`gate_checks`、`resource_control`、`component_health`、`workload`、`links` 等 collector-owned 字段。

## 10. Eval 可观测性

当前 judge 会检查 workflow、evidence routing、classification contract 和 final diagnosis。

关键 workflow/routing facts 包括：

- `architecture_context_loaded`
- `misdiagnosis_guardrails_loaded`
- `direct_conclusion_by_investigator`
- `evidence_collection_completed`
- `diagnosis_analyst_contract_present`
- `classification_contract_valid`
- `signal_tags_contract_valid`
- `fault_classification_contract_valid`
- `selected_diagnosis_skills_present`
- `primary_fault_class_*`

这让我们区分：

- evidence 没采到
- collector 采到了但 handoff/report 缺失
- investigator 直接结论是否符合 analyst contract
- signal tags 格式或 evidence ref 不合法
- fault classification contract 是否存在
- primary legacy class 是否命中
- 分类候选是否包含正确方向但 final root cause 取舍失败
- final answer 是否没有承接 artifact 里的结构化结论

注意：截至当前 main，`classification_subskill_refs_present` 和 `standard_root_cause_class_valid` 不是 judge 的通用 routing facts；如果后续要评分类 subskill 是否真正被读到，需要补 schema/judge/facts。

## 11. 和 2026-07-02 版本的主要差异

| 2026-07-02 口径 | 2026-07-10 当前口径 |
|---|---|
| 主入口是 `diagnosis-orchestrator` | 主入口是 `investigator` |
| 固定三段式：orchestrator -> evidence-agent -> diagnosis-analyst | Investigation loop：plan、collect、deep plan、direct conclude / targeted dig / analyst escalation |
| Orchestrator 不写 root cause | `investigator` 可在清晰 case 中直接写 analyst contract，`agent=investigator` |
| Evidence agent 主要描述为 collector fast path | Evidence agent 明确分 sweep / targeted 两种模式 |
| Diagnosis analyst 是唯一 root-cause 作者 | Analyst 是 expensive reasoning tier；不是所有 case 都必须派 |
| 分类 hard gate 侧重 schema/subskill refs | 当前 schema 仍兼容 legacy；standard class 和 subskill refs 主要是 prompt/subskill 约束 |
| 文档未覆盖 `diagnosis-overview` | `diagnosis-overview` 成为 claim verification / evidence weighing / conclusion contract 的核心纪律 |
| Handoff 主要由 evidence-agent 写 | Backend ACP 可在 collector 成功后自动写 `evidence-agent.json` |

## 12. 当前已知边界

- CDC 分类和 subskill 已存在，但 evidence collector 对 CDC/changefeed/sink/owner/maintainer 证据仍不充分；CDC case 暂时不应作为整体分类能力的主要验收标准。
- `standard_root_cause_class` 与 `classification_subskill_refs` 尚未成为 schema/judge 硬 contract，分类质量仍可能在最终诊断中漂移。
- `investigator` 直接结论提升了效率，但也要求 eval 区分“direct conclusion by investigator 是否合格”和“是否应该升级 analyst”。
- Targeted evidence 是必要能力，但需要防止变成隐式自由探索；每次 targeted pass 都应该绑定 hypothesis 和要验证的数据维度。
- 旧 case 仍受数据保留期、日志接入、租户路由变化影响。长期回归应尽量使用新鲜 case，或固化 reference artifacts 做离线评分。
- Family subskills 仍需要持续从低分 case、nutshell skills 和真实 incident 中回填机制知识。

## 13. 后续建议

1. 把这份文档作为新的 multi-agent 设计入口，旧文档只保留历史演进意义。
2. 补一张 case matrix：`investigator direct` / `targeted evidence` / `analyst escalation` / `classification hit` / `final diagnosis hit` 分开看。
3. 将 `standard_root_cause_class` 和 `classification_subskill_refs` 是否硬化为 schema/judge contract 作为下一轮分类治理决策。
4. 对每个 standard root-cause class 建立小型 eval slice，区分“分类没包含正确类”和“分类包含正确类但专项诊断失败”。
5. 继续把反复出现的 targeted evidence 需求沉淀进标准 collector 或专项 evidence module，减少 prompt 里的 case-specific 规则。
