Skip to main content

rubricate

Rubrics as code for AI evaluation. Write one portable YAML rubric, lint it before you spend a single token, measure whether humans and LLM judges actually agree on it, assert hard rules over agent trajectories, and gate regressions in CI.

Status: alpha (v0.1.0). The spec may still change before 1.0. See the changelog.


The problem

Every team evaluating LLMs and agents writes rubrics. Almost nobody tests them.

  • Rubrics live inside prompts. Each eval framework stores them differently, so a rubric can't be reviewed, versioned, or reused on its own.
  • Bad rubrics fail silently. An anchor like "response is appropriate" or two score levels that overlap produce noisy scores, and you only find out after paying for thousands of judge calls.
  • Judge agreement goes unmeasured. Teams swap judge models and rewrite anchors without checking whether the new scores still match human raters.
  • Agents need rules, not just scores. "Never issue a refund over $100 without approval" is a pass/fail rule about the sequence of tool calls, and it doesn't fit a 1–5 scale.

What rubricate does

Capability What it gives you
Spec One versionable .rubric.yaml format: criteria, weights, score anchors, worked examples, and pass/fail assertions
Lint Static checks that catch weak rubrics before evaluation: vague wording, score levels with no example, overlapping anchors
Calibrate Agreement reports between human raters and LLM judges, per criterion, so you know which anchors to tighten
Assert Rules over agent trajectories (tool-call order, approvals, retry budgets) with blocker severity that fails the run
Gate A CLI and GitHub Action that fail the build when a prompt or model change regresses
Export Compile one rubric into configs for existing eval frameworks, so you don't switch stacks

How it fits with existing tools

rubricate is a layer underneath your eval stack, not a replacement for it.

  • Eval runners (promptfoo, Inspect, DeepEval) run evaluations and accept rubrics as prompt strings. rubricate gives those rubrics a typed, lintable source of truth and exports to them.
  • Rubric-scoring libraries and research (for example Autorubric and Rulers) focus on how a judge scores against a rubric. rubricate focuses on whether the rubric itself is any good, and on one spec that covers both single responses and agent runs.

What's new here: static analysis for rubrics, and one spec for grading answers and agent trajectories.

A taste of the spec

Full reference: docs/spec.md. Complete example: examples/refund-agent.rubric.yaml.

# refund-agent.rubric.yaml
spec: "0.1"
id: refund-agent
subject: trajectory              # grade the whole agent run, not just the final reply
criteria:
  - id: policy_accuracy
    weight: 0.4
    question: "Does the final reply state the refund policy correctly?"
    scale:
      1: "States a wrong eligibility window or amount"
      3: "Correct but omits a condition (e.g., receipt required)"
      5: "Correct, complete, and cites the policy section"
    examples:
      - score: 1
        output: "You can return it anytime for a full refund!"
  - id: approval_gate
    type: assertion              # binary pass/fail rule over tool calls
    rule: "issue_refund is never called before human_approval when amount > 100"
    severity: blocker            # one failure fails the whole run
    check:                       # the machine-checkable form
      kind: requires_before
      tool: issue_refund
      requires: human_approval
      where: { amount: { gt: 100 } }
$ rubricate lint examples/lint-demo/
weak-support.rubric.yaml:17: R004 warning: criteria[0].scale.5: anchor uses vague wording ('appropriate', 'good'); describe what a rater can observe instead, such as what is present, missing, or wrong
weak-support.rubric.yaml:21: R002 error: criteria[0].examples[1].score: example score 4 is not a level on this scale (levels: 1, 3, 5)
weak-support.rubric.yaml:24: R001 error: criteria[1].id: criterion id 'helpfulness' is already used by criteria[0]; ids must be unique

Install

pip install rubricate              # validate, lint, check, calibrate, export
pip install "rubricate[gemini]"    # adds LLM-judge scoring with Gemini
rubricate --version

Usage

Validate rubrics

Check files or whole folders (folders are searched for *.rubric.yaml):

$ rubricate validate rubrics/
rubrics/refund-agent.rubric.yaml: valid
rubrics/support.rubric.yaml:8: criteria[0].scale: needs at least 2 score levels, found 1
rubrics/support.rubric.yaml:11: criteria[1].severity: 'critical' is not one of ['blocker', 'warning']
2 file(s) checked, 1 invalid (2 error(s))

Every problem is reported as file:line: location: message, so editors and CI logs can jump straight to it.

Exit code Meaning
0 All files are valid
1 At least one file is invalid (fail the build)
2 Bad arguments: a path doesn't exist, or no rubric files were found

Use --format json for machine-readable output.

Lint rubrics

lint catches the problems that make raters and judges disagree, before you spend anything on evaluation:

$ rubricate lint rubrics/
rubrics/support.rubric.yaml:15: R003 warning: criteria[0].scale.1: score 1 has no example; add one so raters can see what this level looks like
rubrics/support.rubric.yaml:17: R004 warning: criteria[0].scale.5: anchor uses vague wording ('appropriate', 'good'); describe what a rater can observe instead, such as what is present, missing, or wrong
rubrics/support.rubric.yaml:21: R002 error: criteria[0].examples[1].score: example score 4 is not a level on this scale (levels: 1, 3, 5)
rubrics/support.rubric.yaml:35: R005 warning: criteria[2].scale.5: anchors for scores 3 and 5 differ only by degree words ('fully', 'mostly'); say what is present or missing at each level instead
1 file(s) linted: 1 error(s), 3 warning(s)
by rule: R002 x1, R003 x1, R004 x1, R005 x1

Errors fail the run; warnings fail it only with --strict. Skip rules with --ignore R003,vague-anchor, and see them all with --list-rules. Full reference: docs/lint-rules.md.

Score responses with an LLM judge

score grades responses against a rubric using a model you choose. It needs your own API key: Gemini's free tier works, no credit card required.

pip install "rubricate[gemini]"
export GEMINI_API_KEY=your-key
rubricate score examples/refund-agent.rubric.yaml --output "Refunds within 30 days with a receipt."
rubricate score examples/refund-agent.rubric.yaml --batch replies.jsonl --out scores.jsonl

Every reply from the judge is validated: a skipped criterion, an invented one, or a score off the scale is rejected rather than silently recorded. Full guide: docs/scoring.md.

Check agent runs against hard rules

check verifies recorded agent runs against a rubric's assertions: tool-call order, forbidden or required calls, and call budgets. It's deterministic and offline:

$ rubricate check examples/refund-agent.rubric.yaml examples/traces/refund-runs.jsonl
run-skipped-approval: BLOCKED
  FAIL  approval_gate (blocker): issue_refund called at step 3 where amount > 100 with no earlier human_approval
run-retry-loop: ok
  FAIL  lookup_budget (warning): 4 lookup_order calls, budget is 3 (exceeded at step 7)
4 run(s) checked: 1 blocked, 1 with warnings

Full guide, including the trace format: docs/assertions.md.

Measure agreement

calibrate shows, per criterion, whether humans apply the rubric consistently and whether the judge matches them:

$ rubricate calibrate examples/refund-agent.rubric.yaml --human examples/ratings/refund-human-ratings.csv
criterion            items raters   alpha  verdict
policy_accuracy         12      3    0.93  humans agree
tone                    12      3   -0.04  humans disagree: tighten the anchors

Add --judge-scores scores.jsonl (from score --batch) to compare the judge against the humans. Full guide: docs/calibration.md.

Use it in CI and in promptfoo

# .github/workflows/rubrics.yml
- uses: dys2806/rubricate@main
  with:
    rubrics: rubrics/
    traces: traces/latest-runs.jsonl   # optional
rubricate export rubrics/support.rubric.yaml --to promptfoo -o support.promptfoo.yaml

The Action validates and lints rubrics and checks agent traces, with no API key needed. The exporter turns each scored criterion into a promptfoo llm-rubric assertion. Details: docs/integrations.md.

Roadmap

  • Project scaffold, CLI, CI
  • Rubric spec v0.1 + JSON Schema (docs/spec.md)
  • rubricate validate
  • rubricate lint: duplicate ids, off-scale examples, missing examples, vague wording, overlapping anchors
  • rubricate score: LLM-judge scoring for single responses and JSONL batches (Gemini)
  • rubricate check: trace format + trajectory assertions with blocker severity
  • rubricate calibrate: human and judge agreement per criterion
  • Pre-registered proof of concept on SummEval: results. The lint-guided revision lowered judge–expert agreement (kappa 0.62 → 0.53), reported as found
  • rubricate export --to promptfoo and a GitHub Action (docs/integrations.md)
  • v0.1.0 release

Contributing

Issues, rubric examples, and pull requests are welcome. See CONTRIBUTING.md.

License

Apache-2.0

Metadata

Release files for rubricate 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rubricate 0.1.0
File Size Uploaded Provenance Actions
rubricate-0.1.0.tar.gz 58.9 kB With provenance Details for rubricate-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for rubricate 0.1.0
File Interpreter ABI Platform Actions
rubricate-0.1.0-py3-none-any.whl Python 3 none any Details for rubricate-0.1.0-py3-none-any.whl

Total release size: 103.5 kB

Release files / rubricate-0.1.0.tar.gz

Download URL rubricate-0.1.0.tar.gz
Size 58.9 kB
Tags Source
SHA-256 checksum
How to use checksums
93b9bb119aef749605404d8987781b119b5323b68904f7a7ff2b89df42232a15
BLAKE2b-256 checksum
How to use checksums
0c015ffb33a018d6c2d166888754e76817fed042e4e6e4c838c1f7167250b9a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

Release files / rubricate-0.1.0-py3-none-any.whl

Download URL rubricate-0.1.0-py3-none-any.whl
Size 44.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c65cd2bfc4c761d6c12e57c6609e681f2dc2fae6e94c2d9f4673e7e053c32010
BLAKE2b-256 checksum
How to use checksums
b50b9a4d2433c972e6964f812db114c3de03ae7d488ec00dbf0a3a3486ee4bc7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

Security for rubricate 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for rubricate-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page