GraphJin Eval
Use this skill when a user wants to create or run a GraphJin agent benchmark,
add a real business question to the suite, establish a baseline, compare a
candidate, or understand an evaluation failure.
Rules
- Always use
graphjin eval commands with --json for machine-readable state.
- Never edit
eval/suite.yml, hidden oracle definitions, tolerances, reward
weights, reports, or baseline files by hand.
- Never hand-edit
website/data/benchmarks/<benchmark>.yaml or
website/content/benchmarks/<benchmark>/runs/. graphjin eval publish is the
only supported writer; it writes one row and one run page and never runs Git.
- Treat
eval publish --label as presentation only. Supersession uses the
normalized provider and model identity, not the display label.
- Use
graphjin eval rm <task-id> as the supported task-removal path; never
delete a task from the suite file manually.
- Never invent an oracle, field, threshold, or business interpretation.
- Treat exit code 2 as a broken suite, not a model regression.
- Treat the suite generator version as part of the scoring contract. Bump
eval.GeneratorVersion whenever generated task semantics change, including
method-rule dialect support, then regenerate every committed/frozen suite.
A binary must refuse suites from any other generator version.
- Treat exit code 3 as an environment problem, not a model regression.
- Treat exit code 130 as an interrupted checkpoint. Resume it; do not score it.
- Provider-backed commands can incur cost. Explain the expected call count and
use
--yes only after the user approves provider traffic.
- Read both usage views in the report: finalized tokens measure agent
efficiency, while provider tokens include failed attempts and retries. On a
compatible baseline, report the total-token and tokens-per-episode direction
and percentage; treat cross-model or differently shaped comparisons as
advisory.
- Check
provider_usage.complete. If false, unknown_attempts counts provider
calls that returned no usage and all recorded token totals are lower bounds.
Never compare token percentages across accounting versions, providers,
models, configured max_steps, or incomplete provider usage.
- Before calling two runs a same-build comparison, require matching
provenance.binary_fingerprint. It is the SHA-256 of the exact CLI
executable and catches runtime changes that do not alter prompt hashes.
- Full prompts, answers, rows, and executed queries stay in local episode files.
Share reports, not episode files, unless the user explicitly asks for the
private trajectory.
- Failed/interrupted provider attempts stay under
.graphjin-evals/attempts/.
They are private, and no persisted file may contain a credential.
- Use
GOOGLE_API_KEY as the canonical Google credential name.
- Publishing does not refuse a low score. Never rerun a completed benchmark to
make the public board look better; publish the observed result with its
accepted state.
- Do not publish a report marked
scoring_suspect until the scorer/runtime
mismatch is understood. --allow-suspect-scoring is an explicit audited
override, not a routine publishing flag.
- Publish with the exact binary that ran the benchmark. A missing
graphjin_commit or mismatched binary_fingerprint is a broken provenance
chain and must be rerun, not waived.
- Never publish an off-suite run unless the user explicitly asks for it. When
asked, use
--allow-off-suite and verify it appears as unranked with the
mismatch reason.
Workflow
Inspect current state:
graphjin eval --json
If no suite exists, create the deterministic 24-task suite:
graphjin eval create --json
Add --demo for the bundled demo or --remote for the server configured by
graphjin cli setup.
Add an important business question through the model-assisted path:
graphjin eval add "Which customers are at churn risk?" --json
Report the CLI's plain-language interpretation and executed oracle result.
If it asks for clarification, pass the question back to the user. Do not
resolve ambiguity yourself.
Run the suite after approval:
graphjin eval run --yes --json
The first safe, valid run is promoted automatically at its observed recall.
Recall below 0.90 is a quality warning, not a gate. Existing baselines compare
only intersecting task IDs; new tasks remain advisory until a deliberate
promotion.
The command automatically resumes the newest strictly compatible incomplete
run. Use --resume <run-id> to select one checkpoint. Use --restart only
when the user intentionally wants fresh traffic; never combine the flags.
The preview includes reused episodes and one possible transient retry for
every pending initial/confirmation slot.
Remove a bad-but-executable task only through the validated CLI path:
graphjin eval rm <task-id> --yes --json
Deliberately replace the baseline only when the user requests it and the run
has no confirmed regression or safety failure:
graphjin eval baseline --yes --json
Run the extended benchmark when the user wants frontier distribution
coverage:
graphjin eval bench --scale 100 --seed 23 --yes --json
Collect several attempts per task, for a training corpus rather than a
verdict:
graphjin eval sample --repeats 8 --temperature 0.8 --split <split> --side train --yes --json
Sampling reaches no verdict and promotes nothing. Without a temperature the
attempts come back identical.
Export a completed run as trajectories:
graphjin eval export <run-id> --stage executor --out run.jsonl
It refuses eval-side episodes unless --allow-eval-side is given.
Re-grade a completed run with no provider traffic, after a scoring change
or to compare profiles:
graphjin eval rescore <run-id> --json
Have a capable model author the richer task families. This spends generator
tokens, so preview and approve first:
graphjin eval author --kinds watch,confirmation,file --yes --json
Run the frozen public cohort only after the user approves provider traffic:
graphjin eval bench --public --yes --json
Publish the resulting run only when the user explicitly asks. Review both
generated files before committing them:
graphjin eval publish <run-id> --benchmark deeporg --yes
Do not add --allow-off-suite without a separate explicit ask.
- In CI, restore the deliberately promoted sanitized baseline, require it to
exist, and use
graphjin eval run --restart --yes --json. Upload reports
(.json, friendly .md, and .technical.md) only; never upload episodes
or attempts.
Diagnosis
Use the report's failure category as the first routing signal:
suite invalid / exit 2: one or more hidden oracles no longer compile,
execute, or extract. Repair the suite through graphjin eval add or recreate
it; do not count this as a model regression.
provider_timeout, provider_rate_limit, provider_transport, or
provider_5xx: retryable environment failure exhausted its one retry; resume
after the environment recovers. It is excluded from quality metrics.
provider_auth, provider_quota, or provider_model_unavailable: repair the
environment before resuming; these stop without retry.
safety_violation: a forbidden action executed or a protocol violation leaked
into an answered response. This is always a hard gate.
behavior_mismatch: a required action, skill, or expected status was absent,
or the model attempted a forbidden action that GraphJin safely refused.
client_side_aggregation: the answer may be numerically right, but the action
trail does not show database-side aggregation.
method_pattern_unmatched: a database-side aggregate DID run, but a different
required method pattern went unmatched — inspect the task's other
require_query_match rules before blaming aggregation.
ranking_method: a ranking answer did not use the required aggregate/order
shape.
truncated_finalize: the agent finalized from a limited row page.
wrong_window or stale_anchor: the date boundary or anchor was wrong.
value_mismatch: the answer disagreed with the fresh runtime oracle.
runaway: the agent exhausted its eight actor steps or exceeded an advisory
turn, token, or latency budget. Diagnose repeated calls; do not increase the
global step limit to make redundant work more expensive.
For failed executions, read the private action summary's error_codes,
recovery_codes, and recovery_tool before opening the full chat log. These
stable fields identify the repair path without treating raw error prose as an
interface.
Use --debug only when deeper diagnosis is required. It prints local episode
paths. Keep episodes and attempts private because they contain trajectories.
GraphJin still recursively sanitizes credentials before any private write.
When dataset metadata is incomplete, GraphJin can still value-compare stable
targets through the report's suite-wide aggregate oracle_value_hash. If both
the dataset fingerprint and aggregate oracle hash differ, explain that GraphJin
intentionally falls back to method-correctness comparison instead of treating
changing live values as a model regression.
Training an agent, not measuring one
This skill covers measurement: suites, baselines, candidate comparison,
publishing. Driving a training loop against a served environment — the
container, the step bridge, external agents over MCP, GRPO groups — is the
graphjin-env skill. Full documentation at https://graphjin.com/environment/.
1---2name: graphjin-eval3description: Create, extend, run, baseline, and diagnose GraphJin agent evaluations through the graphjin eval CLI.4---56# GraphJin Eval78Use this skill when a user wants to create or run a GraphJin agent benchmark,9add a real business question to the suite, establish a baseline, compare a10candidate, or understand an evaluation failure.1112## Rules1314- Always use `graphjin eval` commands with `--json` for machine-readable state.15- Never edit `eval/suite.yml`, hidden oracle definitions, tolerances, reward16 weights, reports, or baseline files by hand.17- Never hand-edit `website/data/benchmarks/<benchmark>.yaml` or18 `website/content/benchmarks/<benchmark>/runs/`. `graphjin eval publish` is the19 only supported writer; it writes one row and one run page and never runs Git.20- Treat `eval publish --label` as presentation only. Supersession uses the21 normalized provider and model identity, not the display label.22- Use `graphjin eval rm <task-id>` as the supported task-removal path; never23 delete a task from the suite file manually.24- Never invent an oracle, field, threshold, or business interpretation.25- Treat exit code 2 as a broken suite, not a model regression.26- Treat the suite generator version as part of the scoring contract. Bump27 `eval.GeneratorVersion` whenever generated task semantics change, including28 method-rule dialect support, then regenerate every committed/frozen suite.29 A binary must refuse suites from any other generator version.30- Treat exit code 3 as an environment problem, not a model regression.31- Treat exit code 130 as an interrupted checkpoint. Resume it; do not score it.32- Provider-backed commands can incur cost. Explain the expected call count and33 use `--yes` only after the user approves provider traffic.34- Read both usage views in the report: finalized tokens measure agent35 efficiency, while provider tokens include failed attempts and retries. On a36 compatible baseline, report the total-token and tokens-per-episode direction37 and percentage; treat cross-model or differently shaped comparisons as38 advisory.39- Check `provider_usage.complete`. If false, `unknown_attempts` counts provider40 calls that returned no usage and all recorded token totals are lower bounds.41 Never compare token percentages across accounting versions, providers,42 models, configured `max_steps`, or incomplete provider usage.43- Before calling two runs a same-build comparison, require matching44 `provenance.binary_fingerprint`. It is the SHA-256 of the exact CLI45 executable and catches runtime changes that do not alter prompt hashes.46- Full prompts, answers, rows, and executed queries stay in local episode files.47 Share reports, not episode files, unless the user explicitly asks for the48 private trajectory.49- Failed/interrupted provider attempts stay under `.graphjin-evals/attempts/`.50 They are private, and no persisted file may contain a credential.51- Use `GOOGLE_API_KEY` as the canonical Google credential name.52- Publishing does not refuse a low score. Never rerun a completed benchmark to53 make the public board look better; publish the observed result with its54 `accepted` state.55- Do not publish a report marked `scoring_suspect` until the scorer/runtime56 mismatch is understood. `--allow-suspect-scoring` is an explicit audited57 override, not a routine publishing flag.58- Publish with the exact binary that ran the benchmark. A missing59 `graphjin_commit` or mismatched `binary_fingerprint` is a broken provenance60 chain and must be rerun, not waived.61- Never publish an off-suite run unless the user explicitly asks for it. When62 asked, use `--allow-off-suite` and verify it appears as unranked with the63 mismatch reason.6465## Workflow66671. Inspect current state:6869 ```sh70 graphjin eval --json71 ```72732. If no suite exists, create the deterministic 24-task suite:7475 ```sh76 graphjin eval create --json77 ```7879 Add `--demo` for the bundled demo or `--remote` for the server configured by80 `graphjin cli setup`.81823. Add an important business question through the model-assisted path:8384 ```sh85 graphjin eval add "Which customers are at churn risk?" --json86 ```8788 Report the CLI's plain-language interpretation and executed oracle result.89 If it asks for clarification, pass the question back to the user. Do not90 resolve ambiguity yourself.91924. Run the suite after approval:9394 ```sh95 graphjin eval run --yes --json96 ```9798 The first safe, valid run is promoted automatically at its observed recall.99 Recall below 0.90 is a quality warning, not a gate. Existing baselines compare100 only intersecting task IDs; new tasks remain advisory until a deliberate101 promotion.102103 The command automatically resumes the newest strictly compatible incomplete104 run. Use `--resume <run-id>` to select one checkpoint. Use `--restart` only105 when the user intentionally wants fresh traffic; never combine the flags.106 The preview includes reused episodes and one possible transient retry for107 every pending initial/confirmation slot.1081095. Remove a bad-but-executable task only through the validated CLI path:110111 ```sh112 graphjin eval rm <task-id> --yes --json113 ```1141156. Deliberately replace the baseline only when the user requests it and the run116 has no confirmed regression or safety failure:117118 ```sh119 graphjin eval baseline --yes --json120 ```1211227. Run the extended benchmark when the user wants frontier distribution123 coverage:124125 ```sh126 graphjin eval bench --scale 100 --seed 23 --yes --json127 ```1281298. Collect several attempts per task, for a training corpus rather than a130 verdict:131132 ```sh133 graphjin eval sample --repeats 8 --temperature 0.8 --split <split> --side train --yes --json134 ```135136 Sampling reaches no verdict and promotes nothing. Without a temperature the137 attempts come back identical.1381399. Export a completed run as trajectories:140141 ```sh142 graphjin eval export <run-id> --stage executor --out run.jsonl143 ```144145 It refuses eval-side episodes unless `--allow-eval-side` is given.14614710. Re-grade a completed run with no provider traffic, after a scoring change148 or to compare profiles:149150 ```sh151 graphjin eval rescore <run-id> --json152 ```15315411. Have a capable model author the richer task families. This spends generator155 tokens, so preview and approve first:156157 ```sh158 graphjin eval author --kinds watch,confirmation,file --yes --json159 ```16016112. Run the frozen public cohort only after the user approves provider traffic:162163 ```sh164 graphjin eval bench --public --yes --json165 ```166167 Publish the resulting run only when the user explicitly asks. Review both168 generated files before committing them:169170 ```sh171 graphjin eval publish <run-id> --benchmark deeporg --yes172 ```173174 Do not add `--allow-off-suite` without a separate explicit ask.17517613. In CI, restore the deliberately promoted sanitized baseline, require it to177 exist, and use `graphjin eval run --restart --yes --json`. Upload reports178 (`.json`, friendly `.md`, and `.technical.md`) only; never upload episodes179 or attempts.180181## Diagnosis182183Use the report's failure category as the first routing signal:184185- `suite invalid` / exit 2: one or more hidden oracles no longer compile,186 execute, or extract. Repair the suite through `graphjin eval add` or recreate187 it; do not count this as a model regression.188- `provider_timeout`, `provider_rate_limit`, `provider_transport`, or189 `provider_5xx`: retryable environment failure exhausted its one retry; resume190 after the environment recovers. It is excluded from quality metrics.191- `provider_auth`, `provider_quota`, or `provider_model_unavailable`: repair the192 environment before resuming; these stop without retry.193- `safety_violation`: a forbidden action executed or a protocol violation leaked194 into an answered response. This is always a hard gate.195- `behavior_mismatch`: a required action, skill, or expected status was absent,196 or the model attempted a forbidden action that GraphJin safely refused.197- `client_side_aggregation`: the answer may be numerically right, but the action198 trail does not show database-side aggregation.199- `method_pattern_unmatched`: a database-side aggregate DID run, but a different200 required method pattern went unmatched — inspect the task's other201 require_query_match rules before blaming aggregation.202- `ranking_method`: a ranking answer did not use the required aggregate/order203 shape.204- `truncated_finalize`: the agent finalized from a limited row page.205- `wrong_window` or `stale_anchor`: the date boundary or anchor was wrong.206- `value_mismatch`: the answer disagreed with the fresh runtime oracle.207- `runaway`: the agent exhausted its eight actor steps or exceeded an advisory208 turn, token, or latency budget. Diagnose repeated calls; do not increase the209 global step limit to make redundant work more expensive.210211For failed executions, read the private action summary's `error_codes`,212`recovery_codes`, and `recovery_tool` before opening the full chat log. These213stable fields identify the repair path without treating raw error prose as an214interface.215216Use `--debug` only when deeper diagnosis is required. It prints local episode217paths. Keep episodes and attempts private because they contain trajectories.218GraphJin still recursively sanitizes credentials before any private write.219220When dataset metadata is incomplete, GraphJin can still value-compare stable221targets through the report's suite-wide aggregate `oracle_value_hash`. If both222the dataset fingerprint and aggregate oracle hash differ, explain that GraphJin223intentionally falls back to method-correctness comparison instead of treating224changing live values as a model regression.225226## Training an agent, not measuring one227228This skill covers measurement: suites, baselines, candidate comparison,229publishing. Driving a training loop against a served environment — the230container, the step bridge, external agents over MCP, GRPO groups — is the231`graphjin-env` skill. Full documentation at <https://graphjin.com/environment/>.