*.eval.ts file β you can write one by hand whenever you want the control, but you never have to start there.
Start with your agent
The fastest path is to not run anything yourself. Tell your coding agent:spawn-ori-eval skill walks the agent through everything: it installs Ori, checks ori login, and starts ori code -p with your request. Inside the run, Oriβs create-eval skill asks the questions that shape the eval β which surface to test, what it needs to be good at, whether you have real data, and the cost ceiling β then writes it, runs your candidates, and reports back with a recommendation.
Why run evals through Ori
The hardest part of evals is keeping the test bench stable. Ori is a harness, not just a skill: it pins the model and settings at a level prompts canβt, so a score change means your agent changed, not the environment. And because Ori routes through OpenRouter, a bakeoff can cover every major labβs models β not just the one vendor your usual harness supports.Run it manually
Everything below is the same flow by hand β use it when you want the control, or to understand what the agent built.Before you start
Install the CLI:ori login stores one for Ori to use. Running evals also needs Bun; if it is missing, ori eval offers to install it on an interactive terminal.
Start from a question
From your project directory, ask Ori to run the eval:ori code -p runs without a TTY, streams output to stdout, and exits when the prompt completes. Use --prompt-file instead for a long request; the flags are mutually exclusive and positional prompts are rejected.
You do not need to know eval methodology or model names. The agent:
- Scans your repo for test material β existing prompts, tool definitions, data files (
.jsonl,.csv, chat logs), and gold answers. Tests in any language count: pytest files and Go tests get mined for cases, even though the eval itself is always TypeScript. - Asks what matters β a question or two like βaccuracy first, or speed and cost?β β only when the answer changes the eval.
- Writes and runs the eval β scaffolds
evals/<feature>/<name>.eval.ts, seeds candidate models from OpenRouterβs live catalog under your price cap, and runs them. - Recommends one model, with the scores, latency, and cost that back it up.
Under the hood: the eval file
When you want control β or want to understand what the agent built β here is the whole surface. An eval reads like a normalbun test:
evals/support/recommends.eval.ts
setupAgent() with no arguments is your workspaceβs own resolved harness and model β the same agent you already run. Then:
*.eval.ts in the workspace β keep them under top-level evals/<feature>/ directories β boots an ephemeral runtime, and hands the files to bun test. The exit code mirrors bun test, so a failing eval fails CI. Use --baseline last|best|model:<slug> to compare against an earlier run recorded in .ori/eval/history.jsonl, and --report <path> for a shareable Markdown report. Baselines only compare runs that covered exactly the same eval files.
If a bakeoff candidate is cut off before it answers, the shareable report keeps it visible as unmeasured instead of silently dropping it.
Compare models
Seed candidates from OpenRouterβs live catalog instead of hand-listing slugs, cap the price, and run the same eval against each:evals/support/model.eval.ts
candidateModels can also filter by maxCompletionPrice, minContextLength, quality indexes, required parameters or input modalities, and excludeExpiring, so unknown catalog values do not silently pass a bound.
Use assertModelIsLive(slug) when you pin an incumbent model, so the eval fails clearly if it leaves the live catalog.
Grade open-ended answers
When there is no single right string, grade with an LLM judge. The judge defaults to a dedicated agent on a strong grading model, so scoring stays independent of the model under test:evals/support/quality.eval.ts
startingCriteria.accuracy, completeness, instructionFollowing, safety, structuredOutput, and toneAndVoice provide editable starter rubrics for judge.autoEvals.
Eval against your own data
Real usage data beats synthetic prompts. Loop chat logs or Q&A pairs withtest.each:
Run it in CI
Evals spend model calls, so put them in a credentialed, opt-in job β not your default unit-test run β with the key as a secret. A failing eval fails the build, so a worse agent stops the ship instead of your users.ori eval --list --allow-no-key needs no key and cheaply asserts evals exist.