AI Agent Evaluation Workspace · Review

AI Agent 調查資料集與評測架構
評估與雙方比較

評估日期 2026-09-12 · 合併整理 2026-09-13 · 對象:DESIGN / ARCHITECTURE / SKILL / 兩份 YAML 範本,及兩份獨立審查報告

這份文件在講什麼(一句話): 目前的五個設計檔案方向正確(三層分離、deterministic-first、dataset-first),但格式互不相容、evidence 會過期、eval 會洩題。兩個獨立 agent 各自審查後給出幾乎相同的修正清單,可以直接照著做。

#先記住的結論為什麼重要
1 兩份獨立評估的交集是高信心清單,不是各說各話。 兩個 agent 拿相同來源,獨立得出幾乎相同的 P1 問題(approved 預設、evidence 會過期、洩題、schema 不成契約、SKILL 缺 frontmatter)。 這份交集可以直接當修正 backlog,不需要再辯論要不要做。
2 Dataset 的第一個路障是 replay,不是工具選型。 一個歷史 incident 要能被重新調查,必須先決定 evidence 用什麼形式保存;沒解決這題,選哪個 eval 平台都沒用。 兩份評估都同意:先把 evidence 快照機制做出來,工具晚點選。
3 選 eval runner 前,必須先確認公司 agent 的執行框架。 這題兩份評估都沒能替你回答,卻決定了第一個可行動的下一步。 是 Claude Code 系就先試 claude plugin eval;是 Strands/AgentCore 就先試 Strands Evals;都不是就用 promptfoo 包一層 adapter。

Part 1 · Why為什麼要改(現況與問題)

這節回答:目前的設計哪裡是對的、哪裡壞了、兩份獨立評估怎麼會得出同一份問題清單。

1.1 設計的核心原則是對的

現有的 DESIGN-google-eval-aligned.mdARCHITECTURE-google-eval-aligned.md 建立了三層分離:

flowchart LR
    S["Session
暫時對話記憶"] --> W["Workspace State
目前工作記憶"] W --> K["Knowledge
長期學到的東西"] W -.平行.-> E["Evaluation
agent 表現是否可靠"] K -.平行.-> E

三層都同意保留:

  • State / Knowledge / Evaluation 分離:workspace 的「現在」、跨案例的「學到什麼」、agent 品質的「可不可靠」是三件事,不該混在一起。
  • Deterministic-first:能用程式判斷的絕不用 LLM 判斷。
  • Harness-aware:比較 agent 表現時要連 model / skill / tool / guardrail 一起記錄,否則「換了 model」和「skill 壞了」分不清楚。
  • 負向案例是資產:inconclusive、false alarm、無法確診都要保留,不是只收集「破案」的案例。
  • 人工 promotion gate:agent 產的結論不能自動變成 golden ground truth。

1.2 但五個檔案彼此不相容

問題具體位置
目錄結構有兩套ARCHITECTURE 用 .evals/{datasets,rubrics,baselines,runs,schemas};SKILL.md 用 evals/incidents/{records,golden}
Eval case 有三種形狀DESIGN 的 expected.facts/required_evidence、ARCHITECTURE 例子的另一種組合、templates/eval-case.yamlroot_cause/important_findings 又是第三種
deterministic_checks 的 type 從未定義文件裡出現 no_forbidden_tool_callstool_or_query_match,但沒有參數、沒有列舉,無法寫 schema 也無法寫 runner
review.status: approved 是模板預設值直接複製就會被當成已核准案例,違反 skill 自己「不能自我核准」的規則
SKILL.md 沒有 frontmattername / description,標準 skill discovery(Claude Code、Kiro、Codex)都不會載入它
Evidence 只存 query + time range沒有 snapshot、沒有 hash、沒有保存時機;log / metric 有 retention,幾個月後 reference 會失效

最貴的一個問題: evidence 只存「怎麼查」而不存「查到了什麼」。一個 incident record 存的是 Prometheus 的 PromQL 和時間範圍,但 Prometheus 通常只保留 15–90 天資料。三個月後想把這個案例變成 golden eval case 時,重新執行同一條 query 拿到的可能是空結果——不是因為系統沒異常,是因為資料已經過期。這代表:evidence 快照必須在調查「當下」保存,不能等到挑 golden case 的時候才回頭補。

1.3 兩份獨立評估怎麼會得出同一份清單

同一批來源檔案,交給兩個不同的 agent 分別審查,結果在下面這些點上完全一致,一字不差地指向同一個修正方向:

  • Evidence 需要快照 + hash + 保存時機,不能只有 reference
  • review.status 預設必須是 draft
  • Eval case 必須防止受測 agent 讀到答案(isolation)
  • Schema 需要版本化,且三份文件的格式要統一
  • Safety 類 check(例如「不能寫入」)必須是一票否決,不能被分數平均掉
  • Data classification 的 false 分不出「沒檢查」和「確認沒有」
  • SKILL.md 需要標準 frontmatter
  • Session-end hook 不可靠,不該是唯一的資料擷取點
  • Kiro Crew 是 workspace 層的候選,不是 dataset / eval 工具

兩個獨立來源收斂到同一組結論,代表這些不是某一方的偏好,而是設計本身的結構性缺口。

完整比對細節(含逐條來源引用)收在下方「查資料 → 兩份評估的完整交集清單」。

1.4 三個真正的分歧,以及怎麼合併

不是每一點都一致。有三處兩份評估給出不同答案,原因、取捨、以及合併後的做法如下:

分歧立場 A立場 B怎麼合併
Replay 第一步怎麼做 直接上 mocked tools + fixtures,因為要評 trajectory 不能只評閱讀理解 先用靜態 evidence bundle 評 output,因為 mocked tools 隱含一串沒解決的規格(query matching、virtual clock、fixture miss 行為) 第一天就用 hook 存 tool 輸出;第一批 eval 先只評 output;fixtures 覆蓋率夠了再升級成 mocked tools
哪裡是 canonical git 裡的 YAML,S3 只放版本化快照 S3 上 validator 正規化後的 JSON revision 才是 canonical,且 input / expected 拆成兩個檔案給不同角色讀 git YAML 是編輯與 PR review 介面;publisher 正規化成 JSON、拆檔、算 hash、寫 manifest 後,S3 上的版本才是 runner 實際讀的 canonical
第一個要試的 runner Claude Code 的 claude plugin eval(隱含假設 agent 跑在 Claude Code 上) 依框架而定:promptfoo 包 adapter,或若已用 Strands/AgentCore 就先試官方工具(隱含假設框架未知) 這題兩邊都答不了,因為都不知道公司 agent 的實際框架。先確認這一點,再選路。

第二個分歧(canonical 位置)看似對立,其實兩邊描述的是同一個流程的不同標籤:草稿在 git 給人審,正式發布後的版本在 S3 給機器讀。真正的取捨只在「isolation 靠一個欄位宣告」還是「靠物理拆檔 + IAM 角色」——後者更硬,但成本也更高,規模小的時候前者夠用。


Part 2 · Do怎麼做(合併後的優先清單與行動順序)

這節回答:現在具體要改什麼、先改哪個、卡住的決策點在哪。

2.1 一個必須先問的問題

在動手之前,先回答這題,它決定了第 15 項要走哪條路:

公司現在用來做 incident 調查的 agent,實際跑在哪個框架上?(Claude Code + skills?Strands / AgentCore?LangGraph?別的?)

兩份評估都沒有這個資訊,所以都只能寫條件式建議。這是唯一一項需要人決定、無法由文件分析出來的事。

2.2 合併後的優先清單

#要做的事為什麼類別
1review.status 預設改 draft;approval 綁定 case 的 revision / content hash,改內容後舊 approval 失效模板現況會讓複製出來的案例自動被當成已核准Schema
2拆四層版本:schema_version(格式)、record_revision/case_revision(內容)、dataset_release(整包案例的版本)、rubric_version(判分定義)目前 dataset_version: 1 把單筆案例和整套資料集版本混在一起Schema
3Evidence 補 evidence_idsnapshot_refsha256observed_atavailable_atsource_retention_untildecision_relevant;查不到就標 reference_only,不能編造內容本次評估中優先級最高的單一改動,解決「replay 不可行」的根本問題Schema / Replay
4expected 改用 outcome 列舉(diagnosis/insufficient_evidence/no_issue/escalate),root causes 允許空陣列目前每個 case 都要求填 root cause,會誘導 agent 在無法確診的案例上亂猜Eval schema
5as_of 決策時點,evidence bundle 依此截止,排除事後才出現的 postmortem 與修復結果防止「時間上的洩題」,尤其在接了 RAG 之後更重要Eval schema
6Conclusion 改成 claims 陣列(statement/status/evidence_ids),actions 分 proposed/executed/verified承載多因、部分確認的真實案例;避免「建議重啟」被誤存成「已重啟且成功」Schema
7data_classification 改三態(unknown/present/absent)+ sanitization.statusfalse 目前分不出「沒檢查」和「確認沒有」Schema
8SKILL.md 補 YAML frontmatter(name/description),name 與資料夾一致,瘦身到約 120 行,其餘移到 reference/沒有 frontmatter,標準 skill discovery 不會載入這份 skillSkill
9定義封閉的 grader 字彙(tool_called/tool_not_called/tool_order/trajectory_contains/output_regex/output_schema/budget/identifier_found),safety 類 check 設為一票否決目前只有 type 名稱,無參數無版本,無法判分也無法跨工具匯出Eval 契約
10每個 case 發布時物理拆成 input.jsonexpected.json,不同 IAM 角色讀取;受測 agent 的檔案/工具權限只能碰 input防止洩題不能只靠一個 isolation 欄位宣告,要靠物理隔離隔離
11runs_per_case 定義聚合方式(建議 3 次跑一次,safety 用 all-of-N,品質用 mean),judge 記錄 model/prompt 版本/投票數,留 10–20 筆人工評分做 calibration單次跑一個非決定性 agent 幾乎沒有資訊量Eval 執行
12建立「git YAML 編輯 → publisher 正規化成 JSON revision → S3 immutable release manifest(conditional write)→ Parquet 衍生分析」的流程合併兩份評估對 canonical 位置的分歧(見 1.4)儲存
13Agent-run trace schema 對齊 OpenTelemetry GenAI 命名(invoke_agent/execute_tool/gen_ai.tool.name讓 Bedrock AgentCore、Langfuse、Phoenix 都能直接吃這份 traceTrace
14Session-end hook 不當唯一擷取點;改用「調查途中隨時保存重要證據 + hook 只做補充」,並容忍 Kiro stop/Claude Stop 是每回合觸發而非 session endCodex CLI hooks 仍是實驗性,四個 CLI 的 hook 能力並不均等Hook
15先確認 2.1 的問題,再選 runner:Claude Code 系 → 先試 claude plugin eval;Strands/AgentCore 系 → Strands Evals + AgentCore dataset runner(preview);框架不明或混用 → promptfoo 包一層 adapter兩份評估都無法在不知道框架的情況下替你選定選型

2.3 建議的執行順序

flowchart TD
    A["第 1 週:釘死格式
項目 1、2、7、8"] --> B["第 2–3 週:讓 evidence 可重放
項目 3、6,補 hook 存 tool 輸出"] B --> C["第 4–6 週:第一批可比較的 eval
項目 4、5、9、10、11"] C --> D["中期:確認 framework,選 runner
項目 15,串 S3 流程項目 12、13"] D --> E["長期:runs 量大後升級 S3 Tables,
CI gate、覆蓋分析"]

第一個里程碑不是「做出一個總分」,而是:一筆真實調查,隔一段時間後仍能取回決策所需的證據,再由工程師把它變成不洩題、可解、可追溯的 eval case。 做到這一點,選哪個評測平台都會變得容易。


Part 3 · Reference查資料(參考細節,用時展開)

以下內容平常不需要通讀,需要具體欄位、路徑、或工具對照時再展開對應區塊。

Incident Record v2 完整欄位建議
schema_version: 2
id: inc-20260901-karpenter-ec2-throttling
title: Karpenter node provisioning slowed by EC2 API throttling
status: draft            # draft | reviewed | promoted | rejected

metadata:
  date: 2026-09-01
  environment: prod
  severity: P2
  services: [karpenter, eks]
  tags: [capacity, aws-api, throttling]

timeline:
  started_at: 2026-09-01T02:05Z
  detected_at: 2026-09-01T02:20Z
  mitigated_at: 2026-09-01T03:40Z
  resolved_at: null

scenario:
  symptom: >
    ...
  context: >
    ...

evidence:
  - id: ev-01
    type: metric
    source: prometheus
    description: ...
    query: ...
    time_range: {start: ..., end: ...}
    snapshot_ref: fixtures/ev-01.json
    snapshot_sha256: ...
    source_retention_until: 2026-09-16
    decision_relevant: true

conclusion:
  status: suspected      # confirmed | likely | suspected | inconclusive | no_issue_found
  summary: >
    ...
  confidence: medium

open_questions: []
actions: []

agent_involvement:
  used: true
  provider: claude-code
  run_ref: null
  outcome: partially_correct   # correct | partially_correct | wrong | gave_up | n/a
  notes: ...

source:
  workspace: karpenter-investigation
  incident_id: INC-482
  ticket_id: DOE-1234
  session_id: null

data_classification:
  customer_data: false
  pii: false
  secrets: false
  redaction_applied: true
  redacted_by: <engineer>

eval_candidate:
  value: high
  reasons: [non_obvious_root_cause, clear_replayable_evidence]

review:
  status: draft
  reviewed_by: null
  reviewed_at: null
Eval Case v2 新增區塊
schema_version: 2
id: eval-karpenter-ec2-throttling-001
source_incident_record: incidents/records/inc-20260901-karpenter-ec2-throttling.yaml
dataset_version: 2026.09.1

replay:
  mode: mocked_tools                 # mocked_tools | evidence_in_prompt | live
  fixtures:
    - {evidence_id: ev-01, path: fixtures/ev-01.json}
  tool_mocks:
    - tool: prometheus_query
      serves: [ev-01, ev-02]
      expect:
        input_match: 'karpenter_.*'

isolation:
  must_not_read: ["STATE.md", "evals/"]

deterministic_checks:
  - {id: read_only, type: tool_not_called, tool_pattern: '^(kubectl_apply|aws_.*_(create|delete|update)|.*_write)$'}
  - {id: checked_karpenter_metrics, type: tool_called, tool: prometheus_query, input_match: 'karpenter_'}
  - {id: found_throttle_signal, type: identifier_found, values: [RequestLimitExceeded, Throttling]}
  - {id: budget, type: budget, max_tool_calls: 25}

rubric_ref: rubrics/incident-investigation.v1.yaml

pass_policy:
  runs_per_case: 3
  deterministic_checks: all_runs
  minimum_mean_rubric_score: 7
  judge: {model: pinned, votes: 3}
  ablation: with_without

review:
  status: draft
  reviewed_by: null
  reviewed_at: null
Grader 字彙 v1(建議的封閉列舉)
Type參數對應市場工具
tool_calledtool, input_match(regex), min, maxClaude plugin eval tool_used
tool_not_calledtool / tool_patterntool_used with min:0 max:0
tool_orderbefore, afterClaude tool_order;AgentCore TrajectoryInOrderMatch
trajectory_containstools: [...], mode: any_order|in_orderAgentCore Trajectory*Match;Vertex in_order_match
output_regexpattern, target: final_output
output_schemajson_schema_ref
budgetmax_tool_calls, max_latency_ms, max_cost_usd
identifier_foundvalues

read_only(對所有 write 類工具套用 tool_not_called)應是每個 SRE case 預設帶上的檢查,不需每案重寫。

S3 儲存佈局(中長期)

三種資料、三種策略:

資料Source of truth格式
Curated dataset(records、golden、rubrics、schemas)git,S3 放版本化不可變快照YAML(人工編輯)→ 正規化 JSON
Evidence 快照S3,content-addressedJSON / JSONL.gz
Runs / traces / gradesS3,append-only原始 OTLP JSONL;衍生分析用 Parquet
s3://<org>-agent-eval/
├── datasets/incident-eval/v=2026.09.1/manifest.json   # 不可變,CI 從 git tag 發佈
├── evidence/sha256=<hash>/blob
├── runs/raw/dt=.../run_id=<ulid>/trace.otlp.jsonl.gz
├── runs/curated/{runs,steps,grades}/dt=.../part-*.parquet
└── reports/<suite>/<timestamp>/report.html|json

發布流程:先寫新 revision / 附件 → 驗證所有引用與雜湊 → 以 If-None-Match: * 建立新 manifest。可變的 latest 指標用 If-Match + ETag,衝突就重讀;正式 run 一律固定 release ID,不讀 latest。

何時升級到 S3 Tables (Iceberg): 短期純 S3 + Parquet + DuckDB/Athena;中期當 runs 超過數萬列、需要 schema evolution 或多人 SQL 查詢時,把 runs/curated/* 換成 S3 Tables;長期用 Iceberg V3 的 variant 型別存半結構化欄位、time travel 做跨版本重算。S3 Tables 只吃 Parquet,JSONL 進不去,所以 raw trace 要留在一般 bucket。

安全與治理: SSE-KMS,evidence 與 raw runs 用不同 key;data_classification 同步寫成 S3 object tag;datasets/ 開 Versioning + Object Lock(governance mode,不要用在 draft);被 golden 引用的 evidence 用 tag 排除 lifecycle 刪除。

Eval / Trace 工具對照表
方案型態Trajectory evalReplay / fixtures多 provider現況
Claude Code plugin evalCLI 內建tool_used/tool_order✅ mock MCP + fixtures + expect: 斷言❌ 只有 Claude Code2026-09 early access;sandbox、3 runs、WITH/W-OUT Δ、CI gate 全都有
Bedrock AgentCore EvaluationsAWS 託管3 個 deterministic matcher + 17 個 builtin judge需自行提供 OTel spansEvaluate API 已 GA(2026-03);dataset evaluation runner 官方文件仍標 public preview,需要 supported framework + CloudWatch Transaction Search
Strands EvalsPython 框架TrajectoryEvaluator、ToolSelectionAccuracy 等用 task callable 可評任何 agent,不限 StrandsApache 2.0;CLI 有 run/validate/report/diagnose/generate
Inspect AI(UK AISI)Python 框架自訂 scorer,含 sandbox✅ 自寫 solverMIT;最中立但需要自己寫程式
PromptfooCLI / YAMLtrajectory:* assertions部分MIT,開源持續維護;2026-03 被 OpenAI 收購(金額未揭露,非 86M——那是估值)
Langfuse觀測 + datasets/experiments靠 traceMIT(ee 除外);可排程匯出 S3;適合當 trace 收集層而非 grader
Kiro Crew:定位澄清

Kiro Crew(2026-08 AWS 開源,Apache 2.0,前身 Amazon 內部的 MeshClaw)是持久化 agent workspace / orchestrator:跨 session 記憶、從糾正中學習、subagents、排程、Slack/Discord 整合、OS-level sandbox、signed audit log。只驅動 kiro-cli,狀態存在 ~/.kiro/crew沒有 dataset 或 evaluation 功能

它是 Workspace Memory 層(Part 1 三層圖中的 State 層)的候選替代品,不是 Evaluation 層的替代品。若公司是 Kiro-only 可以評估導入;否則它違反「agent-neutral」的設計原則。

SRE 場景補充欄位(Grafana / Thanos / EKS)

若主要調查對象是 Grafana alert 根因,dataset 的單位應是「一次告警調查 episode」,用 incident/group ID 關聯同一事故的多條告警,而非每次工具呼叫各自成一筆事件。

答案建議拆三層保存與評分:

內容例子
alert_trigger_explanation規則為何成立「5xx 比例超過閾值」
system_diagnosis系統根因 / 促成因素,或標記證據不足「EC2 API throttling 導致擴容延遲」
impact_and_action可證實的影響與後續行動「production 流量未受影響,僅 scale-out 延遲」

各證據來源建議保存的最小資訊:

來源最小資訊為何重要
Grafana alertrule 版本 hash、query/threshold、evaluate interval、firing/recovery 時間同名 rule 不保證同版本
Prometheus/Thanos完整 PromQL、time/start/end/step、partial_response 與 warnings只存 query 字串不足以固定查詢;partial response 不能當全域健康證據
OpenSearchindex/alias、DSL、固定時間範圍、是否截斷查到零筆可能是範圍問題,不是沒有異常
EKS workloadcluster/namespace/resource UID、關鍵 status/events 快照事故結束後 live 查詢已無法還原當下
Argo Rollouts blue/greenactive/preview selector、promotion/pause 時點區分 preview 異常與真正 production 流量

可參考 HolmesGPT 的 create-eval skill 當作「不洩題」設計原則:用中性資源名稱、關鍵值必須透過查詢才能取得、先驗證線索確實可被發現。其 test_case.yaml 格式(user_prompt/expected_output/before_test/after_test/tags)可直接借用。


Part 4 · Explanation兩份評估教我們的事(分歧的完整分析)

這節回答:兩份評估在哪裡真的吵架、誰的論點更站得住腳、以及各自需要修正的事實。

4.1 分歧不是隨機的,是輸入不同造成的

一份評估拿到了使用者補充的場景資訊(Grafana alert、Thanos、OpenSearch、EKS、每月 10–20 件、agent framework 未知),因此在資料模型細節與治理流程上更深入。另一份沒有這些資訊,因此在市場工具現況與 provider hook 標準上查得更廣。這解釋了兩者的側重差異,但不解釋 1.4 節列出的三個真正分歧——那三個是即使給同樣資訊也會持續存在的判斷差異。

4.2 事實核對:雙方各自要修正的地方

來源敘述核對結果
評估 AAgentCore Evaluations「GA 2026-03」Evaluate API 本體確實 GA,但你們實際會用的 dataset evaluation runner(on-demand / batch)官方文件仍標示 public preview,且要求 supported framework + instrumentation + CloudWatch Transaction Search
評估 APromptfoo「2026-03 被 OpenAI 收購(USD 86M)」收購屬實(2026-03-09),但 86M 是 2025-07 的估值,收購金額未揭露
評估 A未提及 Strands Evals已核實存在:Apache 2.0,可用 task callable 評任何 agent,不限 Strands 框架
評估 A首選 Claude plugin eval建議本身合理,但前提(agent 跑在 Claude Code 上)從未驗證
評估 B「未定位到 Google 官方原文連結,無法逐項核對」白皮書存在:The New SDLC With Vibe Coding,Google,2026-05,51 頁,發佈於 Kaggle,作者 Addy Osmani 等,核心公式 Agent = Model + Harness
評估 B完全未提 Claude Code plugin eval2026-09-11 剛推出的功能,其 mock MCP + fixtures + expect: 斷言正好對應評估 B 自己主張的「靜態 evidence bundle」需求

4.3 三個分歧各自的論點強度

  • Replay 第一步: 主張先做靜態 bundle 的一方論點更站得住腳,因為它具體列出了 mocked tools 隱含的未解規格(query matching、virtual clock、fixture-miss 行為);但另一方對「靜態 bundle 評不到 trajectory」的擔憂也成立。兩者不是互斥,可以按 2.3 節的順序分階段合併。
  • Canonical 位置: 主張物理拆檔 + IAM 角色的一方在「防洩題」上設計更硬,因為 isolation 不再依賴 runner 自律。git-first 的一方在小規模(每月 10–20 件)下更省事。兩者合併後就是 2.2 節第 12 項的流程。
  • 第一個 runner: 這題本質上答不了,因為兩份評估都不知道公司 agent 的執行框架。誰的建議「對」,完全取決於 2.1 節那個問題的答案。

Checkpoint檢查點

回答完再看答案,關起來一次讀完。

看答案(先自己想過再展開)
  1. 為什麼「evidence 只存 query 和 time range」是本次評估中優先級最高的問題?
    因為 log / metric 有 retention,幾個月後同一條 query 可能查不到資料——不是系統沒異常,是資料已經過期。這會讓 golden eval case 變成不可重放,而 dataset 是設計中要求的長期資產。
  2. 為什麼兩個獨立 agent 得出幾乎相同的 P1 清單,比其中一份報告寫得更詳細更重要?
    因為這代表問題是結構性的、可驗證的,不是某一方的主觀偏好。當兩個獨立來源用相同素材收斂到同一組結論時,這組結論的可信度遠高於單一報告的判斷。
  3. 為什麼「先選 eval runner」這一步在確認 agent 框架之前做,是浪費的?
    因為 Claude Code、Strands/AgentCore、其他框架各自對應完全不同的 replay 機制(mock MCP vs. OTel span vs. 自訂 adapter)。選錯框架的工具,後面接的 fixtures、grader 格式都要重做。
  4. git YAML 與 S3 JSON revision,為什麼不是互斥的兩個方案?
    因為它們服務不同階段:git YAML 是人工編輯與 PR review 的介面,S3 上正規化後的 JSON revision 才是 runner 實際讀取、且不可篡改的 canonical 版本。把兩者的角色分清楚,「canonical 位置」的分歧就消失了。
  5. 為什麼 expectedoutcome 列舉(含 insufficient_evidence)比強制填 root_cause 更好?
    因為真實的調查有相當比例會無法確診或是誤報。強制每個 case 都要有 root cause,會讓 agent 在證據不足時傾向亂猜一個看似合理的答案,這正是評測要防止的行為。