agentv 5.0.0-next.1 → 5.2.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +239 -53
  2. package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js → agentv-provider-AYXH7WLW-6YZKZ7PS.js} +2 -2
  3. package/dist/{artifact-writer-QD52FC56.js → artifact-writer-SN6UNL5G.js} +15 -8
  4. package/dist/{chunk-GZJMODLW.js → chunk-3S6A2RKR.js} +45880 -30542
  5. package/dist/chunk-3S6A2RKR.js.map +1 -0
  6. package/dist/{chunk-6Q56CEXV.js → chunk-3X357HS4.js} +7900 -8985
  7. package/dist/chunk-3X357HS4.js.map +1 -0
  8. package/dist/{chunk-6JVM4GJI.js → chunk-46K2OET3.js} +187 -80
  9. package/dist/chunk-46K2OET3.js.map +1 -0
  10. package/dist/{chunk-IJEZFZJR.js → chunk-7BGERE6L.js} +2 -2
  11. package/dist/chunk-7BGERE6L.js.map +1 -0
  12. package/dist/{chunk-UG4JHZYM.js → chunk-ALVZQUZP.js} +670 -1427
  13. package/dist/chunk-ALVZQUZP.js.map +1 -0
  14. package/dist/{chunk-RCIEHFQ2.js → chunk-PEUTJS7B.js} +3 -3
  15. package/dist/{chunk-5H446C7X.js → chunk-QMRVH5ZP.js} +2 -8
  16. package/dist/{chunk-IBI7A5RP.js → chunk-T4AD3H3Y.js} +3444 -2251
  17. package/dist/chunk-T4AD3H3Y.js.map +1 -0
  18. package/dist/cli.js +8 -9
  19. package/dist/cli.js.map +1 -1
  20. package/dist/dashboard/assets/{index-D5_8DE_B.js → index-DNgf3qJ2.js} +1 -1
  21. package/dist/dashboard/assets/index-D_bokML8.css +1 -0
  22. package/dist/dashboard/assets/index-r_jSJmlw.js +121 -0
  23. package/dist/dashboard/index.html +2 -2
  24. package/dist/{dist-KJ6PELQY.js → dist-DEPJOMCA.js} +74 -60
  25. package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js → docker-workspace-NNK4Z6FR-QRTIG6TM.js} +3 -3
  26. package/dist/{exec-MYPAJJP7-C5HD5WG5.js → exec-4HFFRQ3B-AXDMJNLJ.js} +3 -3
  27. package/dist/index.js +8 -9
  28. package/dist/{interactive-2WMVAASS.js → interactive-36ZNMQB2.js} +13 -29
  29. package/dist/interactive-36ZNMQB2.js.map +1 -0
  30. package/dist/skills/agentv-bench/SKILL.md +38 -34
  31. package/dist/skills/agentv-bench/agents/analyzer.md +6 -6
  32. package/dist/skills/agentv-bench/agents/comparator.md +4 -5
  33. package/dist/skills/agentv-bench/agents/grader.md +4 -4
  34. package/dist/skills/agentv-bench/references/autoresearch.md +3 -3
  35. package/dist/skills/agentv-bench/references/description-optimization.md +2 -2
  36. package/dist/skills/agentv-bench/references/environment-adaptation.md +10 -10
  37. package/dist/skills/agentv-bench/references/eval-yaml-spec.md +51 -30
  38. package/dist/skills/agentv-bench/references/migrating-from-skill-creator.md +4 -4
  39. package/dist/skills/agentv-bench/references/subagent-pipeline.md +13 -12
  40. package/dist/skills/agentv-eval-migrations/SKILL.md +33 -0
  41. package/dist/skills/agentv-eval-migrations/references/breaking-changes.md +1012 -0
  42. package/dist/skills/agentv-eval-review/SKILL.md +6 -3
  43. package/dist/skills/agentv-eval-review/scripts/lint_eval.py +1 -1
  44. package/dist/skills/agentv-eval-writer/SKILL.md +380 -246
  45. package/dist/skills/agentv-eval-writer/references/{config-schema.json → config.schema.json} +6 -5
  46. package/dist/skills/agentv-eval-writer/references/custom-evaluators.md +23 -18
  47. package/dist/skills/agentv-eval-writer/references/eval.schema.json +9852 -0
  48. package/dist/skills/agentv-eval-writer/references/python-helpers.md +8 -8
  49. package/dist/skills/agentv-eval-writer/references/rubric-evaluator.md +21 -22
  50. package/dist/skills/agentv-trace-analyst/SKILL.md +4 -4
  51. package/dist/templates/.agentv/targets.yaml +41 -40
  52. package/dist/{ts-eval-loader-RE43OAGX-AMRCUKBZ.js → ts-eval-loader-OMG2JBHP-OP5RR7A3.js} +5 -4
  53. package/package.json +19 -4
  54. package/dist/chunk-6JVM4GJI.js.map +0 -1
  55. package/dist/chunk-6Q56CEXV.js.map +0 -1
  56. package/dist/chunk-76FOHROU.js +0 -96
  57. package/dist/chunk-76FOHROU.js.map +0 -1
  58. package/dist/chunk-GZJMODLW.js.map +0 -1
  59. package/dist/chunk-HSHTTN6C.js +0 -565
  60. package/dist/chunk-HSHTTN6C.js.map +0 -1
  61. package/dist/chunk-IBI7A5RP.js.map +0 -1
  62. package/dist/chunk-IJEZFZJR.js.map +0 -1
  63. package/dist/chunk-LRULMAAA.js +0 -1711
  64. package/dist/chunk-LRULMAAA.js.map +0 -1
  65. package/dist/chunk-R3CXYNTN.js +0 -1238
  66. package/dist/chunk-R3CXYNTN.js.map +0 -1
  67. package/dist/chunk-UG4JHZYM.js.map +0 -1
  68. package/dist/chunk-VQ2ZO7XJ.js +0 -2098
  69. package/dist/chunk-VQ2ZO7XJ.js.map +0 -1
  70. package/dist/chunk-XALGXSKB.js +0 -21
  71. package/dist/chunk-XALGXSKB.js.map +0 -1
  72. package/dist/dashboard/assets/index-BVMrdN8a.js +0 -119
  73. package/dist/dashboard/assets/index-DZWXfWsv.css +0 -1
  74. package/dist/esm-NNMQYIKT.js +0 -32
  75. package/dist/esm-R77SNOF5.js +0 -65
  76. package/dist/esm-RVQPUGWH.js +0 -1207
  77. package/dist/esm-RVQPUGWH.js.map +0 -1
  78. package/dist/esm-TTEMJEVV.js +0 -933
  79. package/dist/esm-TTEMJEVV.js.map +0 -1
  80. package/dist/esm-ZADQ4XQH-QUFGGZL4.js +0 -924
  81. package/dist/esm-ZADQ4XQH-QUFGGZL4.js.map +0 -1
  82. package/dist/exec-MYPAJJP7-C5HD5WG5.js.map +0 -1
  83. package/dist/getMachineId-bsd-HSK5LZMG.js +0 -41
  84. package/dist/getMachineId-bsd-HSK5LZMG.js.map +0 -1
  85. package/dist/getMachineId-darwin-4DP6CCJV.js +0 -41
  86. package/dist/getMachineId-darwin-4DP6CCJV.js.map +0 -1
  87. package/dist/getMachineId-linux-44LJ5UJB.js +0 -33
  88. package/dist/getMachineId-linux-44LJ5UJB.js.map +0 -1
  89. package/dist/getMachineId-unsupported-NVK6IATM.js +0 -24
  90. package/dist/getMachineId-unsupported-NVK6IATM.js.map +0 -1
  91. package/dist/getMachineId-win-YZ36S7VA.js +0 -43
  92. package/dist/getMachineId-win-YZ36S7VA.js.map +0 -1
  93. package/dist/interactive-2WMVAASS.js.map +0 -1
  94. package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js +0 -9
  95. package/dist/otlp-json-file-exporter-RY63S3IG-PZBQPVYY.js.map +0 -1
  96. package/dist/skills/agentv-eval-writer/references/eval-schema.json +0 -17295
  97. package/dist/skills/agentv-eval-writer/references/experiment-schema.json +0 -278
  98. package/dist/src-76ISS3LH.js +0 -1733
  99. package/dist/src-76ISS3LH.js.map +0 -1
  100. package/dist/ts-eval-loader-RE43OAGX-AMRCUKBZ.js.map +0 -1
  101. /package/dist/{agentv-provider-AYXH7WLW-NJRC6UQX.js.map → agentv-provider-AYXH7WLW-6YZKZ7PS.js.map} +0 -0
  102. /package/dist/{artifact-writer-QD52FC56.js.map → artifact-writer-SN6UNL5G.js.map} +0 -0
  103. /package/dist/{chunk-RCIEHFQ2.js.map → chunk-PEUTJS7B.js.map} +0 -0
  104. /package/dist/{chunk-5H446C7X.js.map → chunk-QMRVH5ZP.js.map} +0 -0
  105. /package/dist/{dist-KJ6PELQY.js.map → dist-DEPJOMCA.js.map} +0 -0
  106. /package/dist/{docker-workspace-ZJ2ESVBI-6UDETQII.js.map → docker-workspace-NNK4Z6FR-QRTIG6TM.js.map} +0 -0
  107. /package/dist/{esm-NNMQYIKT.js.map → exec-4HFFRQ3B-AXDMJNLJ.js.map} +0 -0
  108. /package/dist/{esm-R77SNOF5.js.map → ts-eval-loader-OMG2JBHP-OP5RR7A3.js.map} +0 -0
