Skip to main content
This guide shows how to contribute a evaluator directly to the agent-control repo. If you want to publish a standalone evaluator as a separate wheel, see Custom Evaluators. For a working reference, see the Galileo Luna-2.

Quick Start

Pick an evaluator name. Everything else derives from this:
Example: evaluator = toxicity
  • Package module: agent_control_evaluators.toxicity
  • Entry point: toxicity
  • Evaluator class: ToxicityEvaluator
From the repo root:
You’ll end up with:

Writing the Evaluator

Config — extend EvaluatorConfig with your evaluator’s settings:
Evaluator — extend Evaluator and decorate with @register_evaluator:

Register the Entry Point

Add the entry point to evaluators/builtin/pyproject.toml:
The entry point key (toxicity) must exactly match metadata.name in the evaluator class. Exports in toxicity/__init__.py:

Testing

Write tests using Given/When/Then style. Cover at least three cases:
  1. Null input — returns matched=False, no error
  2. Normal evaluation — returns correct matched based on threshold
  3. Infrastructure failure — returns matched=False with error set (fail-open)

Rules to Know

Error handling — The error field is only for infrastructure failures (network errors, API 500s, missing credentials). If your evaluator ran and produced a judgment, that’s matched=True or matched=False — not an error. When error is set, matched must be False (fail-open). Thread safety — Evaluator instances are cached and reused across concurrent requests. Never store request-scoped state on self. Use local variables in evaluate(). Performance — Pre-compile patterns in __init__(). Use asyncio.to_thread() for CPU-bound work. Respect timeout_ms for external calls.

Before You Submit

From the repo root: