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 规划(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]
# 声明 / 证据 / 回归 / 覆盖率(问题 #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。只有当每个所需的关键声明在其自身的证据要求下被证明为 PROVEN 时,技能才被认为是 READY。当声明被声明时,run 的门控条件是基于用例和基于声明的就绪度中较差的,因此二十个绿色的确定性测试,如果有一个未满足的所需 live_e2e 插槽,则不能达到 READY。支持多个声明的实时用例必须携带独立的 per-claim 工件,否则它不会计入任何一个声明。report["capability_readiness"] 保存了 per-claim 的细分。
不变派生的声明(永远不要存根答案)—— 运营指令 2026-09-11
oai-trial 因一个遗漏而失败:要求“没有 PII 到达输出”被悄悄窄化为“没有 PII 字符串到达输出”。每个评估、验证器和资格认证运行都证明了窄化的声明是绿色的,而整数类型的电话号码未受任何影响地通过了。客户在域范围内读取了不变性;我们在机制范围内证明了它。规则:
- 声明是从域不变性派生的,而不是从代码已经执行的操作派生的。 在声明
capability_claims之前,用客户的术语编写不变性(“没有 X 以任何表示形式到达输出”),然后逐字将其声明为关键声明。描述当前行为的声明是存根。 - 值承载声明必须附有表示矩阵。 关于数据值(PII、金钱、标识符、机密)的任何声明必须枚举输入格式允许的表示形式——JSON 字符串/整数/浮点数/科学计数法、CSV 引用、SQL 类型——并且每种表示形式至少包含一个能够失败的对抗性用例。没有表示矩阵的值声明不能被证明为
PROVEN。 - 对于任何转换、过滤或编辑数据值的管道,需要一个名为
value-representation(关键性: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;过期或不完整的豁免将被忽略。没有适用于可执行操作能力的 blanket 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:必须在用例的顶级命令中出现的下游合约命令子字符串列表。当包装器可能伪造成功时使用此选项;例如,声称$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:没有执行任何用例。
失败-关闭退出
run 退出非零,除非就绪度为 READY。对于 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",
"equals_artifact": {"path": "out/detach.json", "json_pointer": "/sessionId"}}
]
}
json_pointer 求值为工件文件中的文字值。比较器包括:
equals:文字匹配(支持null、布尔值、数字、字符串)equals_artifact:跨文件相等性(如上所述)not_equals:反向文字匹配matches_regex:正则表达式type_of:期望的 JSON 类型exists/not_exists:键存在性
每个工件断言必须满足,用例才能在该试验中通过。
轨迹健全性
expected.trajectory_must_include 是一个字符串列表。对于子进程朝向的用例,运行器会记录命令的完整参数列表和任何记录的步骤,并验证轨迹包含所有声明的标记。这可以防止通过运行完全不同的命令来“通过”的用例。
安全约束
expected.safety_constraints 是可选的,是一个对象列表,每个对象带有 type、severity 和 action:
type:no_new_files_outside_temp、no_network_unless_allowed、no_fork_bomb_clustersseverity:error、warn、infoaction:block、flag、monitor
违反 error 级别约束且 action 为 block 的用例会立即失败。违反 warn 级别的用例会被标记并记录。
证据保留
所有收集的证据(stdout、stderr、退出代码、持续时间、工件快照、轨迹标记)都保留在运行器的输出目录中(--output 参数)。对于回归,保留的证据与回归记录链接,以便事后审计。
集成支持
此技能与以下平台集成:
- Claude Code:
"/agentic-evals run fixtures/agentic_eval.json" - Codex:
"/agentic-evals run fixtures/agentic_eval.json" - Cursor:
"/agentic-evals run fixtures/agentic_eval.json"
故障排除
常见问题
问题:run 在 USABLE_WITH_GAPS 上退出非零。
解决方案:这是设计使然。默认情况下,run 门控要求 READY。使用 --report-only 以获取报告而不需要门控。
问题:我的夹具因 trials < 2 而被拒绝。
解决方案:将 trials 增加到至少 2。
问题:我的夹具因没有负面或对抗性用例而被拒绝。 解决方案:添加一个失败的用例(负面或对抗性)。
问题:live_e2e 证据被降级。
解决方案:确保您的实时用例有真实的入口点和独立的回读预言机。
架构决策记录
ADR-001:基于声明的就绪度,而非基于用例计数的
上下文:计数用例无法表达能力是否被真正验证。 决定:就绪度是根据每个声明的能力要求计算的。 后果:更复杂的声明配置,但能保证更准确的评估。
ADR-002:非空性回归证明
上下文:修改期望以匹配已破坏的输出破坏了回归的价值。
决定:regressions verify 重新运行证明命令并确认它失败。
后果:防止无声的退化。
词汇表
- 声明:由夹具声称的关于技能的能力或行为的事实。
- 证据类别:支持声明的证据类型(例如,
deterministic、live_e2e)。 - 连接点:技能中的架构边界,覆盖对于检测回归至关重要。
- 回归:引入前存在但之后被移除的行为。
- 就绪度:对技能所有要求的满足程度。