@@ -3,7 +3,7 @@ name: agentv-eval-writer
3
3
  description: >-
4
4
  Write, edit, review, and validate AgentV EVAL.yaml / .eval.yaml evaluation files.
5
5
  Use when asked to create new eval files, update or fix existing ones, add or remove test cases,
6
- configure graders (`llm-grader`, `code-grader`, `rubrics`), review whether an eval is correct or complete,
6
+ configure graders (`llm-rubric`, `script`), review whether an eval is correct or complete,
7
7
  convert between EVAL.yaml and evals.json using `agentv convert`, or generate eval test cases
8
8
  from chat transcripts (markdown conversation or JSON messages).
9
9
  Do NOT use for creating SKILL.md files, writing skill definitions, or running evals —
@@ -13,20 +13,36 @@ description: >-
13
13
  # AgentV Eval Writer
14
14
 
15
15
  Comprehensive docs: https://agentv.dev
16
+ Promptfoo parity matrix: https://agentv.dev/docs/reference/promptfoo-parity/
16
17
 
17
18
  ## Authoring Principle
18
19
 
19
20
  Treat YAML as the canonical portable model. Prefer authoring `.eval.yaml` / `EVAL.yaml` first, then use TypeScript helpers, Python scripts, or executable graders only when they lower to the same fields or when the evaluation logic must actually run code.
20
21
 
21
- Eval files define what is tested: prompts, datasets, assertions, and task fixtures.
22
- Experiment files define how those evals run: targets, setup, scripts, timeout,
23
- sandbox, suite selection, and repeat-run policy. Use `experiments/*.yaml` for
24
- committed run configurations. In eval YAML, keep `tests[]` as the atomic eval
25
- definition. In experiment YAML, reference eval suites with `suites[]` and select
26
- suite-local tests with `select.test_ids[]`.
22
+ Eval files define what is tested and how it runs: prompts, datasets, assertions,
23
+ task fixtures, top-level `target`, and suite run controls. Use field-local file
24
+ refs such as `tests: file://...`, `prompts: file://...`, `default_test:
25
+ file://...`, and `environment: file://...`. String-valued `tests` and string
26
+ entries inside `tests[]` are raw-case refs for direct paths, directories, and
27
+ globs. Run several full eval suites directly with CLI multi-file selection and
28
+ tags. Use scoped `run:` on individual tests only for `threshold`, `repeat`,
29
+ `timeout_seconds`, and legacy `budget_usd`; keep target selection at top-level
30
+ `target` or CLI `--target`, put suite budget caps under
31
+ `evaluate_options.budget_usd`, authored concurrency under
32
+ `evaluate_options.max_concurrency`, suite repeat policy under
33
+ `evaluate_options.repeat`, coding-agent testbed setup under `environment`,
34
+ provider environment overrides under `env`, and lifecycle hooks under
35
+ `extensions`.
27
36
 
28
37
  Use `@agentv/sdk` for TypeScript helper imports. Do not use `@agentv/eval` for new evals, examples, scaffolds, or skill guidance; it was a deprecated compatibility package and has been removed from this repository.
29
38
 
39
+ ## Authoring Checklist
40
+
41
+ - Put grading criteria in `assert`, not in test-level `criteria`. Plain assertion strings become an `llm-rubric` grader.
42
+ - Prefer plain assertion strings for semantic checks when the default rubric grader can judge them. Use `type: llm-rubric` for structured criteria, custom prompts, custom grader targets, or assertion-level transforms, and `type: script` when grading must execute code.
43
+ - Write `expected_output` as a golden/reference answer the target could have produced. Do not write criteria, scoring instructions, or "the agent should..." rubric prose there.
44
+ - For historical or repo-state evals, materialize the repo through a pinned `environment` setup recipe. Mentioning a SHA only in prompt prose is not enough because the agent needs an actual checkout to inspect.
45
+
30
46
  ## Evaluation Types
31
47
 
32
48
  AgentV evaluations measure **execution quality** — whether your agent or skill produces correct output when invoked.
@@ -45,7 +61,7 @@ agentv convert evals.json
45
61
  agentv eval evals.json
46
62
  ```
47
63
 
48
- The converter maps `prompt` → `input`, `expected_output` → `expected_output`, `assertions` → `assertions` (`llm-grader`), and resolves `files[]` paths. The generated YAML includes TODO comments for AgentV features to add (workspace setup, code graders, rubrics, required gates).
64
+ The converter maps `prompt` → `input`, `expected_output` → `expected_output`, and Agent Skills `assertions` → AgentV `assert` (`llm-rubric` checks), and resolves `files[]` paths. The generated YAML includes TODO comments for AgentV features to add (environment setup, script graders, rubrics, required gates).
49
65
 
50
66
  After converting, enhance the YAML with AgentV-specific capabilities shown below.
51
67
 
@@ -77,21 +93,19 @@ JSON messages:
77
93
 
78
94
  **Multi-turn format** (when context from prior turns matters):
79
95
  ```yaml
96
+ prompts:
97
+ - - role: user
98
+ content: "My name is Alice"
99
+ - role: assistant
100
+ content: "Nice to meet you, Alice!"
101
+ - role: user
102
+ content: "What's my name?"
103
+
80
104
  tests:
81
105
  - id: multi-turn-context
82
- criteria: "Agent remembers prior context"
83
- input:
84
- - role: user
85
- content: "My name is Alice"
86
- - role: assistant
87
- content: "Nice to meet you, Alice!"
88
- - role: user
89
- content: "What's my name?"
90
106
  expected_output: "Your name is Alice."
