Building a Grader for Autonomous Coding Agents
A complete walkthrough of creating a packaged TaskGrader, configuring it in task.yaml, validating it with coral validate, and debugging common evaluation failures.
A packaged TaskGrader allows CORAL to evaluate agent submissions using
custom Python logic while keeping evaluation dependencies isolated from the
agent's workspace.
This guide walks through creating a grader package, configuring it in
task.yaml, validating it with coral validate, and diagnosing common
evaluation failures.
What you'll build
By the end of this guide, you'll have:
- Created a packaged
TaskGraderusingcoral init. - Configured the grader in
task.yaml. - Added grading logic using the
TaskGraderAPI. - Validated the task with
coral validate. - Learned how to diagnose common grader failures.
Quick start
Create a new task using the CORAL CLI:
coral init my-taskThis scaffolds a new task with a packaged grader, a starter task.yaml, and
the directory structure needed to begin writing custom evaluation logic.
Throughout this tutorial, we'll use the bundled examples/erdos task as a
concrete example. It demonstrates a packaged grader, task.yaml
configuration, and validation workflow using a real optimization task from the
CORAL repository.
Layout
my-task/
├── task.yaml
├── seed/
│ └── solution.py
└── grader/
├── pyproject.toml
└── src/my_task_grader/
├── __init__.py
└── grader.pyThe bundled examples/erdos task follows this same structure:
| File | Purpose |
|---|---|
examples/erdos/task.yaml | Configures the grader entrypoint, setup commands, timeout, and arguments. |
examples/erdos/grader/src/erdos_grader/grader.py | Implements the TaskGrader used during evaluation. |
examples/erdos/seed/initial_program.py | The program evaluated by the grader. |
Package the grader
Each grader is a standalone Python package. This allows CORAL to install its dependencies in an isolated virtual environment without affecting either the agent's workspace or the main CORAL installation.
The package metadata lives in grader/pyproject.toml, while the grading logic
is implemented under grader/src/. During validation, the commands listed
under grader.setup install this package before any evaluations are run.
Configure the grader
The grader configuration lives in task.yaml. It tells CORAL how to locate,
install, and execute your grader during validation and task runs.
The bundled examples/erdos task provides a complete packaged grader. The
configuration below is taken from its task.yaml.
grader:
entrypoint: "erdos_grader.grader:Grader"
setup:
- "uv pip install -e ./grader"
timeout: 1100
direction: maximize
args:
program_file: "initial_program.py"entrypoint
The entrypoint tells CORAL which Python class implements your grader. It
uses the format:
package.module:ClassNameFor example:
entrypoint: "erdos_grader.grader:Grader"CORAL imports this class whenever it needs to evaluate an agent submission.
setup
The commands listed under setup prepare the grader environment before any
evaluations run.
setup:
- "uv pip install -e ./grader"Installing the grader in editable mode makes your package available inside the isolated grader virtual environment while allowing you to continue developing it locally.
timeout
The timeout limits how long a single evaluation can run.
timeout: 1100If grading exceeds this limit, CORAL stops the evaluation and records it as a failure.
direction
The direction field tells CORAL whether higher or lower scores are preferred.
direction: maximizeUse maximize when higher scores represent better solutions, or minimize
when lower scores indicate better performance.
args
Use args to pass custom configuration into your grader.
args:
program_file: "initial_program.py"These values are available through self.args inside your TaskGrader
implementation, making it easy to customize grader behavior without modifying
the grader code.
Create the grader
The grader implementation is responsible for evaluating an agent's submission
and returning a score. Every packaged grader inherits from TaskGrader and
implements the evaluate() method.
This tutorial focuses on the complete workflow for building a grader. For a
complete reference of the available TaskGrader helper methods and advanced
configuration options, see
Writing a Custom Grader.
The bundled examples/erdos task contains a complete packaged grader that
implements this workflow. The simplified example below introduces the
TaskGrader API, while the Erdős task demonstrates how those concepts are
applied in a complete implementation.
A minimal grader looks like this:
from coral.grader import TaskGrader
from coral.types import ScoreBundle
class Grader(TaskGrader):
def evaluate(self) -> float | ScoreBundle:
result = self.run_program("solution.py")
return self.score(1.0, "Evaluation completed successfully.")If you'd like to see a complete implementation, explore:
examples/erdos/task.yamlexamples/erdos/grader/src/erdos_grader/grader.py
Together, these files show how a packaged grader is configured, executes the
submitted program, validates its output, computes a task-specific score, and
returns detailed feedback using ScoreBundle.
The Erdős grader also demonstrates several commonly used TaskGrader
helpers, including self.run_program(), self.args, self.fail(), and
self.score(), making it a useful reference alongside the API
documentation.
Returning a score together with a clear explanation makes evaluation results easier to understand. Helpful feedback allows contributors to quickly identify why a submission passed or failed without inspecting the grader's implementation.
When CORAL runs an evaluation, it loads the class defined by the
entrypoint in task.yaml and calls evaluate() for every submission.
Inside evaluate(), you typically:
- Run the submitted program.
- Verify that its output is valid.
- Compute a score.
- Return the result together with useful feedback.
Example evaluation flow
The bundled examples/erdos task demonstrates a complete packaged grader for
an optimization problem. Its grader follows this evaluation pattern:
-
Read the target program from
self.args. -
Verify that the program exists.
-
Execute it with a timeout.
-
Validate the returned values.
Typical correctness checks include verifying that the program returns the expected data type, shape, value ranges, and any task-specific constraints before computing a score. Failing fast with a clear explanation makes grading easier to understand and debug.
-
Compute the final score.
-
Return the score together with an explanation.
Unlike the minimal example shown earlier, the Erdős grader performs
task-specific validation before scoring. It verifies that the submitted
program exists, executes within the configured timeout, checks that the
returned values satisfy the problem constraints, computes the final score, and
returns a ScoreBundle containing both the score and a human-readable
explanation.
This structure works well for most optimization and coding tasks because it separates execution, validation, and scoring into clear steps.
Validate the grader
Before launching agents, validate the task to ensure that the grader, configuration, and seed solution all work together correctly.
Since this guide uses the bundled examples/erdos task throughout, validate it
with:
coral validate examples/erdosIf you're building your own task instead, replace examples/erdos with the
path to your task directory.
Once validation completes successfully, your packaged grader is ready to be
used with coral start.
During validation, CORAL:
- Creates an isolated grader virtual environment.
- Executes the commands listed under
grader.setup. - Installs the packaged grader.
- Runs the seed solution.
- Calls the grader's
evaluate()method. - Reports the resulting score or any validation errors.
Running validation before starting a long optimization run helps catch configuration and grading issues early.
Debugging common failures
Validation failures are usually caused by configuration mistakes, runtime
errors, or unexpected outputs from the submitted program. Running
coral validate before starting a task makes these issues much easier to
identify.
Program file not found
If the grader cannot locate the configured program, validation will fail before evaluation begins.
If task.yaml contains:
Program file not found: initial_program.pyFor example, if task.yaml contains:
args:
program_file: "initial_program.py"make sure that file exists in the task workspace and matches the filename expected by your grader.
Runtime errors
If the submitted program raises an exception or exits with a non-zero status, the grader reports the failure instead of returning a score.
For example:
Evaluation failed:
Traceback (most recent call last):
...The traceback usually points to an exception in either the submitted program or the grader itself. Running the program independently can help isolate the cause before validating again.
For the bundled examples/erdos task, you can run the seed program directly:
python -c "import sys, os; sys.path.insert(0, 'examples/erdos/seed'); import initial_program; print(initial_program.run())"If the error occurs while setting up or installing the grader, rerun validation with verbose logging to inspect the grader setup steps:
coral validate examples/erdos --verboseInvalid outputs
The grader should verify that submitted results match the expected format.
Common validation checks include:
- incorrect return types;
- unexpected array or object shapes;
- values outside an expected range;
- missing required outputs.
Providing clear error messages helps contributors quickly understand what needs to be fixed.
Timeouts
For example:
Evaluation timed out after 1100sIf evaluation exceeds the configured timeout, CORAL terminates the grading process and records the attempt as failed.
Increase the timeout only when necessary. Otherwise, prefer reducing the runtime of the evaluated program.
Protecting private evaluation data
Some tasks require hidden datasets, answer keys, or reference implementations that agents should not be able to access.
Files listed under grader.private are copied into .coral/private/, where
they remain available to the grader but are hidden from agent workspaces.
grader:
private:
- "answers"Inside your grader, access these files through self.private_dir instead of
reading them directly from the task directory. This keeps evaluation data
separate from the visible workspace while allowing the grader to use it
during scoring.
Best practices
When writing a custom grader:
- Keep evaluation deterministic whenever possible. The same submission should produce the same score each time it is evaluated.
- Avoid introducing uncontrolled randomness into grading logic, as inconsistent scores make results difficult to compare and debug.
- Return clear explanations with both successful scores and failures.
- Validate inputs before computing a score.
- Store hidden evaluation data under
grader.privateinstead of inside the visible task directory. - Test changes with
coral validatebefore launching a full run.
Next steps
Now that you've created and validated a packaged grader, explore the bundled
examples/erdos task to see a complete production-style implementation, then
continue with the guides below for more advanced grading patterns: