Skip to content

Commit 6e7c322

Browse files
christsoclaude
andcommitted
feat(config)!: hard-deprecate the graders: config block — a grader is just a target
Peer-framework research this session (Margin-Lab/evals, Harbor) found neither maintains a separate grader/judge schema type distinct from their target/agent config — Margin-Lab's own docs say it outright: "there is no separate grader abstraction." AgentV's own design principles already prefer config-level grader selection through `defaults.grader` over target-level `grader_target`, and the live `.agentv/targets.yaml` execution path already resolves `grader_target`/`defaults.grader` against the same target-id namespace. The only place a separate "grader" entity still existed was the newer, dead `graders:` top-level config-graph schema (`NormalizedGraderConfig`) — zero implementation depth, nothing ever turned it into a Provider. A grader can also need grading itself (oracle/calibration checks), which only works for free if it's addressable the same way as any other target. - config-graph.ts: remove `NormalizedGraderConfig`/`parseGraders`/the `graders` field from `ComposableConfigGraph`; authoring a `graders:` block now throws a clear error pointing at folding entries into `targets`. `defaults.grader` now validates against the same `graph.targets` pool as `defaults.target`, instead of the removed `graph.graders`. - eval-file.schema.ts: same hard-rejection for the Zod schema backing the published eval.schema.json (IDE-autocomplete surface), matching the existing pattern for other removed fields (`eval_cases`, `providerPromptMap`). - config-loader.ts: drop the `graders` pass-through. - Updated the one place in docs, README.md, and the readme-quickstart example that authored a `graders:` block, folding each grader into `targets:`. readme-quickstart's targets.yaml/graders.yaml also still had the legacy `${{ VAR }}` env syntax (pre-existing, unrelated breakage) — fixed to `{{ env.VAR }}` in the same pass since the file needed touching anyway. - Added a CONCEPTS.md entry disambiguating grader-selection (a target) from grader-method (an assertion type) and grader-prompt (criteria/rubric). Verified: full workspace typecheck and lint clean; 935 tests across the touched loader/validation/orchestrator suites pass; all 109 example eval files validate; live CLI check confirms the error fires end-to-end and the folded-into-targets shape validates cleanly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 589c01a commit 6e7c322

20 files changed

Lines changed: 156 additions & 128 deletions

File tree

CONCEPTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Shared domain vocabulary for this project — entities, named processes, and sta
1010

1111
**Target runtime** — The placement/transport mode for invoking a target provider, such as host execution, sandbox/container placement, CLI subprocess, app-server protocol, RPC, or SDK child runner. Runtime describes how the selected agent is invoked. Advanced home/env/profile-style overlays are provider or runtime configuration details, not the authored testbed recipe. Runtime is separate from the environment that prepares files, services, and cwd.
1212

13+
**Grader (selection)** — Not a distinct entity type. A grader is a regular target, listed under `targets` like any other and selected for a grading role via `defaults.grader`, CLI `--grader-target`, or an assertion-level target override. Authoring a separate `graders:` list is a hard error: move each entry into `targets`. This also means a grader can itself be the target of an ordinary eval (oracle/calibration checks), which a separate schema would block. Do not confuse this with **grader (method)** — an assertion `type` such as `llm-rubric`, `code-grader`, or `g-eval` that names *how* scoring works, independent of *which* target performs it; or with a rubric's `criteria`/`value`, which is the grading *prompt*. AgentV once called grader-selection "judge" (`judge_target`) before a deliberate, full rename to "grader" — do not reintroduce "judge" without a stronger reason than surface-level clarity, since peer frameworks (Margin-Lab/evals, Harbor) don't treat judge/grader as a first-class schema concept either.
14+
1315
**Provider runtime boundary** — The process boundary between AgentV's evaluation orchestrator and the agent runtime a provider invokes. CLI-backed providers place the agent runtime outside the orchestrator; SDK providers should run through an AgentV-owned child-runner boundary when runtime teardown can threaten run artifact finalization. This boundary does not own repository/testbed setup by default.
1416

1517
## Evaluation Model

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ targets:
4444
api_key: "{{ env.LOCAL_OPENAI_PROXY_API_KEY }}"
4545
model: "{{ env.LOCAL_OPENAI_PROXY_MODEL }}"
4646

47-
graders:
4847
- id: local-openai-grader
4948
provider: openai
49+
runtime: host
5050
config:
5151
api_format: chat
5252
base_url: "{{ env.LOCAL_OPENAI_PROXY_BASE_URL }}"

apps/web/src/content/docs/docs/next/evaluation/running-evals.mdx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ default.
474474
### YAML config (`config.yaml` plus optional `config.local.yaml`)
475475

476476
Project config and eval YAML share the same eval-definition graph for targets,
477-
graders, tests, defaults, and supported execution defaults. Small projects can keep that
477+
tests, defaults, and supported execution defaults. A grader is not a separate
478+
part of that graph — it is a target, listed under `targets` like any other,
479+
selected for a grading role via `defaults.grader`. Small projects can keep the
478480
graph inline:
479481

480482
```yaml
@@ -486,9 +488,9 @@ targets:
486488
command: ["codex", "app-server"]
487489
model: gpt-5-codex
488490
489-
graders:
490491
- id: openai-grader
491492
provider: openai
493+
runtime: host
492494
config:
493495
model: gpt-5-mini
494496
@@ -511,7 +513,6 @@ directly:
511513

512514
```yaml
513515
targets: file://targets.yaml
514-
graders: file://graders.yaml
515516
tests: file://tests.yaml
516517
defaults: file://defaults.yaml
517518
```
@@ -523,6 +524,12 @@ defaults: file://defaults.yaml
523524
runtime: host
524525
config:
525526
command: ["codex", "app-server"]
527+
528+
- id: openai-grader
529+
provider: openai
530+
runtime: host
531+
config:
532+
model: gpt-5-mini
526533
```
527534

528535
```yaml

apps/web/src/content/docs/docs/next/targets/cli-provider.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ targets:
2121
config:
2222
command: python agent.py --prompt {PROMPT} --out {OUTPUT_FILE}
2323

24-
graders:
2524
- id: azure-grader
2625
provider: azure
26+
runtime: host
2727
config:
2828
endpoint: "{{ env.AZURE_OPENAI_ENDPOINT }}"
2929
api_key: "{{ env.AZURE_OPENAI_API_KEY }}"
@@ -133,9 +133,9 @@ targets:
133133
config:
134134
command: cp fixtures/{EVAL_ID}.expected.txt {OUTPUT_FILE}
135135
136-
graders:
137136
- id: azure-grader
138137
provider: azure
138+
runtime: host
139139
config:
140140
endpoint: "{{ env.AZURE_OPENAI_ENDPOINT }}"
141141
api_key: "{{ env.AZURE_OPENAI_API_KEY }}"

apps/web/src/content/docs/docs/next/targets/coding-agents.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ settings live under `config`.
1515
Use `defaults.grader`, CLI `--grader` / `--grader-target`, or an
1616
evaluator-specific target override for LLM-based grading. Grader selection is
1717
separate from the coding-agent target, so target definitions do not carry a
18-
grader field.
18+
grader field. A grader is not a distinct kind of entity either — it is a
19+
regular target, listed under `targets` like any other, selected for a grading
20+
role.
1921

2022
```yaml
2123
targets:
@@ -27,9 +29,9 @@ targets:
2729
model: gpt-5-codex
2830
reasoning_effort: high
2931

30-
graders:
3132
- id: openai-grader
3233
provider: openai
34+
runtime: host
3335
config:
3436
model: gpt-5-mini
3537

apps/web/src/content/docs/docs/next/targets/configuration.mdx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Targets define which agent or LLM provider to evaluate. AgentV uses one
1010
composable config graph across project manifests and eval files:
1111

1212
- `.agentv/config.yaml` is the project-local discovery and composition root. It
13-
can hold targets, graders, tests, defaults, execution policy, results
14-
settings, and repo-local project policy.
13+
can hold targets, tests, defaults, execution policy, results settings, and
14+
repo-local project policy.
1515
- `$AGENTV_HOME/config.yaml` is the user/operator config. Use it for defaults
1616
that apply across projects, project registry data, default result locations,
1717
and provider defaults that should not be copied into each repo.
@@ -43,9 +43,9 @@ targets:
4343
command: ["codex", "app-server"]
4444
model: gpt-5-codex
4545

46-
graders:
4746
- id: openai-grader
4847
provider: openai
48+
runtime: host
4949
config:
5050
model: gpt-5-mini
5151

@@ -61,6 +61,11 @@ the shorthand for the current machine, or object form when you need
6161
settings belong under `config`. Process-backed coding-agent providers use
6262
`config.command` as a non-empty argv array.
6363

64+
A grader is not a separate kind of entity — it is a target selected for a
65+
grading role, either through `defaults.grader` (shown above) or an
66+
assertion-level target override. There is no separate `graders:` list;
67+
authoring one is a hard error telling you to move each entry into `targets`.
68+
6469
## Runtime Modes
6570

6671
Use `runtime: host` when you want AgentV to run the target exactly as it is
@@ -128,9 +133,9 @@ targets:
128133
command: ["codex", "app-server"]
129134
model: gpt-5-codex
130135
131-
graders:
132136
- id: openai-grader
133137
provider: openai
138+
runtime: host
134139
config:
135140
model: gpt-5-mini
136141
@@ -151,7 +156,6 @@ can be decomposed like this:
151156

152157
```yaml
153158
targets: file://targets.yaml
154-
graders: file://graders.yaml
155159
tests: file://tests.yaml
156160
defaults: file://defaults.yaml
157161
```
@@ -167,6 +171,12 @@ a bare array, not an object wrapped in `targets:`:
167171
config:
168172
command: ["codex", "app-server"]
169173
model: gpt-5-codex
174+
175+
- id: openai-grader
176+
provider: openai
177+
runtime: host
178+
config:
179+
model: gpt-5-mini
170180
```
171181

172182
```yaml

apps/web/src/content/docs/docs/next/targets/custom-providers.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ targets:
184184
config:
185185
base_url: http://localhost:8080
186186

187-
graders:
188187
- id: azure-grader
189188
provider: azure
189+
runtime: host
190190
config:
191191
endpoint: "{{ env.AZURE_OPENAI_ENDPOINT }}"
192192
api_key: "{{ env.AZURE_OPENAI_API_KEY }}"

apps/web/src/content/docs/docs/next/targets/llm-providers.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ For smoke tests and dogfood runs against a local OpenAI-compatible proxy, keep
6666
the endpoint, model, and placeholder key in environment variables:
6767

6868
```yaml
69-
graders:
69+
targets:
7070
- id: local-openai-grader
7171
provider: openai
72+
runtime: host
7273
config:
7374
api_format: chat
7475
base_url: "{{ env.LOCAL_OPENAI_PROXY_BASE_URL }}"
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
targets: file://targets.yaml
2-
graders: file://graders.yaml
32
tests: file://tests.yaml
43
defaults: file://defaults.yaml

examples/features/readme-quickstart/.agentv/graders.yaml

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)