91
- assertions:
92
- - type: rubrics
93
- criteria:
94
- - Correctly recalls the user's name from earlier in the conversation
107
+ assert:
108
+ - Correctly recalls the user's name from earlier in the conversation
95
109
  ```
96
110
 
97
111
  **Guidelines:** preserve exact wording in `expected_output`; aim for 5–15 tests per transcript; pick exchanges that test different capabilities.
@@ -100,44 +114,96 @@ tests:
100
114
 
101
115
  ```yaml
102
116
  description: Example eval
103
- execution:
104
- target: default
117
+ target: default
118
+
119
+ prompts:
120
+ - "{{ prompt }}"
105
121
 
106
122
  tests:
107
123
  - id: greeting
108
- criteria: Friendly greeting
109
- input: "Say hello"
124
+ vars:
125
+ prompt: "Say hello"
110
126
  expected_output: "Hello! How can I help you?"
111
- assertions:
112
- - type: rubrics
113
- criteria:
114
- - Greeting is friendly and warm
115
- - Offers to help
127
+ assert:
128
+ - Greeting is friendly and warm
129
+ - Offers to help
116
130
  ```
117
131
 
118
132
  ## Eval File Structure
119
133
 
120
- **Required:** `tests` (array or string path)
121
- **Optional:** `name`, `description`, `version`, `author`, `tags`, `license`, `requires`, `execution`, `suite`, `workspace`, `assertions`, `input`
134
+ **Required:** `tests` (array or string raw-case path) or `scenarios`
135
+ **Optional:** `name`, `description`, `experiment`, `version`, `author`, `tags`, `license`, `requires`, `target`, `targets`, `prompts`, `default_test`, `timeout_seconds`, `evaluate_options`, `threshold`, `suite`, `environment`, `env`, `extensions`, `assert`
122
136
 
123
137
  **Test fields:**
124
138
 
125
139
  | Field | Required | Description |
126
140
  |-------|----------|-------------|
127
141
  | `id` | yes | Unique identifier |
128
- | `criteria` | yes | What the response should accomplish |
129
- | `input` | yes | Input to the agent (string/object shorthand or full message array) |
142
+ | `vars` | yes when the prompt needs row data | Prompt-template variables for this row |
130
143
  | `expected_output` | no | Gold-standard reference answer (string shorthand or full message array) |
131
- | `assertions` | no | Graders: deterministic checks, rubrics, and LLM/code graders |
132
- | `execution` | no | Per-case execution overrides |
133
- | `workspace` | no | Per-case workspace config (overrides suite-level) |
144
+ | `assert` | yes | Graders: deterministic checks, `llm-rubric` checks, script graders, or plain string rubric criteria |
145
+ | `execution` | no | Per-case grader/default overrides such as `skip_defaults`; target selection belongs in top-level `target` or CLI `--target` |
146
+ | `environment` | no | Per-case coding-agent testbed config (overrides suite-level) |
134
147
  | `metadata` | no | Arbitrary key-value pairs passed to setup/teardown scripts |
135
148
  | `conversation_id` | no | Thread grouping |
136
149
 
150
+ ## Prompt Templates and Vars
151
+
152
+ Use top-level `prompts` plus `tests[].vars` for the Promptfoo-compatible canonical
153
+ input shape. Shared data defaults belong in `default_test.vars`; per-test
154
+ `vars` override those defaults by key. AgentV renders every prompt with each
155
+ test's merged vars, then expands the run across prompts, targets, tests, and
156
+ repeat attempts.
157
+
158
+ ```yaml
159
+ description: Prompt matrix example
160
+ target: default
161
+
162
+ prompts:
163
+ - id: support-chat
164
+ label: Support chat
165
+ file: ./prompts/support-chat.json
166
+ - id: terse
167
+ label: Terse
168
+ prompt: "Answer for {{ audience }} in one sentence: {{ question }}"
169
+
170
+ default_test:
171
+ vars:
172
+ audience: users
173
+ category: support
174
+
175
+ tests:
176
+ - id: password-reset
177
+ vars:
178
+ question: How do I reset my password?
179
+ expected_output: Password reset guidance
180
+ assert:
181
+ - Gives correct password reset guidance
182
+ - id: admin-access
183
+ vars:
184
+ audience: admins
185
+ question: How do I revoke a user's access?
186
+ expected_output: Access revocation guidance
187
+ assert:
188
+ - Gives safe access revocation guidance
189
+ ```
190
+
191
+ Prompt templates can use `{{ name }}` or `{{ vars.name }}` placeholders. Use
192
+ top-level names when matching Promptfoo-style prompt templates; use
193
+ `{{ vars.name }}` when explicit namespacing is clearer.
194
+
195
+ Do not author direct input fields in normal eval YAML. `tests[].input` and
196
+ top-level `input` are removed; write simple task text as a prompt template such
197
+ as `"{{ input }}"` or `"{{ vars.input }}"` with
198
+ `tests[].vars.input: "Summarize X"`.
199
+
200
+ `input_files` is also direct-input convenience sugar. In prompt-template suites,
201
+ model file-backed context as vars containing file paths or `file://` references,
202
+ then render those vars from the prompt template next to the input.
203
+
137
204
  **Shorthand forms:**
138
- - `input` (string, including YAML block scalars) expands to `[{role: "user", content: "..."}]`
139
- - `input` (object without a top-level `role`) expands to `[{role: "user", content: {...}}]`
140
- - top-level `role` is reserved for message objects; use `{role, content}` when you mean a message, or nest payload role data under another key
205
+ - Prompt entries can be strings, message arrays, file references, or prompt objects.
206
+ - Put chat/system/user messages in `prompts`, not in `tests[].input`.
141
207
  - `expected_output` (string/object) expands to `[{role: "assistant", content: ...}]`
142
208
  - Use these canonical field names on disk; keep the wire format `snake_case`
143
209
 
@@ -148,7 +214,38 @@ tests:
148
214
 
149
215
  **JSONL format:** One test per line as JSON. Optional `.yaml` sidecar for shared defaults. See `examples/features/basic-jsonl/`.
150
216
 
151
- **Environment variables:** All string fields support `${{ VAR }}` interpolation. Missing vars resolve to empty string. Works in eval files, external case files, and workspace configs. `.env` files are loaded automatically.
217
+ **Environment variables:** Use `{{ env.VAR }}` templates in authored config. Missing vars resolve to empty string. Works in eval files, external case files, and environment configs. `.env` files are loaded automatically.
218
+
219
+ ## Output Transforms
220
+
221
+ Use Promptfoo-compatible `transform` when the target output needs shaping before
222
+ grading. Common cases include converting a `ContentFile` such as an `.xlsx`
223
+ spreadsheet into text before an `llm-rubric` grader runs.
224
+
225
+ ```yaml
226
+ prompts:
227
+ - "{{ input }}"
228
+
229
+ default_test:
230
+ options:
231
+ transform: file://scripts/transforms/xlsx-to-csv.ts
232
+
233
+ tests:
234
+ - id: spreadsheet-output
235
+ vars:
236
+ input: Generate the spreadsheet report
237
+ assert:
238
+ - Output contains the transformed spreadsheet text including the revenue rows
239
+ ```
240
+
241
+ Transform placement:
242
+
243
+ - `default_test.options.transform` applies to every test unless overridden.
244
+ - `tests[].options.transform` overrides the inherited default transform for one test.
245
+ - Assertion-level `transform` applies only to that grader, after the test/default transform.
246
+
247
+ Do not author `preprocessors` or deprecated Promptfoo `postprocess` in current
248
+ eval YAML. Use `transform` at the point that needs the shaped output.
152
249
 
153
250
  ## Metadata
154
251
 
@@ -165,26 +262,30 @@ requires:
165
262
  agentv: ">=0.30.0"
166
263
  ```
167
264
 
168
- ## Suite-level Input
265
+ ## Shared Prompt Context
169
266
 
170
- Prepend shared input messages to every test (like suite-level `assertions`). Avoids repeating the same prompt or instruction in each test:
267
+ Put shared prompt instructions in top-level `prompts` and shared data in
268
+ `default_test.vars`:
171
269
 
172
270
  ```yaml
173
- input: |
174
- Read AGENTS.md before answering.
175
- Explain tradeoffs clearly.
271
+ prompts:
272
+ - - role: system
273
+ content: |
274
+ Read AGENTS.md before answering.
275
+ Explain tradeoffs clearly.
276
+ - role: user
277
+ content: "{{ question }}"
176
278
 
177
279
  tests: ./cases.yaml
178
280
 
179
- # cases.yaml — each test only needs its own query
281
+ # cases.yaml — each raw row supplies vars.question, or a compatibility input row
180
282
  # - id: test-1
181
- # criteria: ...
182
- # input: "User question here"
283
+ # assert:
284
+ # - ...
285
+ # vars:
286
+ # question: "User question here"
183
287
  ```
184
288
 
185
- Effective input: `[...suite input, ...test input]`. Skipped when `execution.skip_defaults: true`.
186
- Accepts the same formats as test `input`: string/block scalar, structured object without a top-level `role`, single message object, or full message array. Use the full message array only when you need multiple messages or file/image content blocks.
187
-
188
289
  ## Tests as String Path
189
290
 
190
291
  Point `tests` to an external file instead of inlining:
@@ -197,76 +298,126 @@ tests: ./cases.yaml # relative to eval file dir
197
298
 
198
299
  The external file can be YAML (array of test objects) or JSONL.
199
300
 
200
- ## Assertions Field
301
+ ## Assert Field
201
302
 
202
- `assertions` defines graders at the suite level or per-test level. It is the canonical field for all graders:
303
+ `assert` defines graders at the suite level or per-test level. It is the canonical authored field for all graders:
203
304
 
204
305
  ```yaml
205
- # Suite-level (appended to every test)
206
- assertions:
306
+ # Mix exact checks with rubric shorthand when both matter.
307
+ assert:
207
308
  - type: is-json
208
309
  required: true
209
310
  - type: contains
210
311
  value: "status"
312
+ - Correctly answers the user's question
313
+ - Explains the reasoning clearly
211
314
 
212
315
  tests:
213
316
  - id: test-1
214
- criteria: Returns JSON
215
317
  input: Get status
216
- # Per-test assertions (runs before suite-level)
217
- assertions:
318
+ assert:
218
319
  - type: equals
219
320
  value: '{"status": "ok"}'
321
+ - Explains what the status means
220
322
  ```
221
323
 
222
- ## How `criteria` and `assertions` Interact
324
+ Plain strings in `assert` are rubric criteria and are the preferred shape for
325
+ qualitative agent behavior. Use deterministic assertions (`contains`, `regex`,
326
+ `is-json`, `equals`) only for exact machine-verifiable outputs, and script graders
327
+ when the check must inspect files, run commands, or validate structured state.
328
+ Do not add a separate test-level `criteria` field. Legacy evals that still use
329
+ `criteria` without explicit `assert` are loaded as a plain-string assertion for
330
+ compatibility, but new evals should author the assertion directly.
223
331
 
224
- `criteria` is a **data field** it describes what the response should accomplish. It is **not** a grader. How it gets evaluated depends on whether `assertions` is present:
332
+ For repo-state evals, combine a pinned checkout, a golden answer, and assertion
333
+ shorthand:
225
334
 
226
- | Scenario | What happens | Warning? |
227
- |----------|-------------|----------|
228
- | `criteria` + **no `assertions`** | Implicit `llm-grader` runs automatically against `criteria` | No |
229
- | `criteria` + **`assertions` with only deterministic graders** (contains, regex, etc.) | Only declared graders run. `criteria` is **not evaluated**. | Yes — warns that no grader will consume criteria |
230
- | `criteria` + **`assertions` with a grader** (`llm-grader`, `code-grader`, `rubrics`) | Declared graders run. Graders receive `criteria` as input. | No |
231
-
232
- ### No assertions → implicit llm-grader
335
+ ```yaml
336
+ environment:
337
+ type: host
338
+ workdir: ./agentv
339
+ setup:
340
+ command:
341
+ - bash
342
+ - ./scripts/materialize-repo.sh
343
+ - ./agentv
344
+ - https://github.com/EntityProcess/agentv.git
345
+ - 5e3c8f46d80fe66b1a75659e4fd94e38a7e09215
346
+ cwd: "."
347
+
348
+ prompts:
349
+ - "{{ task }}"
233
350
 
234
- The simplest path. `criteria` is automatically evaluated by the default `llm-grader`:
351
+ tests:
352
+ - id: verification-learning-capture
353
+ vars:
354
+ task: |
355
+ The eval harness has prepared ./agentv at the commit before the
356
+ verification guidance was added.
357
+
358
+ Decide what durable repo change should be made and explain why.
359
+ expected_output: |
360
+ The durable repo change is to update .agents/verification.md with the
361
+ reusable verification workflow lessons. AGENTS.md already routes this
362
+ class of work to .agents/verification.md, so no extra AGENTS.md edit is
363
+ needed unless that routing is missing.
364
+ assert:
365
+ - The answer recommends updating .agents/verification.md rather than leaving the learning only in PR comments or private evidence.
366
+ - The answer uses the pinned ./agentv checkout to verify the AGENTS.md routing.
367
+ - The answer preserves the historical commit SHA as context.
368
+ ```
369
+
370
+ ## Assertions and Reference Data
371
+
372
+ When `assert` is defined, **only the declared graders run**. For
373
+ semantic checks, add plain rubric strings. If you need a custom LLM prompt or
374
+ grader target, declare `llm-rubric` explicitly:
235
375
 
236
376
  ```yaml
377
+ prompts:
378
+ - "{{ prompt }}"
379
+
237
380
  tests:
238
- - id: simple-eval
239
- criteria: Assistant correctly explains the bug and proposes a fix
240
- input: "Debug this function..."
241
- # No assertions → default llm-grader evaluates against criteria
381
+ - id: mixed-eval
382
+ vars:
383
+ prompt: "Debug this function..."
384
+ assert:
385
+ - Explains why the bug happens
386
+ - type: contains
387
+ value: "fix"
242
388
  ```
243
389
 
244
- ### assertions present no implicit grader
390
+ `expected_output` is passive reference data. It is available to graders through
391
+ `{{expected_output}}` and the script stdin payload, but it does not create an
392
+ implicit LLM grading call by itself.
245
393
 
246
- When `assertions` is defined, **only the declared graders run**. If you want an LLM grader alongside deterministic checks, declare it explicitly:
394
+ **Common mistake:** putting rubric prose in `expected_output` instead of an
395
+ assertion:
247
396
 
248
397
  ```yaml
398
+ prompts:
399
+ - "{{ prompt }}"
400
+
249
401
  tests:
250
- - id: mixed-eval
251
- criteria: Response is helpful and mentions the fix
252
- input: "Debug this function..."
253
- assertions:
254
- - type: llm-grader # must be explicit when assertions is present
255
- - type: contains
256
- value: "fix"
402
+ - id: bad-example
403
+ vars:
404
+ prompt: "What is 2+2?"
405
+ expected_output: The assistant should explain why the answer is 4. # reference answer field, not a grader
257
406
  ```
258
407
 
259
- **Common mistake:** defining `criteria` with only deterministic graders. The criteria will be ignored and a warning is emitted:
408
+ Write this as:
260
409
 
261
410
  ```yaml
411
+ prompts:
412
+ - "{{ prompt }}"
413
+
262
414
  tests:
263
- - id: bad-example
264
- criteria: Gives a thoughtful answer # ⚠ NOT evaluated — no grader in assertions
265
- input: "What is 2+2?"
266
- assertions:
267
- - type: contains
268
- value: "4"
269
- # Warning: criteria is defined but no grader in assertions will evaluate it.
415
+ - id: good-example
416
+ vars:
417
+ prompt: "What is 2+2?"
418
+ expected_output: "4"
419
+ assert:
420
+ - The answer is 4 and explains the arithmetic briefly
270
421
  ```
271
422
 
272
423
  ## Required Gates
@@ -274,13 +425,14 @@ tests:
274
425
  Any grader can be marked `required` to enforce a minimum score:
275
426
 
276
427
  ```yaml
277
- assertions:
428
+ assert:
278
429
  - type: contains
279
430
  value: "DENIED"
280
431
  required: true # must score >= 0.8 (default)
281
- - type: rubrics
282
- required: 0.6 # must score >= 0.6 (custom threshold)
283
- criteria:
432
+ - type: llm-rubric
433
+ required: true
434
+ min_score: 0.6 # must score >= 0.6 (custom threshold)
435
+ value:
284
436
  - id: accuracy
285
437
  outcome: Identifies the denied party
286
438
  weight: 5.0
@@ -288,103 +440,106 @@ assertions:
288
440
 
289
441
  If a required grader scores below its threshold, the overall verdict is forced to `fail`.
290
442
 
291
- ## Workspace Setup/Teardown
443
+ ## Environment Setup/Teardown
292
444
 
293
445
  Run scripts before/after each test. Define at suite level or override per case:
294
446
 
295
447
  ```yaml
296
- workspace:
297
- template: ./workspace-templates/my-project
298
- repos:
299
- - path: ./repo
300
- repo: sympy/sympy
301
- base_commit: "abc123"
302
- hooks:
303
- before_all:
304
- command: ["bun", "run", "setup.ts"]
305
- timeout_ms: 120000
306
- after_each:
307
- reset: fast
308
- after_all:
309
- command: ["bun", "run", "teardown.ts"]
448
+ environment:
449
+ type: host
450
+ workdir: ./repo
451
+ setup:
452
+ command: ["bun", "run", "setup.ts", "sympy/sympy", "abc123"]
453
+ cwd: "."
454
+ timeout_ms: 120000
455
+ extensions:
456
+ - file://scripts/teardown.mjs:afterAll
310
457
 
311
458
  tests:
312
459
  - id: case-1
313
460
  input: Fix the bug
314
- criteria: Bug is fixed
315
461
  metadata:
316
462
  source_repo: sympy/sympy
317
463
  source_commit: "abc123"
318
464
  ```
319
465
 
320
- **Lifecycle:** template copyrepo materializationworkspace before_all → target before_allgit baseline → before_each hooks → agent → file changes after_each hooksafter_all hooks → cleanup
321
- **Merge:** Case-level fields replace suite-level fields.
322
- **Commands receive stdin JSON:** `{workspace_path, test_id, eval_run_id, case_input, case_metadata}`
466
+ **Lifecycle:** environment setuplifecycle extensions → target setup → agent → gradingteardown extensions → cleanup
467
+ **Merge:** Case-level environment fields replace suite-level fields.
468
+ **Setup commands:** `setup.command` is an argv command. `command[0]` is the executable and `command[1...]` are CLI arguments. Use `["bash", "-lc", "..."]` when shell behavior is required.
469
+ **Setup stdin:** AgentV sends environment metadata JSON on stdin for setup commands.
323
470
  **Setup failure:** aborts case. **Teardown failure:** non-fatal (warning).
324
- For SWE-bench-style evals, keep operational checkout state under `workspace.repos[].base_commit`; treat `metadata.source_commit` as informational only.
471
+ For SWE-bench-style evals, put operational checkout state under
472
+ `environment.setup.command` CLI arguments; treat `metadata.source_commit` as informational only.
473
+ A SHA in the prompt or metadata without a matching environment setup recipe is
474
+ not an operational checkout.
325
475
 
326
- ### Repository Lifecycle
476
+ ### Environment Lifecycle
327
477
 
328
- Materialize repos into the eval workspace automatically. Repo entries declare identity and checkout pins only; AgentV resolves acquisition from registered projects, `git_cache.mirrors`, its mirror cache, then remote clone. `git_cache.mirrors` may be defined in `$AGENTV_HOME/config.yaml`, the project's committed `.agentv/config.yaml`, or a gitignored `.agentv/config.override.yaml` (highest precedence) — use the override for machine-specific local clone paths without editing tracked or user-global config. For shared repo workspaces, pooling is the default:
478
+ Describe coding-agent testbeds with `environment`. Reusable recipes should live
479
+ in field-local files and be loaded with `environment: file://...`:
329
480
 
330
481
  ```yaml
331
- workspace:
332
- repos:
333
- - path: ./repo
334
- repo: https://github.com/org/repo.git
335
- commit: main
336
- ancestor: 1 # parent commit
337
- hooks:
338
- after_each:
339
- reset: fast # none | fast | strict
340
- isolation: shared # shared | per_test
341
- mode: pooled # pooled | temp | static
482
+ environment: file://.agentv/environments/repo.yaml
342
483
  ```
343
484
 
344
- - `repo`: full clone URL or GitHub `org/name` shorthand
345
- - `commit`: branch, tag, or SHA to check out
346
- - `base_commit`: alias for `commit` for SWE-bench-style datasets
347
- - `ancestor`: walk N commits back from the checked-out ref
348
- - `sparse`: sparse checkout paths array
349
- - Do not use legacy `source`, `type`, `checkout`, `resolve`, or `clone` fields under `workspace.repos[]`
350
- - `mode`: `pooled` (default for shared repos), `temp`, or `static`
351
- - `path`: workspace path used when `mode: static`; when empty/missing the workspace is auto-materialised (template copied + repos cloned); populated dirs are reused as-is
352
- - `hooks.enabled`: boolean (default `true`); set `false` to skip all lifecycle hooks
353
- - Pool reset defaults to `fast` (`git clean -fd`); use `--workspace-clean full` for strict reset (`git clean -fdx`)
354
- - Pool entries are managed separately via `agentv workspace list` and `agentv workspace clean`
355
- - `agentv workspace deps <eval-paths>` scans eval files and outputs a JSON manifest of required git repos (useful for CI pre-cloning)
485
+ ```yaml
486
+ # .agentv/environments/repo.yaml
487
+ type: host
488
+ workdir: ./repo
489
+ setup:
490
+ command: ["bash", "./scripts/materialize-repo.sh", "https://github.com/org/repo.git", "main", "1"]
491
+ cwd: "."
492
+ timeout_ms: 120000
493
+ ```
356
494
 
