agentic-evals 是做什麼的?
當一次性的簡易冒煙測試過於薄弱,且任務需要針對某個技能或代理工作流程提供可重複、基於證據的評估時,請使用此技能。
當前範圍
此初始套件為基於命令的案例提供了一個確定性設備執行器。它會多次執行每個案例,記錄 stdout/stderr、退出狀態與持續時間,檢查明確的期望值,並輸出機器可讀的準備度摘要。
此工具僅證明已宣告的設備行為。它無法證明語義正確性、真實服務整合、LLM 判斷品質或發佈就緒性,除非設備命令本身實際執行了這些真實路徑。
使用方式
./run.sh run fixtures/agentic_eval.json
./run.sh run fixtures/agentic_eval.json --output /tmp/agentic-evals-report.json
./run.sh audit-skills ../ --output /tmp/agentic-evals-baseline-gap-report.json
./run.sh scaffold-fixture ../some-skill --output ../some-skill/fixtures/agentic_eval.json
./run.sh apply-scaffolds ../ --write --output /tmp/agentic-evals-apply-scaffolds.json
# requirements-to-journey planning over live discovery (issue #1629)
./run.sh plan-journeys --fixture fixtures/agentic_eval.json \
--requirements requirements.json \
--interaction-inventory discovery/discovery-inventory.json \
--state-graph discovery/state-graph.json \
--output journey-plan.json [--scaffold-output fragment.json] [--report-only]
# claim / evidence / regression / coverage (issues #1445-#1448)
./run.sh regressions audit ../ --output /tmp/agentic-evals-regressions.json
./run.sh regressions show . && ./run.sh regressions verify .
./run.sh coverage audit ../ --output /tmp/agentic-evals-coverage.json
./run.sh coverage show .
基於聲明的準備度 (#1445)
確定性測試證明的是機制;真實端到端測試證明的是能力。 一堆通過的確定性案例絕不能看起來像是從未實際演練過的即時能力的準備度。因此,準備度是按每個已宣告的能力聲明計算,然後聚合計算的——而不是根據案例數量。
宣告 capability_claims(與 claims 的證明範圍敘述分開,以便 v2 設備保持有效)。每個支援某項聲明的案例會標記自身:
{
"capability_claims": [
{"id": "ask.roundtable.mixed_provider", "description": "...",
"criticality": "critical",
"evidence_required": {"deterministic": true, "live_e2e": true}}
],
"cases": [
{"name": "roundtable-live", "type": "positive", "evidence_class": "live_e2e",
"supports_claims": ["ask.roundtable.mixed_provider"],
"command": ["bash", "run.sh", "..."],
"expected": {"exit_code": 0, "artifacts": [{"path": "out/join.json", "json_pointer": "/settled", "equals": true}]}}
]
}
證據類別:deterministic、property_or_fuzz、fault_injected_deterministic、live_e2e、adversarial_live_e2e、human_evaluation。每個聲明的判定結果:PROVEN、PARTIALLY_PROVEN、BLOCKED_EXTERNAL、FAILED、NOT_ESTABLISHED。只有當每個必需的 critical 聲明都根據其自身的證據要求被驗證為 PROVEN 時,該技能才被視為 READY。當宣告了聲明時,run 的門檻會採用基於案例和基於聲明的準備度中較差的那個結果,因此即使有二十個通過的確定性案例,只要有一個必備的 live_e2e 要求未被滿足,就無法達到 READY。支援多個聲明的即時案例必須為每個聲明攜帶獨立的證據產物,否則它對任何一個聲明都不算數。report["capability_readiness"] 會保存每個聲明的細分結果。
從不變量推導的聲明(絕不偽造答案)— 營運方針 2026-09-11
oai-trial 失敗於一個遺漏:要求「不得有任何 PII 到達輸出」被悄然縮小為「不得有任何 PII 字串到達輸出」。每個評估、驗證器和資格測試都證明這個縮小後的聲明是綠燈,而整數類型的電話號碼卻未經處理地通過了。客戶是以領域範圍解讀不變量的;我們卻是以機制範圍證明它。規則:
- 聲明是從領域不變量推導的,而不是從程式碼已經做的事情推導。 在宣告
capability_claims之前,先用客戶的話寫下不變量(「在任何表示形式中,不得有任何 X 到達輸出」),然後直接宣告它——一字不差——作為關鍵聲明。描述當前行為的聲明就是一個贗品。 - 對於承載值的聲明,表示形式矩陣是強制性的。 任何關於資料值(PII、金錢、識別碼、機密)的聲明都必須列舉輸入格式所允許的表示形式——JSON 字串/整數/浮點數/科學記號、CSV 引號、SQL 類型——並為每種表示形式提供至少一個對抗性案例,每個案例都必須能夠失敗。沒有表示形式矩陣的值相關聲明不能被證明為
PROVEN。 - 任何轉換、過濾或編校資料值的管線都需要一個名為
value-representation(criticality: critical)的覆蓋縫隙。 審計必須顯示在該縫隙處有一個有能力的防護。 - 獨立檢查器不得共用生產者的資料生成器。 驗證器的設備必須包含轉換器自身設備所沒有的表示形式,否則獨立性僅是名義上的。
- 當出現表示形式漏洞時,將其記錄在
fixtures/regressions.json(事故 → 保留的防護)和value-representation縫隙中——同類的遺漏必須能夠在此之後永遠被檢測到。
反漏洞合約拒絕的是自我服務的管線;這些規則拒絕的是自我服務的假設——那些測試套件誠實、對抗、多輪試驗卻仍然盲目,因為每個設備都共享一個關於資料形狀的不可見前提。
真實端到端證據契約 (#1446)
evidence_class 不是從包含 run.sh 或 curl 的命令中推斷出來的。宣告為即時類別(live_e2e/adversarial_live_e2e)的案例會經過結構性的資格審查,如果符合以下情況則會被降級(絕不靜默接受):
- 以
fixtures//stub/mocked輸入作為邊界權威來餵養自身; - 未到達實質性的生產入口點;
- 沒有獨立的讀回預言機(
expected.artifacts、readback: true或stdout_excludes)——僅憑退出碼加上命令自身的成功訊息不算證明;或者 - 為
$ask瀏覽器tau-dag/compete處理器聲明即時證據,但沒有--execute以及來自瀏覽器/提供者執行產物的讀回,例如node-receipt.json、response.md、response.meta.json、browser-tab-lifecycle.json、execution-status.json、roundtable-summary.md或compete-scorecard.json。僅編譯/預檢的$ask案例屬於確定性機制證據,絕非live_e2e。
被降級的案例會變成 fault_injected_deterministic(在真實路徑上注入故障)或 deterministic,並且報告會記錄 evidence_disqualifiers。一個僅由 BLOCKED_EXTERNAL 案例滿足的必備即時槽位會使該聲明保持未 PROVEN 狀態。
豁免是明確且有期限的。一個聲明可以攜帶 exemptions,指定 evidence_class、reason_code、justification、owner 和 expires。有效的豁免會在報告中顯示(exempt_evidence),但絕不能使聲明變成 PROVEN;已過期或不完整的豁免會被忽略。沒有通用的 eval_not_required 可以滿足一個可執行的營運能力。
事故 → 保留的回歸測試 (#1447)
即時失敗會成為 fixtures/regressions.json(agentic_evals.regressions.v1)中的永久性證據。每條記錄都將事故連結到它所威脅的聲明和縫隙,指明保留的防護案例(retained_case / retained_fixture),並攜帶一個 fail_before_fix.proof_command。
regressions show <skill>/regressions audit <root>報告:未受保護的回歸(保留案例遺失/重新命名)、從未被證明(可能空洞)的回歸、過時的即時證明、已退役的回歸,以及沒有對應回歸映射的開放事故。regressions verify <skill>重新執行每個證明命令並確認該防護確實會對有問題的行為失敗(退出碼非零)——這是一個非空洞性證明,而不是一個自我報告的旗標。如果任何活躍回歸的防護無法證明在修復前會失敗,它會以非零退出碼退出。
透過修改評估期望值來匹配有問題的輸出,從而修復一個錯誤——這正是非空洞性證明所要捕捉的。退役一個回歸需要一個 retirement 原因。
基於風險的覆蓋充分性 (#1448)
計算案例數量是可以作弊的。coverage audit/coverage show 會針對每個已宣告的 seam 提出問題:在該縫隙處,是否有至少一個案例能夠檢測到回歸,並且其證據類別滿足該縫隙風險所要求的?宣告 seams 時需要提供 seam_id、seam_type、criticality 和 required_evidence;並為案例標記 seams。只有當一個案例列出了該縫隙並且攜帶了一個可以失敗的預言機時,它才算覆蓋了該縫隙——一個單純的 exit 0 正向案例屬於 weak_only,不計入。審計會報告已覆蓋/未覆蓋的縫隙、僅弱覆蓋、即時與確定性覆蓋、已映射的事故回歸,以及優先級最高的下一步評估。覆蓋率(宣告了有能力的防護)和新鮮度(即時證明是最新的)是兩個不同的維度;執行器在此處不會執行縫隙案例。
設備契約
{
"version": 2,
"skill": "example-skill",
"trials": 3,
"proof_scope": "fixture wiring smoke",
"claims": {
"proves": "the declared command exits with the expected status",
"does_not_prove": "semantic correctness, live service behavior, or full skill readiness"
},
"cases": [
{
"name": "happy-path",
"type": "positive",
"command": ["echo", "success"],
"expected": {
"exit_code": 0,
"stdout_contains": ["success"]
}
}
]
}
每個案例都必須宣告:
nametype:positive、negative或adversarialcommand:非空的 argv 列表expected.exit_code
可選的期望值:
expected.stdout_containsexpected.stderr_containsmust_exercise:必須出現在案例頂層命令中的下游合約命令子字串列表。當 wrapper 可能偽造成功時使用;例如,一個聲稱具備$ticket/$project-watchdog路由能力的評估必須包含"skills/ticket/run.sh feature",而不僅僅是一個印出OK的輔助腳本。
反漏洞合約(失敗關閉)
如果一個技能評估設備是自我服務的確定性管線而非真實世界證明,則會在載入時被拒絕(非零退出碼,不執行)。要通過,技能設備必須:
- 設定
trials>= 2(單次試驗不算證據); - 至少包含一個
negative或adversarial案例(全正向的設備是自我服務的); - 至少包含一個真實世界案例:
"real_world": true,其命令執行一條真實路徑(該技能的run.sh/ 一個腳本 / 即時 HTTP / 一個測試執行器),並且不以fixtures/樁輸入餵養自身; - 不含任何微不足道的
echo/常數案例(這些什麼都證明不了)。
拒絕訊息會列出每一項違規。這可以防止一個評估雖然輕鬆通過,但對於該技能是否真的能運作卻毫無證明力。
合規層級("eval_tier": "compliance")
一個守護合規管線階段的設備會宣告 "eval_tier": "compliance",然後執行器會在基本合約之上強制執行強合約(營運方針 2026-08-12,「這是一條合規管線,必須要健壯地強化」)。除非滿足以下條件,否則此類設備將被拒絕:
- 嚴格多數的案例是
adversarial/negative(超過一半,而不是剛好一半——正向控制項是少數); - 至少有一個案例是非確定性的:其命令每次執行都透過
--samples、--seed或 shell 的$RANDOM來取樣新的輸入(使用固定鍵值的探測腳本名稱不計入); - 每個非確定性案例都指定
--samples>= 50,因此每個階段的覆蓋率每次執行都有數百到數千個斷言,目標是跨其模式達到每個階段約 1000 個斷言。
該宣告不能被悄悄放寬:合規管線自身的設備設定了層級,因此移除它以繞過門檻本身就算是一個回歸。tests/test_compliance_tier_gate.py 將每條規則固定下來,以防止其被削弱。
兩個誠實宣告的豁免可以繞過門檻——對於真實的技能評估永遠無效:
"eval_kind": "runner_selftest"——測試此執行器本身的設備或作為文件範例。"eval_kind": "scaffold"——由scaffold-fixture/apply-scaffolds所發出的機械性初始姿勢設備,審計仍會將其標記為需要真實案例。
準備度映射
準備度僅針對必需的案例進行評分("required": false 可將案例排除)。一個必要的 BLOCKED 案例無法達到 READY:未滿足的前提條件是證據的缺失,而非成功的證據。
READY:每個必要案例都通過了每一次試驗。USABLE_WITH_GAPS:至少通過了一次試驗,且至少有一次未通過。NOT_READY:試驗已執行,但沒有任何必要案例完全通過。NOT_ESTABLISHED:沒有執行任何案例。
失敗關閉的退出
除非準備度為 READY,否則 run 會以非零退出碼退出。一個在 USABLE_WITH_GAPS 時仍以 0 退出的執行器會讓外部的 CI 工作流在案例失敗的情況下變成綠燈,而這正是此門檻存在的全部原因。當你需要報告而不想要門檻時,請傳遞 --report-only。
案例結果
每個案例報告一個 outcome,因為這些結果對門檻來說意義不同:
| 結果 | 意義 |
|---|---|
PASS | 每次試驗都滿足所有期望值 |
FAIL | 存在缺陷、超時,或者某次試驗留下了子行程 |
BLOCKED | 前提條件未滿足;透過 blocked_when_stdout_contains 宣告標記 |
NOT_TESTED | 沒有執行任何試驗 |
產物斷言
stdout 子字串匹配無法表達「這兩個收據指向同一個會話」或「執行結束後沒留下任何東西」。宣告 expected.artifacts:
"expected": {
"exit_code": 0,
"artifacts": [
{"path": "out/session.json", "json_pointer": "/sessionId",
"equals_artifact": {"path": "out/detach.json", "json_pointer": "/sessionId"}},
{"path": "out/attach.json", "json_pointer": "/sessionId"}
…
[此處省略,原文已截斷]