iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
AI Engineering

《30 天從零拆解 AI Agent:從 Tool Calling 到多 Agent 協作》系列 第 29

【AI Agent 29】Eval-first:不要先加複雜架構,先驗證你在解決什麼問題

  • 分享至 

  • xImage
  •  

前面 28 天,我們一路把 Agent Harness 拆成約 20 種機制。

到這裡,很容易進入一種「架構焦慮」。

Agent 表現不好時,第一個反應常常是:

是不是該加 Planning?
是不是該加 Memory?
是不是該加 Subagent?
是不是該換 Graph?
是不是該多一個 Judge?
是不是該換更強 Model?

這些都可能是答案。

但也可能全部不是。

真正更應該先問的是:

它到底失敗在哪裡?

如果這個問題沒有先回答,所有架構修改都只是猜。

這就是 Day 29 的主題:

Eval-first。

不是「Agent 做完之後補一套 Eval」。

而是:

在你決定 Architecture 之前,就先定義 Failure、Dataset、Rubric、Baseline 和 Done Bar。

今天也會參考我另外做的 EvalGrill:

https://github.com/hardness1020/EvalGrill

EvalGrill 的核心定位很直接:

Turn real AI agent failures into trustworthy evals, then prove the eval works.

它不是另一個 Agent Eval Dashboard。

它處理的是更前面的一層:

你拿什麼證據決定「哪個 Agent 比較好」?


第一個錯誤:有 Eval = Eval-first

很多團隊其實已經有 Eval。

流程長這樣:

Build Agent
↓
加 Planning
↓
加 Memory
↓
加 Subagent
↓
開始覺得系統太複雜
↓
最後補 50 個測試

這叫:

Eval-later。

Eval-first 的順序相反:

Collect Failures
↓
Define Failure Modes
↓
Build Dataset
↓
Design Rubric
↓
Validate Eval
↓
Measure Baseline
↓
Change One Mechanism
↓
Measure Again

差別很大。

因為 Eval-later 是:

用 Eval 幫已經做出的架構找理由。

Eval-first 是:

用 Eval 決定下一個架構值不值得做。


Architecture 應該從 Failure Mode 長出來

這其實是整個 Awesome Agent Architecture 系列最重要的一條線。

每個 Mechanism 都應該回答:

它在解哪個可觀察 Failure?

例如:

Agent 忘記前面重要限制
→ Context / Memory

一直重複失敗 Tool Call
→ Recovery / Budget

Child Agent 污染 Parent Context
→ Subagent Boundary

Deploy 前不能自動執行
→ Permission / Approval

Model 說 Done 但其實沒完成
→ Verification

已知流程每次都重新問 Model
→ Graph

如果你說:

我要加 Memory。

但 Dataset 裡根本沒有 Memory-related Failure。

那它可能只會增加:

  • Token
  • Retrieval Noise
  • Stale State
  • Maintenance

沒有 measurable gain。


Eval-first 的第一步不是 Dataset

很多 Eval 文章會從:

準備 100 個 Prompt。

開始。

我不建議。

更前面的第一步是:

Failure Taxonomy。

也就是先把「Agent 不好」拆成具體失敗。

例如一個 Research Agent:

F1
漏掉關鍵來源

F2
引用不存在來源

F3
把來源中的不確定內容寫成 Fact

F4
沒有比較互相衝突的 Evidence

F5
回答核心問題之外寫很多無關內容

這比:

Quality 不好

有用太多。


EvalGrill Phase 1:Analyze

EvalGrill 把第一階段叫:

Analyze

它會產生:

failure-taxonomy.yaml
evaluation-dimensions.yaml

核心思想是:

每個 Failure Mode 都要有 Evidence。

Evidence 可以來自:

  • 真實 Failed Output
  • User Complaint
  • Support Ticket
  • Production Trace
  • Domain Rule
  • Human Review
  • Incident
  • Known Safety Constraint

不要憑空列:

Helpfulness
Correctness
Relevance
Professionalism

這些詞本身沒有錯。

但它們太容易變成 Generic Checklist。

Eval-first 更關心:

真實 Agent 到底曾經在哪裡摔過?


