This file is the agent-facing contract for evaluator agents such as skill-eval.
agentic-evals is a target-driven evaluation repo for testing one skill at a time.
This repo is the source of truth for:
- targets
- suites
- cases
- assertions
- evaluations (AB tests, subjective scoring, vendor comparisons)
- rubrics (scoring dimensions)
- required run artifacts
- report shape
The target skill remains the source of truth for the behavior being tested. The evaluator must not invent new rules when this repo is silent.
If a case cannot be judged reliably from the available evidence, mark it blocked.
The current default target is voice-ai-integration.
This repo supports 2 evaluator run modes:
single-run: the existing one-skill evaluation flowab-urls: a top-level comparison flow that prepares 2 isolated skill variants from URLs and runs the same case set twice
single-run remains the baseline contract.
ab-urls adds a top-level orchestrator artifact shape around 2 variant-local single-run executions.
It does not change case semantics, assertion semantics, or allowed case statuses.
Every evaluator that uses this repo should follow this order:
- Read this file.
- Resolve
run_mode. If omitted, usesingle-run. - Resolve
target_id. If none is provided, use the repo default target. - Read
targets/<target_id>/target.yaml. - Read the selected suite files from
targets/<target_id>/cases/<suite_id>/suite.yaml. - Read each case file referenced by those suites, or the selected case file.
- Create
runs/<run_id>/manifest.json. - If
run_modeisab-urls, prepare 2 variant source workspaces before any case execution. - Create a parent temp directory for isolated per-case workspaces.
- Execute each case in its own fresh isolated workspace.
- Locate the accepted fresh-agent child session for each case.
- Save the accepted child session for each case.
- Render a readable
transcript.mdfrom the accepted child sessions. - Write one
case-results/<case_id>.jsonfile per case. - Write
report.md. - If
run_modeisab-urls, join the 2 variant result sets bycase_id, then writecomparison.jsonand the top-level comparisonreport.md.
Do not start execution before the case set is known.
In ab-urls, both variants must use the exact same resolved case set.
agentic-evals/
├── AGENT.md
├── README.md
├── docs/
│ └── session-evidence.md
├── targets/
│ └── <target_id>/
│ ├── target.yaml
│ └── cases/
│ └── <suite_id>/
│ ├── suite.yaml
│ └── <case_id>.yaml
├── evaluations/
│ ├── ab/
│ ├── comparison/
│ └── subjective/
├── rubrics/
│ └── default.yaml
└── runs/
targets/<target_id>/target.yamldefines the target under test, the entry skill, the skill roots that may be consulted, the default suites, the required run artifacts, and the allowed statuses.targets/<target_id>/cases/<suite_id>/suite.yamldefines a runnable suite and lists its cases.targets/<target_id>/cases/<suite_id>/<case_id>.yamlholds active cases, co-located with their suite.targets/<target_id>/deferred-cases/holds backlog cases that are intentionally not active.docs/session-evidence.mddefines the dual-mode session evidence model for Codex and OpenClaw runtimes.
Deferred cases are not part of the runnable active suite set unless a human explicitly promotes them.
Each single-run must create:
runs/<run_id>/
├── manifest.json
├── case-artifacts/
│ ├── <case_id>/
│ │ ├── accepted-session.json
│ │ └── final-answer.txt
│ └── ...
├── transcript.md
├── case-results/
│ ├── <case_id>.json
│ └── ...
└── report.md
manifest.json must record:
run_modewith valuesingle-runrun_idtarget_idsuite_idstarget_skill_pathstarted_atmodelif availableworkspace_modewith valueisolated-per-casecase_workspace_rootfor the parent temp directory used for per-case workspacesevidence_modewith one of:codex-local-session-storeopenclaw-session-history
notesif the environment is unusual
It is also acceptable to record extra fields such as selected_case_ids, resolved_case_ids, source_workspace, run_state, variant_label, or variant_source_url.
Each case result must record that case's accepted workspace_root.
Each ab-urls top-level run must create:
runs/<ab_run_id>/
├── manifest.json
├── variants/
│ ├── A/
│ │ ├── source-manifest.json
│ │ └── run/
│ │ ├── manifest.json
│ │ ├── case-artifacts/
│ │ ├── transcript.md
│ │ ├── case-results/
│ │ └── report.md
│ └── B/
│ ├── source-manifest.json
│ └── run/
│ ├── manifest.json
│ ├── case-artifacts/
│ ├── transcript.md
│ ├── case-results/
│ └── report.md
├── comparison.json
└── report.md
Rules:
variants/<label>/run/must follow the same artifact shape assingle-run.- the A and B source workspaces must be isolated from each other and must not share the target skill directory
- the 2 variant runs must resolve the same
target.yaml, suite set, and case set - the top-level
ab-urlsrun is responsible only for variant acquisition, variant run coordination, and comparison agentic-evalsremains the only source of truth for case meaning and assertion meaning
runs/<ab_run_id>/manifest.json must record:
run_modewith valueab-urlsrun_idtarget_idsuite_idsselected_case_idswhen applicableresolved_case_idsstarted_atevidence_modevariantswith A/B source URLs and relative artifact pathsnoteswhen the environment is unusual
Each variants/<label>/source-manifest.json should record at least:
labelsource_url- normalized URL parse output such as
repo_url,ref,subdir,ref_type, andcheckout_ref checkout_dirresolved_skill_dirprepared_source_workspacestatuserrorwhen acquisition failed
If a variant URL cannot be parsed, downloaded, checked out, or resolved to a skill root:
- mark that variant as an acquisition failure
- do not judge cases for that variant
- continue the other variant if possible
- mark the top-level A/B run
blockedorpartial - state clearly which side failed and why
If acquisition fails before a variant can run cases, the evaluator may still initialize variants/<label>/run/ as a blocked skeleton with run_state: acquisition-failed.
pass: all required assertions passed with enough evidencefail: one or more required assertions failedblocked: the evaluator could not judge reliably because of environment limits, unclear target behavior, or missing evidence
When a case is blocked, include blocked_reason with one of:
environmentunclear-ruleinsufficient-evidence
Only use statuses allowed by targets/<target_id>/target.yaml.
Preferred evidence:
- the accepted fresh-agent child session captured from the active runtime
- the accepted final answer extracted from that child session
- runtime-native child-session locator metadata
Supported runtime patterns:
- Codex mode:
- spawn with
spawn_agent - locate evidence from
~/.codex/sessions/ - use
~/.codex/state_5.sqliteonly as a locator or tie-breaker when needed
- spawn with
- OpenClaw mode:
- spawn with
sessions_spawn - retrieve evidence from
sessions_history - use returned child session keys or labels as the primary locator
- spawn with
The accepted child session JSON is the authoritative evidence source for the current framework.
transcript.md is a derived human-readable view of that accepted session evidence.
Do not mark a case pass from a generic assistant claim such as "I checked the skill" unless the accepted session evidence shows what was actually read or run.
Static reads by the evaluator are allowed for:
- loading the repo contract
- understanding a case
- understanding the target skill after the fresh-agent run
- mapping failures to likely fix files
Static reads by the evaluator are not enough on their own to mark a dynamic case pass when a fresh-agent run was available.
If the runtime evidence source is unavailable, if the accepted child session cannot be retrieved, or if the session evidence is too coarse to support the assertion, do not judge the case as pass.
Mark the case blocked with:
environmentwhen the runtime evidence source is unavailableinsufficient-evidencewhen the session exists but cannot support a reliable judgment
Invalid attempts can explain notes, but they cannot satisfy assertions or justify a pass.
Each case must run in its own fresh isolated workspace.
Rules:
- Do not execute cases directly in the user's main workspace.
- Create a new case workspace under
case_workspace_rootfor every case. - Apply case
setupmutations only inside that case workspace. - No case may observe filesystem mutations left by a previous case unless the current case setup explicitly recreates them.
- Preserve the accepted case workspace at least until
case-results/<case_id>.jsonandreport.mdare written. Cleanup after reporting is optional. - Judge isolation from observed session evidence, not from fresh-agent self-reporting.
- For both Codex and OpenClaw spawned-subagent evidence, treat per-tool
workdirvalues, resolved read/write paths, and command-derived cwd outputs as authoritative isolation signals. - Do not treat top-level session cwd metadata as authoritative isolation evidence by itself, because spawned child-session metadata may inherit the parent workspace cwd.
- Treat any observed access outside the case workspace as invalid evidence for that attempt.
- If no reliable per-tool workdir, resolved path, or command-derived cwd can be observed, that evidence cannot justify a
pass.
The same isolation policy applies inside ab-urls.
Only the variant-local source workspace for that side may be used to create case workspaces.
Cases may include:
- optional
assert.summaryas a short human-readable description of the protected behavior - optional per-assertion
descriptionto explain the intent of that single check - optional per-assertion
evidence_scopeto hint which accepted artifact file the evaluator should rely on, such asaccepted-session.jsonorfinal-answer.txt
These human-readable fields are the assertion contract. Older requirements should be written in terms of consultation, observed commands, ordering, and final answers, not idealized runtime-native events.
Use this shape for every required or forbidden assertion.
Fields:
- optional
description pass_criteria- optional
fail_signals - optional
evidence_scope
The evaluator must judge the check from the accepted session evidence and the accepted final answer.
Pass only when the available evidence satisfies the pass criteria and does not show any fail signal.
If the accepted session evidence does not support a reliable answer, mark the assertion blocked.
Each case-results/<case_id>.json file must contain:
{
"case_id": "example-case",
"workspace_root": "/tmp/skill-eval/run-123/example-case",
"thread_id": "optional-thread-id-or-null",
"session_path": "openclaw-session://child-session-key or /Users/name/.codex/sessions/...jsonl",
"status": "pass",
"blocked_reason": null,
"assertions": [
{
"summary": "Consulted the top-level skill instructions before answering.",
"status": "pass",
"evidence": [
"case-artifacts/example-case/accepted-session.json#msg-12"
]
}
],
"notes": ["Short explanation."],
"suggested_fix_files": [".agents/skills/<target_id>/SKILL.md"]
}Prefer accepted-session.json#msg-<n> references in evidence when the accepted session artifact is normalized into message records.
If the runtime only exposes stable line-oriented evidence, accepted-session.json#L<line> is also acceptable.
Use transcript.md#L<line> only as a readability aid.
comparison.json for ab-urls should contain:
run_modewith valueab-urlstarget_idstatuswith a top-level run state such ascompleted,partial, orblockedvariant_aandvariant_b, each with:labelsource_urlrun_dir- acquisition and run status summary
summarycases
Each comparison case entry should contain:
case_idstatus_astatus_bcomparisonnotes
Recommended comparison values:
same-passsame-failsame-blockedregressionimprovementbehavior-changeenvironment-divergence
The comparison must join only on the same case_id.
For single-run, report.md must contain exactly these sections:
Run SummaryCase TableFailuresSuggested Next Fixes
For ab-urls, the top-level report.md must contain exactly these sections:
Comparison SummaryVariant TableCase MatrixRegressionsImprovementsSuggested Next Fixes
Keep Suggested Next Fixes to at most 3 items and point to real files.
Evaluations are a higher-level orchestration layer above targets and cases. They define how to run tests (AB, comparison, subjective), not what to test.
| Mode | Purpose | Variants | Output |
|---|---|---|---|
ab |
Compare two versions of the same skill on the same cases | 2 (a, b) | Win/loss/tie per case + rubric scores |
comparison |
Compare different vendors' skills on shared cases | 2+ | Side-by-side rubric scores + ranking |
subjective |
Score a single skill on rubric dimensions beyond pass/fail | 1 | Per-case rubric scores |
Every evaluation file must contain:
eval_id: unique identifiermode: one ofab,comparison,subjectivetitle: human-readable descriptionrubric: path to a rubric YAML file
Mode-specific fields:
abandcomparison:variantsobject with labeled skill paths or target IDsab:target_idandsuites(both variants share the same cases)comparison:shared_cases.from_targetandshared_cases.suitessubjective:target_idandsuites
Each rubric file must contain:
rubric_id: unique identifierdimensions: array of scoring dimensions
Each dimension must contain:
name: short identifier (e.g.,accuracy,safety)description: what the dimension measuresscale: array of valid scores (e.g.,[1, 2, 3, 4, 5])anchors: optional map of score → description for calibration
- Read this file.
- Read the evaluation YAML from
evaluations/<mode>/<eval_id>.yaml. - Read the referenced rubric from
rubrics/. - Resolve the target(s) and case set.
- For each variant: a. Prepare the skill version or skill path in the case workspace. b. Execute each case using the standard case execution chain. c. Collect evidence and judge pass/fail assertions as usual. d. Score each rubric dimension from the accepted session evidence.
- Write variant-specific artifacts under
runs/<run_id>/variants/<variant_label>/. - Write
eval-report.md.
runs/<run_id>/
├── manifest.json
├── variants/
│ └── <variant_label>/
│ ├── case-artifacts/
│ │ └── <case_id>/
│ │ ├── accepted-session.json
│ │ └── final-answer.txt
│ ├── case-results/
│ │ └── <case_id>.json
│ └── transcript.md
├── eval-report.md
└── report.md
manifest.json must additionally record:
eval_ideval_modevariant_labelsrubric_id
Each variant's case-results/<case_id>.json extends the standard case result with:
{
"case_id": "example-case",
"variant": "a",
"status": "pass",
"assertions": [ ... ],
"rubric_scores": {
"accuracy": 4,
"completeness": 5,
"doc_consultation": 3,
"safety": 5,
"flow_adherence": 4
},
"rubric_notes": {
"doc_consultation": "Consulted README but skipped quickstarts.md."
}
}eval-report.md must contain exactly these sections:
Evaluation Summary— mode, variants, case count, rubric usedScoring Table— each case × each dimension, columns per variantHead-to-Head— (AB and comparison only) win/loss/tie counts per dimensionDetailed Findings— per-case narrative of notable differences or quality issuesRecommendations— at most 3 actionable items pointing to real files
For subjective mode, omit the Head-to-Head section.
- Score each dimension independently from the accepted session evidence.
- Use the rubric anchors for calibration. A score of 3 means "meets the anchor description for 3."
- If evidence is insufficient to score a dimension, record
nulland explain inrubric_notes. - Rubric scores are independent of pass/fail assertions. A case can
passall assertions but score low oncompleteness, orfailan assertion but score high onaccuracy. - For AB and comparison modes, score each variant independently before comparing. Do not let one variant's score influence another's.