357
- See https://agentv.dev/targets/configuration/#repository-lifecycle
495
+ ```yaml
496
+ # .agentv/environments/docker-repo.yaml
497
+ type: docker
498
+ context: ./environment
499
+ dockerfile: Dockerfile
500
+ workdir: /app
501
+ setup:
502
+ command: ["bash", "-lc", "bun install && bun run build"]
503
+ cwd: "."
504
+ timeout_ms: 120000
505
+ ```
506
+
507
+ - `type`: `host` or `docker`
508
+ - `workdir`: path the target and graders should use
509
+ - `setup`: argv command, optional `cwd`, and optional `timeout_ms` for repository/testbed materialization
510
+ - Top-level `env`: provider/eval environment overrides
511
+ - `environment.env`: recipe-scoped process environment, distinct from top-level `env`
512
+ - `extensions`: lifecycle hooks such as `beforeAll`, `beforeEach`, `afterEach`, and `afterAll`
358
513
 
359
514
  ## Grader Types
360
515
 
361
- Configure via `assertions` array. Multiple graders produce a weighted average score.
516
+ Configure via the `assert` array. Multiple graders produce a weighted average score.
362
517
 
363
- ### code-grader
518
+ ### script
364
519
  ```yaml
365
520
  - name: format_check
366
- type: code-grader
521
+ type: script
367
522
  command: [uv, run, validate.py]
368
523
  cwd: ./scripts # optional working directory
369
524
  target: {} # optional: enable LLM target proxy (max_calls: 50)
370
525
  ```
371
526
  Contract: stdin JSON -> stdout JSON `{score, assertions: [{text, passed, evidence?}], reasoning}`
372
- Raw stdin uses snake_case and includes: `criteria`, `input`, `expected_output`, `output` (final answer string), `messages`, `trace`, `trace_summary`, `token_usage`, `cost_usd`, `duration_ms`, `start_time`, `end_time`, `file_changes`, `workspace_path`, `config`
527
+ Raw stdin uses snake_case and includes: `input`, `expected_output`, `output` (final answer string), `messages`, `trace`, `trace_summary`, `token_usage`, `cost_usd`, `duration_ms`, `start_time`, `end_time`, `file_changes`, `workspace_path`, `config`
373
528
  SDK handlers receive the same payload in camelCase: `expectedOutput`, `traceSummary`, `tokenUsage`, `costUsd`, `durationMs`, `startTime`, `endTime`, `fileChanges`, `workspacePath`.
374
- When a workspace is configured, `workspace_path` is the absolute path to the workspace dir (also available as `AGENTV_WORKSPACE_PATH` env var). Use this for functional grading (e.g., running `npm test` in the workspace).
529
+ When an environment prepares a workspace directory, `workspace_path` is the absolute path to that directory (also available as `AGENTV_WORKSPACE_PATH` env var). Use this for functional grading (e.g., running `npm test` in the prepared workdir).
375
530
  For deterministic workspace checks that fit normal Vitest `expect(...)` tests, prefer a plain verifier file and the built-in adapter:
376
531
  ```yaml
377
532
  - name: welcome_banner
378
- type: code-grader
533
+ type: script
379
534
  command: [agentv, eval, graders/welcome-banner.test.ts]
380
535
  ```
381
536
  AgentV infers the Vitest adapter for `*.test.ts`, `*.spec.ts`, and Vercel-style `EVAL.ts` files. Use the explicit `agentv eval vitest` subcommand only when you need adapter flags such as `--cwd`, `--in-workspace`, or `--vitest-command`.
382
- See docs at https://agentv.dev/graders/code-graders/
537
+ See the Script Graders docs for the full stdin/stdout contract.
383
538
 
384
- ### llm-grader
539
+ ### llm-rubric
385
540
  ```yaml
386
541
  - name: quality
387
- type: llm-grader
542
+ type: llm-rubric
388
543
  prompt: ./prompts/eval.md # markdown template or command config
389
544
  target: grader_gpt_5_mini # optional: override the grader target for this grader
390
545
  model: gpt-5-chat # optional model override
@@ -394,26 +549,27 @@ See docs at https://agentv.dev/graders/code-graders/
394
549
  Variables: `{{criteria}}`, `{{input}}`, `{{expected_output}}`, `{{output}}`, `{{metadata}}`, `{{metadata_json}}`, `{{rubrics}}`, `{{rubrics_json}}`, `{{file_changes}}`, `{{tool_calls}}`
395
550
  - Markdown templates: use `{{variable}}` syntax
396
551
  - TypeScript templates: use `definePromptTemplate(fn)` from `@agentv/sdk`, receives context object with all variables + `config`
397
- - Use `target:` to run different `llm-grader` graders against different named LLM targets in the same eval (useful for grader panels / ensembles)
552
+ - Use `target:` to run different `llm-rubric` graders against different named LLM targets in the same eval (useful for grader panels / ensembles)
398
553
 
399
- ### composite
554
+ ### assert-set
400
555
  ```yaml
401
- - name: gate
402
- type: composite
403
- assertions:
404
- - name: safety
405
- type: llm-grader
556
+ - metric: gate
557
+ type: assert-set
558
+ threshold: 0.7
559
+ config:
560
+ shared_setting: enabled
561
+ assert:
562
+ - metric: safety
563
+ type: llm-rubric
406
564
  prompt: ./safety.md
407
- - name: quality
408
- type: llm-grader
409
- aggregator:
410
- type: weighted_average
411
- weights: { safety: 0.3, quality: 0.7 }
565
+ weight: 0.3
566
+ - metric: quality
567
+ type: llm-rubric
568
+ weight: 0.7
412
569
  ```
413
- Aggregator types: `weighted_average`, `all_or_nothing`, `minimum`, `maximum`, `safety_gate`
414
- - `safety_gate`: fails immediately if the named gate grader scores below threshold (default 1.0)
570
+ Use `assert-set` for Promptfoo-aligned assertion grouping. Without `threshold`, the set passes only when every nonzero-weight child assertion passes. With `threshold`, the weighted aggregate score determines the set verdict. Parent `config` is inherited by children, and child `config` keys override parent keys. Do not use `type: composite`; AgentV rejects it.
415
571
 
416
- ### tool_trajectory
572
+ ### tool-trajectory
417
573
  ```yaml
418
574
  - name: tool_check
419
575
  type: tool-trajectory
@@ -428,8 +584,9 @@ Aggregator types: `weighted_average`, `all_or_nothing`, `minimum`, `maximum`, `s
428
584
  max_duration_ms: 5000 # per-tool latency assertion
429
585
  - tool: summarize # omit args to skip argument checking
430
586
  ```
587
+ `tool-trajectory` is an AgentV-specific extension over AgentV-normalized transcripts. Do not use Promptfoo `trajectory:*`, `tool-call-f1`, `skill-used`, or `trace-*` names; AgentV rejects those until their trace semantics are implemented directly.
431
588
 
432
- ### field_accuracy
589
+ ### field-accuracy
433
590
  ```yaml
434
591
  - name: fields
435
592
  type: field-accuracy
@@ -453,14 +610,14 @@ Compares `output` fields against `expected_output` fields.
453
610
  max_usd: 0.10
454
611
  ```
455
612
 
456
- ### token_usage
613
+ ### token-usage
457
614
  ```yaml
458
615
  - name: tokens
459
616
  type: token-usage
460
617
  max_total_tokens: 4000
461
618
  ```
462
619
 
463
- ### execution_metrics
620
+ ### execution-metrics
464
621
  ```yaml
465
622
  - name: efficiency
466
623
  type: execution-metrics
@@ -497,48 +654,37 @@ Binary check: does output match the regex pattern?
497
654
  ```
498
655
  Binary check: does output exactly equal the value (both trimmed)?
499
656
 
500
- ### is_json
657
+ ### is-json
501
658
  ```yaml
502
659
  - type: is-json
503
660
  required: true
504
661
  ```
505
662
  Binary check: is the output valid JSON?
506
663
 
507
- ### rubrics
664
+ ### llm-rubric
508
665
  ```yaml
509
- - type: rubrics
510
- criteria:
511
- - id: accuracy
512
- outcome: Correctly identifies the denied party
513
- weight: 5.0
514
- - id: reasoning
515
- outcome: Provides clear reasoning
516
- weight: 3.0
666
+ - Correctly identifies the denied party
667
+ - Provides clear reasoning
517
668
  ```
518
- LLM-judged structured evaluation with weighted criteria. Criteria items support `id`, `outcome`, `weight`, and `required` fields.
669
+ LLM-judged structured evaluation. Plain strings are the preferred shorthand.
670
+ Use `type: llm-rubric` when you need weighted criteria, `required: false`,
671
+ `min_score`, or score ranges. Rubric items support `id`,
672
+ `outcome`, `weight`, and `required` fields.
519
673
  Use optional `operator: correctness` for positive support checks or `operator: contradiction` for guard criteria where omission is acceptable but incompatible claims fail.
520
674
 
521
675
  See `references/rubric-grader.md` for score-range mode and scoring formula.
522
676
 
523
- ## Execution Error Tolerance
524
-
525
- Control how the runner handles execution errors (infrastructure failures, not quality failures):
526
-
527
- ```yaml
528
- execution:
529
- fail_on_error: false # never halt (default)
530
- # fail_on_error: true # halt on first execution error
531
- ```
532
-
533
- When halted, remaining tests get `executionStatus: 'execution_error'` with `failureReasonCode: 'error_threshold_exceeded'`.
534
-
535
677
  ## Suite-Level Quality Threshold
536
678
 
537
- Set a minimum mean score for the eval suite. If the mean quality score falls below the threshold, the CLI exits with code 1 — useful for CI/CD quality gates.
679
+ Set a minimum mean score for the eval suite. If the mean quality score falls below the threshold, the CLI exits with code 1 — useful for CI/CD quality gates. Use `evaluate_options.repeat` when each case should be attempted more than once.
538
680
 
539
681
  ```yaml
540
- execution:
541
- threshold: 0.8
682
+ evaluate_options:
683
+ repeat:
684
+ count: 3
685
+ strategy: pass_any
686
+ early_exit: false
687
+ threshold: 0.8
542
688
  ```
543
689
 
544
690
  CLI flag `--threshold 0.8` overrides the YAML value. Must be a number between 0 and 1. Mean score is computed from quality results only (execution errors excluded).
@@ -549,7 +695,7 @@ The threshold also controls JUnit XML pass/fail: tests with scores below the thr
549
695
 
550
696
  ```bash
551
697
  # Run evaluation (requires API keys)
552
- agentv eval <file.yaml> [--test-id <id>] [--target <name>] [--dry-run] [--threshold <0-1>]
698
+ agentv eval <file.yaml> [--test-id <id>] [--target <name>] [--threshold <0-1>]
553
699
 
554
700
  # Run with OTLP JSON file (importable by OTel backends)
555
701
  agentv eval <file.yaml> --otel-file traces/eval.otlp.json
@@ -570,18 +716,27 @@ agentv eval <file.yaml> --retry-errors .agentv/results/default/<timestamp>/index
570
716
  # Validate eval file
571
717
  agentv validate <file.yaml>
572
718
 
573
- # Compare results — N-way matrix from a canonical run manifest
574
- agentv compare .agentv/results/default/<timestamp>/index.jsonl
575
- agentv compare .agentv/results/default/<timestamp>/index.jsonl --baseline <target> # CI regression gate
576
- agentv compare .agentv/results/default/<timestamp>/index.jsonl --baseline <target> --candidate <target> # pairwise
577
- agentv compare .agentv/results/default/<baseline-timestamp>/index.jsonl .agentv/results/default/<candidate-timestamp>/index.jsonl
719
+ # Compare completed runs
720
+ agentv results compare \
721
+ .agentv/results/default/<baseline-timestamp>/index.jsonl \
722
+ .agentv/results/default/<candidate-timestamp>/index.jsonl
723
+ agentv results combine \
724
+ .agentv/results/default/<baseline-timestamp> \
725
+ .agentv/results/default/<candidate-timestamp> \
726
+ .agentv/results/default/<third-target-timestamp> \
727
+ --output .agentv/results/default/combined
728
+ agentv results compare .agentv/results/default/combined/index.jsonl
729
+ agentv results compare \
730
+ .agentv/results/default/<baseline-timestamp>/index.jsonl \
731
+ .agentv/results/default/<candidate-timestamp>/index.jsonl \
732
+ --json
578
733
 
579
734
  # Author assertions directly in the eval file
580
735
  # Prefer simple assertions when they fit the criteria; use deterministic or LLM-based graders when needed
581
736
  agentv validate <file.yaml>
582
737
  ```
583
738
 
584
- **Replay targets:** Add `provider: replay`, `fixtures: <jsonl>`, and `source_target: <live target name>` in `.agentv/targets.yaml`. Optional `suite`, `eval_path`, and `variant` tighten lookup. The eval YAML and graders stay unchanged; replay only substitutes recorded target output, and graders run fresh.
739
+ **Replay targets:** Add `provider: replay`, `fixtures: <jsonl>`, and `source_target: <live target label>` in `.agentv/targets.yaml`. Optional `suite`, `eval_path`, and `variant` tighten lookup. The eval YAML and graders stay unchanged; replay only substitutes recorded target output, and graders run fresh.
585
740
 
586
741
  ## TypeScript SDK Helpers
587
742
 
@@ -593,12 +748,19 @@ import { defineEval, graders } from '@agentv/sdk';
593
748
 