Failure-first 和 Quality-first 的差別

Quality-first:

我們希望 Agent:
Helpful
Relevant
Correct
Concise

Failure-first:

真實 Failure:
Agent 在缺少 Order ID 時自己猜了一個。

後者直接可以推導:

Dataset Case
缺少 Order ID

Expected Behavior
先 clarification

Veto
不得執行任何 Order Mutation

這樣 Eval 才會對 Architecture 有指導力。


Severity 也要先定義

不是所有 Failure 都一樣重要。

例如:

回答稍微太長

和:

退款錯訂單

不能只是同一張表裡:

-1

所以 Failure Taxonomy 需要 Severity。

例如:

P0
Safety / destructive side effect

P1
Core task incorrect

P2
Missing required information

P3
Style / efficiency

Severity 會影響:

  • Dataset Coverage
  • Rubric Weight
  • Veto
  • Release Gate

第二步:Dataset 是用來「逼 Failure 出現」

Dataset 不是收集很多正常 Request。

它應該是:

針對 Failure Mode 設計的壓力測試。

如果 Failure 是:

Agent 在缺少必要資訊時亂猜

Dataset 就應該故意:

不給必要資訊

而不是每個 Case 都把資料準備得非常完整。

如果 Failure 是:

Memory 污染

Dataset 應該放:

舊偏好
+
新的相反要求

看 Agent 會不會選錯 Priority。


EvalGrill Phase 2:Dataset

EvalGrill 的第二階段會產生:

dataset.jsonl
dataset-card.md

它的核心不是:

多生一些 Cases。

而是:

每一個 Case 都要能對應到前面的 Failure Mode。

也就是 Coverage 要能追蹤:

Failure F1
被哪些 Tasks 測?

Failure F2
被哪些 Tasks 測?

這會讓 Dataset 從一堆 Example,變成 Detection Surface。


High-severity Failure 沒有 Task Coverage,是 Eval Bug

這一點非常重要。

假設 Failure Taxonomy 有:

F1
Unauthorized external send
Severity: Critical

結果 Dataset 裡完全沒有測。

那不管整體 Score 是:

98%

都沒有太大意義。

因為最重要的 Failure 根本沒被碰到。

EvalGrill 的 Validate Phase 會專門抓這類問題:

High-severity failure mode with zero task coverage.

也就是:

先測 Eval 是否有能力抓 Failure,再拿它測 Agent。


第三步:Rubric 不是「請 Judge 評 1 到 5 分」

有 Dataset 後,下一個常見錯誤是:

請評估這個 Answer 的 Quality。
1 到 5 分。

這個 Rubric 幾乎沒有 Diagnostic Value。

因為當 Score = 3 時,你不知道:

  • 哪裡錯
  • 怎麼修
  • 要改 Model 還是 Harness
  • 哪個 Failure Mode 被觸發

Eval-first 的 Rubric 必須能映射回 Failure。


Observable Anchor

例如不要寫:

回答應該具有深度。

可以寫:

回答必須:
1. 引用至少兩個來源
2. 說明來源如何支持主要結論
3. 如果來源衝突,明確指出衝突

這叫 Observable Anchor。

Judge 不需要「感受品質」。

它只需要檢查:

有沒有出現可以觀察的 Evidence?


EvalGrill Phase 3:Rubric

EvalGrill 的第三階段會產生:

rubric.yaml
judge-protocol.yaml
human-review-guide.md

它特別強調:

  • Checkable Criteria
  • Observable Anchors
  • Vetoes
  • Judge Protocol

這些 Mechanism 的目的都是同一個:

讓「評分」從 Impression 變成可重複的檢查。


Deterministic Check 不要交給 LLM Judge

這是非常實用的一條規則。

假設 Criteria 是:

Output 必須是 Valid JSON。

最差做法:

Judge Model:
這看起來像合法 JSON 嗎?

直接:

json.loads(output)

就好。

或者:

File 必須存在

就直接檢查 File。

Database State 必須 updated

就直接查 Database。

LLM Judge 應該留給真正需要語意判斷的項目。

這和整個系列的 Graph Engineering 原則完全一致:

Deterministic 的事情留給 Code。


Veto:某些 Failure 不能被平均分救回來

假設 Agent:

回答完整
+5

語氣很好
+3

有引用來源
+5

但 Fabricate 了一個 Citation

如果最後平均:

8.7 / 10

這個 Score 沒有意義。

有些 Failure 應該:

一旦觸發
→ 整個 Episode Fail

這就是 Veto。

例如:

  • Fabricated Citation
  • Unauthorized Side Effect
  • Secret Leakage
  • Wrong Recipient
  • Wrong Order Mutation
  • Required Approval 被繞過

EvalGrill 特別把 Veto 當成 Portable EvalPack 的一部分,而不是假設執行平台本身會有同樣語意。


第四步:先 Validate Eval,再相信 Agent Score

這是 Eval-first 最容易漏掉的一層。

我們一直在說:

Agent 可能不可靠。

但 Judge 也可能不可靠。

Rubric 也可能有 Bug。

Dataset 也可能有洞。

所以:

Eval 本身也要被 Eval。


EvalGrill Phase 4:Validate

EvalGrill 的 Validate Phase 會檢查幾種典型 Eval Defect。

例如:

  1. High-severity Failure 沒有 Coverage:代表 Dataset 有洞。
  2. Rubric 太模糊:沒有 Observable Anchor。
  3. 本來能用 Script 判斷,卻交給 Judge:增加不必要 Variance。
  4. Zero-tolerance Rule 沒有 Veto:Critical Failure 可能被平均分掩蓋。
  5. Judge 多次執行結果不一致:Rubric / Judge 不穩。
  6. Pairwise Order Sensitivity:Candidate A / B 換順序,Judge Verdict 改變。
  7. Judge 和 Human Label 不一致:甚至可能被 Reward-hacking Candidate 騙過。

這個思路非常重要:

Eval 不是 Ground Truth,它也是一個需要驗證的 Detection System。


Judge Calibration

假設我們有 20 個 Candidate Output。

Human 已經標:

Pass
Fail
Fail
Pass
...

再讓 Judge 跑。

就可以比較:

Judge vs Human

例如觀察:

  • Coverage
  • False Failure Rate
  • Alignment
  • Disagreement

如果 Judge 常常把 Human 認為 Fail 的 Case 判成 Pass,那它沒有資格當 Release Gate。


Stability 也是 Eval Quality

同一個 Output 讓 Judge 跑五次:

PASS
PASS
FAIL
PASS
FAIL

這不是 Agent Variance。

這是 Grader Variance。

所以 Judge 也需要測:

run-to-run disagreement

同樣地,Pairwise Judge 還要測:

A vs B
B vs A

如果結果只因 Candidate 順序改變就不同,代表存在 Position Bias。


Reward Hacking:Agent 也會學會討好 Eval

一旦 Eval 成為 Optimization Target,就會出現 Goodhart's Law:

Metric 變成 Target 後,Metric 就容易失效。

例如 Judge 喜歡:

  • 長答案
  • 大量引用
  • 特定格式
  • 很自信的語氣

Agent 可能學會:

讓 Judge 覺得好。

而不是:

真的把 Task 做好。

所以 Validate Eval 時最好放入:

Reward-hacking Candidate。

也就是:

看起來很會拿分,但其實不符合真實 Outcome 的 Output。

如果 Judge 被騙,Eval 本身還沒準備好。


Baseline:沒有 Baseline,就不知道 Complexity 值不值得

Eval-first 的下一步不是直接做 Best Agent。

先建立最簡單 Baseline。

例如:

Baseline A
Model + Tool Loop

先跑:

Success: 64%
Cost: $0.11
Latency: 12s

接著你想加 Planning。

變成:

Variant B
Model + Tool Loop + Planning

結果:

Success: 66%
Cost: $0.21
Latency: 19s

這時你才有資格問:

+2% 值不值得接近 2 倍成本?

沒有 Baseline,Architecture Complexity 沒有 Opportunity Cost。


每次只改一個 Mechanism

這是 Eval-first 最重要的實驗紀律。

不要一次:

換 Model
+
加 Planning
+
加 Memory
+
改 Prompt
+
加 Judge

然後看到:

64% → 78%

最後不知道誰做的。

比較好的方式:

Baseline
↓
+ Planning
↓
Measure

Baseline
↓
+ Memory
↓
Measure

Baseline
↓
+ Verification
↓
Measure

這就是 Ablation。

也是 Awesome Agent Architecture 一直強調:

每一層 Harness 都應該證明自己的價值。


Failure Cluster 比 Overall Score 更重要

假設:

Overall:
82% → 84%

看起來很小。

但拆 Failure:

Tool misuse
90% → 91%

Clarification
42% → 76%

Memory conflict
88% → 87%

這時真正的故事不是:

+2%。

而是:

新機制大幅改善 Clarification,但可能輕微傷害 Memory Conflict。

這會直接影響下一個 Architecture Decision。

所以 Eval Dashboard 最重要的不是一個大數字。

而是:

Failure Mode Breakdown。


一個實際的 Eval-first 架構流程

假設你要做一個 Coding Agent。

不要先說:

我想做 Multi-Agent。

先收 Failure。

例如:

F1
沒有讀完整 Context 就開始改

F2
改完沒有跑 Tests

F3
明明 Test Fail 還說 Done

F4
讀太多不相關檔案

F5
對簡單 Task 過度 Planning

接著設 Dataset。


Dataset

Task A
需要先理解 3 個 module 才能修改

Task B
簡單 one-line fix

Task C
Patch 看起來合理但 test 必然 fail

Task D
Large repo,只有 2 files relevant

然後 Rubric。


Rubric

R1
修改前是否取得必要 Evidence

R2
是否執行 required test

R3
Test fail 時不得 declare completion

R4
Relevant-file ratio

R5
Simple task 不得超過指定 turn budget

接著跑 Baseline。


Baseline

Plain Agent Loop

你發現:

F1: 70%
F2: 45%
F3: 38%
F4: 76%
F5: 92%

現在 Architecture Direction 很清楚。

最先該修的是:

Verification

不是 Memory。

不是 Subagent。

不是 Graph。

因為 F2 / F3 是最大 Failure Cluster。

這就是 Eval-first 真正的價值:

它讓 Architecture Roadmap 從 Evidence 長出來。


Planning 應該什麼時候加?

只有當 Eval 顯示:

Complex Task decomposition failure

Planning 才有明確 Hypothesis。

例如:

Agent 在 5-step Task 中常漏 Step 4。

那可以測:

Without Planning
vs
With Planning

如果提升明顯,留下。

如果沒有:

刪。


Memory 應該什麼時候加?

只有當 Dataset 有:

Cross-session information loss
Repeated user preference failure
Project fact retrieval failure

Memory 才是合理 Intervention。

如果 Task 全部單 Session 完成:

Memory 很可能只是 Complexity Tax。


Subagent 應該什麼時候加?

不是因為 Task 看起來很大。

而是 Eval 顯示:

Context interference
Responsibility confusion
Independent subproblems
Parallel opportunity

才值得加。

否則多 Agent 很可能只增加:

  • Token
  • Coordination
  • Merge
  • Verification

Graph 應該什麼時候加?

當 Failure 來自:

固定流程被跳過

例如:

Deploy before Review
Complete before Verification
Send before Approval

那 Graph / coded edge 非常適合。

因為這不是 Reasoning Failure。

而是:

Deterministic Control 沒有被 Encode。


更強 Model 應該什麼時候換?

這也是 Eval-first 很容易幫你省錢的一點。

如果 Failure 是:

Permission bypass

換更強 Model 不應該是第一解。

如果 Failure 是:

Tool timeout

也不是。

如果 Failure 是:

複雜 Evidence synthesis consistently poor

才可能是 Model Capability 問題。

Eval-first 可以把:

Model Problem
vs
Harness Problem

分開。


Observability 是 Eval-first 的資料來源

Day 21 我們談 Observability。

Production 中:

Trace
User Correction
Tool Failure
Permission Denial
Handoff

都可以變成 Failure Evidence。

所以理想的 Loop 是:

Production
↓
Observability
↓
Failure Evidence
↓
EvalGrill / Eval Design
↓
Dataset
↓
Regression Eval
↓
Architecture Change
↓
Deploy
↓
Observe Again

這是一個真正閉環。


EvalGrill 在這條 Loop 裡的位置

很多 Eval Platform 解決的是:

怎麼執行 Eval?

例如:

  • Dataset Runner
  • Trace Viewer
  • Scorer
  • Dashboard

EvalGrill 解的是更前面:

這個 Eval 本身是否值得信?

可以簡化成:

Real Failure Evidence
↓
EvalGrill
↓
Validated EvalPack
↓
Braintrust / LangSmith / Phoenix / 自己的 Runner
↓
Agent Comparison

EvalGrill 不是取代 Eval Platform。

它更像 Eval Design Layer。


EvalPack:把 Eval 當一個 Artifact

EvalGrill 的一個重要想法是把整套 Eval Design 變成 Portable Artifact。

包含:

Failure Taxonomy
Dataset
Dataset Card
Rubric
Judge Protocol
Human Review Guide
Coverage
Calibration
Validation Status

這比:

eval.py

更完整。

因為真正決定 Score 意義的,往往不是 Runner。

而是:

這些 Cases 為什麼存在,Criteria 怎麼定義,Judge 是否可信。


Portable Eval 的價值

如果同一個 Eval 定義:

在 Platform A
82%

Platform B
84%

你至少知道它們是在測同一套 Failure。

如果每個 Platform 都重新人工設定:

  • Dataset
  • Rubric
  • Veto
  • Judge Prompt

比較就會失去一致性。

所以 EvalGrill 會把 Veto / Essential Gate 也一起編譯到 Export。

核心原則是:

Eval semantics 應該屬於 Eval,不應該偷偷依賴某個 Dashboard。


CI 不應該只 Test Agent Code,也要 Test Eval

EvalGrill 本身包含:

  • Schema Validation
  • Referential Integrity
  • Coverage Audit
  • Judge Calibration
  • Exporter Contract Test
  • Acceptance Run

這其實是在實踐一個很重要的觀念:

Eval 是 Production Code。

如果 Eval 決定:

這個版本能不能 Deploy。

那 Eval Bug 的風險和 Agent Bug 一樣大。


Eval-first 不等於 Benchmark-first

這兩個概念也要分開。

Benchmark-first 容易變成:

我們先追一個公開分數。

Eval-first 是:

我們先定義產品真正在乎的 Failure。

公開 Benchmark 可以使用。

但不一定代表你的真實 Product。

例如:

SWE-bench

很適合測 Coding Capability。

但它不一定測:

  • 你的 Production Permission
  • 你的 Internal Tool
  • 你的 User Clarification
  • 你的 Domain Safety
  • 你的 Cost Constraint

所以 Internal Eval 還是必要。


Eval-first 最終會讓 Architecture 變小

這件事看起來反直覺。

很多人以為 Eval-first 會增加很多工程成本。

短期是。

但長期它會幫你刪掉很多不需要的 Harness。

例如:

Memory
沒有 measurable gain
→ Remove

Subagent
成功率 +1%,Cost +70%
→ Remove

Planner
只對 Hard Task 有效
→ Conditional Enable

Verification
降低 False Completion 40%
→ Keep

Graph Gate
完全消除 Approval Bypass
→ Keep

最後得到的系統不是功能最多。

而是:

每一層都有證據存在的理由。


常見錯誤設計

  1. 做完 Agent 才補 Eval:Architecture 已經變成 Sunk Cost。
  2. 先寫 Generic Rubric:無法映射真實 Failure。
  3. Dataset 只有正常 Happy Path:最重要的 Failure 根本不會被觸發。
  4. Judge Criteria 太模糊:分數不可重現。
  5. Script 能判斷的事情交給 Judge:白白增加 Variance 和 Cost。
  6. Critical Failure 沒有 Veto:Safety Violation 被其他高分平均掉。
  7. Eval 自己沒有 Calibration:Judge Bug 被當成 Agent Bug。
  8. 一次改五個 Mechanism:成功也不知道是誰的功勞。
  9. 只看 Overall Score:Failure Cluster 被平均值藏掉。
  10. 為了分數一直加 Harness:Complexity Increase 沒有 Cost / Latency / Reliability Trade-off。

第一版 Eval-first Workflow

如果明天要開始一個新的 Agent,我會先做這個:

Step 1:收集 10 到 20 個真實 Failure

來源:

  • Failed Runs
  • Complaints
  • Trace
  • Domain Rules
  • Human Review

Step 2:建立 Failure Taxonomy

每個 Failure 至少有:

id
description
severity
evidence
expected_behavior

Step 3:每個高風險 Failure 至少做一個 Task

不要先追求 1,000 個 Dataset Case。

先追求:

Critical Failure 有 Coverage。

Step 4:Rubric 只寫 Observable Criteria

可以 Script 的就 Script。

需要語意的才 Judge。

Zero-tolerance Rule 加 Veto。

Step 5:Validate Eval

測:

  • Coverage
  • Vague Criteria
  • Deterministic-vs-Judge
  • Missing Veto
  • Judge Stability
  • Position Bias
  • Human Alignment

Step 6:跑最小 Baseline

例如:

Model + Tool Loop

不要一開始就堆滿所有 Harness。

Step 7:找最大 Failure Cluster

只提出一個 Architecture Hypothesis。

例如:

False Completion 太高
→ 加 Verification

Step 8:只改一個 Mechanism

再跑同一套 Eval。

Step 9:同時看 Quality、Cost、Latency

如果:

成功率 +2%
成本 +80%

不一定值得。

Step 10:保留有證據的 Layer,刪掉沒有證據的 Layer

這才是 Eval-first Architecture。


Day 29 重新看前 28 天

如果用 Eval-first 回頭看整個系列:

Agent Loop
不是因為 Agent 都該有 while
而是需要多輪 Action / Observation

Permission
不是因為安全是流行詞
而是 Side Effect 需要 Enforcement

Planning
不是因為複雜 Task 看起來需要 Plan
而是 Dataset 顯示 Decomposition Failure

Subagent
不是因為 Multi-Agent 很酷
而是 Context / Responsibility 真的需要隔離

Memory
不是因為 Agent 應該記住一切
而是跨 Session Failure 真的存在

Graph
不是因為 Workflow Framework 好用
而是固定 Control Flow 被 Model 跳過

Evaluation
不是最後一個 Feature
而是前面所有 Mechanism 的存在理由

這其實把整個系列重新串起來了。


Eval-first 的真正定義

最後可以把 Eval-first 壓成四句話。

1.先定義 Failure,再定義 Architecture。
2.先證明 Eval 能抓到 Failure,再相信 Score。
3.一次只改一個 Mechanism,否則沒有 Attribution。
4.沒有 measurable value 的 Harness Layer,應該被刪掉。


今天的結論

Agent Engineering 最容易犯的錯,不是 Architecture 太簡單。

而是:

在不知道真正 Failure 是什麼之前,就開始解 Solution。

Eval-first 把順序反過來:

Failure
↓
Eval
↓
Baseline
↓
Hypothesis
↓
Architecture Change
↓
Regression

而不是:

Architecture Idea
↓
Build
↓
Build More
↓
最後想辦法證明它有效

最重要的原則只有一句:

不要先問「Agent 還能加什麼」,先問「哪個失敗值得被下一個 Mechanism 修掉」。

這也是我做 EvalGrill 的原因。

不是為了再做一個 Eval Runner。

而是把:

Failure Taxonomy
Dataset
Rubric
Judge Calibration
Coverage
Validation

變成一個可以被檢查的 Eval Artifact。

只有當 Eval 值得相信,我們才有資格用它決定:

下一個 Agent Architecture 到底該加什麼,或更重要的,該刪什麼。

完整系列與程式碼範例收錄於


上一篇
【AI Agent 28】DeepSeek Harness 架構拆解:如果連 Agent Loop 都只是一個 Plugin,Harness 會變成什麼?
系列文
《30 天從零拆解 AI Agent:從 Tool Calling 到多 Agent 協作》29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言