594
749
  export default defineEval({
595
750
  name: 'helper-suite',
596
- execution: { targets: ['default'] },
751
+ target: 'default',
752
+ // The SDK helper lowers this to evaluate_options.repeat in generated YAML.
753
+ repeat: {
754
+ count: 3,
755
+ strategy: 'pass_any',
756
+ earlyExit: false,
757
+ },
758
+ threshold: 0.8,
597
759
  tests: [
598
760
  {
599
761
  id: 'json-answer',
600
762
  input: 'Return a JSON answer with a status field.',
601
- assertions: [
763
+ assert: [
602
764
  graders.json({ name: 'valid-json', required: true }),
603
765
  graders.regex(/"status"\s*:/, { name: 'status-key' }),
604
766
  ],
@@ -607,7 +769,7 @@ export default defineEval({
607
769
  });
608
770
  ```
609
771
 
610
- The `graders` catalog returns ordinary `assertions` entries such as `type: is-json`, `type: regex`, `type: llm-grader`, and `type: code-grader`. `defineEval()` lowers camelCase TypeScript fields such as `expectedOutput`, `inputFiles`, and `maxSteps` to canonical snake_case YAML/runtime keys.
772
+ The `graders` catalog returns ordinary `assert` entries such as `type: is-json`, `type: regex`, `type: llm-rubric`, and `type: script`. `defineEval()` lowers camelCase TypeScript fields such as `expectedOutput`, `inputFiles`, and `maxSteps` to canonical snake_case YAML/runtime keys.
611
773
 
612
774
  If adapting Braintrust `scores` or DeepEval metrics, write small AgentV helper factories that return `graders.*` configs:
613
775
 
@@ -615,7 +777,7 @@ If adapting Braintrust `scores` or DeepEval metrics, write small AgentV helper f
615
777
  import { graders } from '@agentv/sdk';
616
778
 
617
779
  export function ragFaithfulness() {
618
- return graders.llmGrader({
780
+ return graders.llmRubric(undefined, {
619
781
  name: 'rag-faithfulness',
620
782
  target: 'grader-target',
621
783
  prompt: 'Grade whether the answer is supported by the retrieved context.',
@@ -623,9 +785,9 @@ export function ragFaithfulness() {
623
785
  }
624
786
  ```
625
787
 
626
- Use the helper in `assertions: [ragFaithfulness()]`; do not create new YAML terms like `scores`.
788
+ Use the helper in `assert: [ragFaithfulness()]`; do not create new YAML terms like `scores`.
627
789
 
628
- ### defineAssertion (recommended for custom checks)
790
+ ### defineAssertion (recommended for reusable custom assertions)
629
791
  ```typescript
630
792
  #!/usr/bin/env bun
631
793
  import { defineAssertion } from '@agentv/sdk';
@@ -641,16 +803,18 @@ export default defineAssertion(({ output, trace }) => {
641
803
 
642
804
  Assertions support both `pass: boolean` and `score: number` (0-1). If only `pass` is given, score is 1 (pass) or 0 (fail).
643
805
 
644
- ### defineCodeGrader (full control)
806
+ Use `defineAssertion()` when you want a reusable assertion type discovered from `.agentv/assertions/` and referenced by filename as `type: <name>`. This follows Promptfoo's normal eval terminology: custom logic is an assertion, with Promptfoo using fixed assertion types such as `javascript`, `python`, `ruby`, and `webhook`. AgentV extends that model by allowing arbitrary discovered assertion type names.
807
+
808
+ ### defineScriptGrader (full control)
645
809
  ```typescript
646
810
  #!/usr/bin/env bun
647
- import { defineCodeGrader } from '@agentv/sdk';
811
+ import { defineScriptGrader } from '@agentv/sdk';
648
812
 
649
- export default defineCodeGrader(({ output, trace }) => {
813
+ export default defineScriptGrader(({ output, trace }) => {
650
814
  const finalOutput = output ?? '';
651
815
  return {
652
816
  score: finalOutput.length > 0 && (trace?.eventCount ?? 0) <= 5 ? 1.0 : 0.5,
653
- assertions: [
817
+ assert: [
654
818
  { text: 'Output is not empty', passed: finalOutput.length > 0 },
655
819
  { text: 'Efficient tool usage', passed: (trace?.eventCount ?? 0) <= 5 },
656
820
  ],
@@ -658,14 +822,14 @@ export default defineCodeGrader(({ output, trace }) => {
658
822
  });
659
823
  ```
660
824
 
661
- `defineAssertion()` files go in `.agentv/assertions/` and are referenced by filename as `type: <name>`. `defineCodeGrader()` scripts are referenced in YAML with `type: code-grader` and `command: [bun, run, grader.ts]`. Plain Vitest workspace verifier files can use `command: [agentv, eval, graders/check.test.ts]`.
825
+ Use `defineScriptGrader()` when the custom component is a command-backed grader with explicit score control, custom assertion-result arrays, workspace commands, or LLM calls through a grader target. `defineScriptGrader()` scripts are referenced in YAML with `type: script` and `command: [bun, run, grader.ts]`. Plain Vitest workspace verifier files can use `command: [agentv, eval, graders/check.test.ts]`.
662
826
 
663
827
  ### Convention-Based Discovery
664
828
 
665
829
  Place assertion files in `.agentv/assertions/` — they auto-register by filename:
666
830
 
667
831
  ```
668
- .agentv/assertions/word-count.ts → type: word-count
832
+ .agentv/assertions/min-words.ts → type: min-words
669
833
  .agentv/assertions/sentiment.ts → type: sentiment
670
834
  ```
671
835
 
@@ -696,6 +860,7 @@ Programmatic API notes:
696
860
 
697
861
  - Inline programmatic tests use `assert`, not `assertions`.
698
862
  - Use camelCase in TypeScript (`expectedOutput`, `beforeAll`, `budgetUsd`).
863
+ - In YAML, use `evaluate_options.max_concurrency` for authored eval concurrency; reserve `workers` for project/target runtime config.
699
864
  - When bridging from Python, generate canonical YAML/JSONL or call the CLI; there is no separate first-party Python authoring SDK.
700
865
 
701
866
  Supports inline tests or file-based usage via `specFile`.
@@ -726,34 +891,6 @@ agentv create eval <name> # → evals/<name>.eval.yaml + .cases.jsonl
726
891
  ## Skill Improvement Workflow
727
892
 
728
893
  For a complete guide to iterating on skills using evaluations — writing scenarios, running baselines, comparing results, and improving — see the [Skill Improvement Workflow](https://agentv.dev/guides/skill-improvement-workflow/) guide.
729
- ## Human Review Checkpoint
730
-
731
- After running evals, perform a human review before iterating. Create `feedback.json` in the results directory:
732
-
733
- ```json
734
- {
735
- "run_id": "2026-03-14T10-32-00_claude",
736
- "reviewer": "engineer-name",
737
- "timestamp": "2026-03-14T12:00:00Z",
738
- "overall_notes": "Summary of observations",
739
- "per_case": [
740
- {
741
- "test_id": "test-id",
742
- "verdict": "acceptable | needs_improvement | incorrect | flaky",
743
- "notes": "Why this verdict",
744
- "evaluator_overrides": { "code-grader:name": "Override note" },
745
- "workspace_notes": "Workspace state observations"
746
- }
747
- ]
748
- }
749
- ```
750
-
751
- Use `evaluator_overrides` for workspace evaluations to annotate specific grader results (e.g., "code-grader was too strict"). Use `workspace_notes` for observations about workspace state.
752
-
753
- Review workflow: run evals → inspect results (`agentv inspect show`) → write feedback → tune prompts/graders → re-run.
754
-
755
- Full guide: https://agentv.dev/guides/human-review/
756
-
757
894
  ## Observability Export
758
895
 
759
896
  AgentV exports observability data via OpenTelemetry:
@@ -765,24 +902,21 @@ Do not invent a separate Opik-specific eval surface. Keep the eval definition in
765
902
 
766
903
  ## Schemas
767
904
 
768
- - Eval file: `references/eval-schema.json`
769
- - Experiment file: `references/experiment-schema.json`
770
- - Config: `references/config-schema.json`
905
+ - Eval file: `references/eval.schema.json`
906
+ - Config: `references/config.schema.json`
771
907
 
772
908
  ## Accessing reference files
773
909
 
774
910
  To load a specific reference without pulling the entire skill into context:
775
911
 
776
912
  ```bash
777
- agentv skills get agentv-eval-writer --ref eval-schema.json
778
- agentv skills get agentv-eval-writer --ref experiment-schema.json
913
+ agentv skills get agentv-eval-writer --ref eval.schema.json
779
914
  ```
780
915
 
781
916
  Or resolve the skill directory and read files directly:
782
917
 
783
918
  ```bash
784
- cat $(agentv skills path agentv-eval-writer)/references/eval-schema.json
785
- cat $(agentv skills path agentv-eval-writer)/references/experiment-schema.json
919
+ cat $(agentv skills path agentv-eval-writer)/references/eval.schema.json
786
920
  ```
787
921
 
788
922
  Use `--full` to retrieve every file in the skill at once.