Before you begin
Before you start, make sure you have:- Eval script: A command, such as
python -m evals.run, that runs one or moreEvalcalls. Keep each eval’s name the same on every branch: baselines are matched on the name and the dataset. - Dataset: Recommended. Results pair across runs by
dataset_record_id, or bycase_idfor inline cases with stable IDs. See Create eval datasets. - API key: A workspace-scoped key that can create experiments, stored as the repository secret
ATLAN_API_KEY. - Workspace ID: Stored as the repository variable
ATLAN_WORKSPACE_ID.
1
Write eval script
The script builds the suite and runs it. It does not compare anything or choose an exit code: the action does that.Run it from the repository root as a module, To run the command locally against a gateway other than
- Python
- TypeScript
evals/run.py
python -m evals.run, with an empty evals/__init__.py, so evals.scorers and your agent’s package import. python evals/run.py puts evals/ itself on the import path, and from evals.scorers import ... then fails.Inside the action, Python Eval stamps the commit, branch, and pull request number onto the experiment config, and reports each experiment to the action. There is nothing else to wire up.https://api.atlan.com, also set ATLAN_BASE_URL. The workflow does not need it, because the action works only with https://api.atlan.com.2
Add workflow
- Python
- TypeScript
.github/workflows/atlan-evals.yml
api-key input is used only by the action, to read results. It is deliberately not placed in the command’s environment, so the step’s env must set ATLAN_API_KEY and ATLAN_WORKSPACE_ID for Eval; without them the verdict is invalid. Your eval command runs in the same job, so treat it as trusted code. The action refuses to run under pull_request_target. The examples pin the action to an immutable commit; review a newer commit before updating that reference.Do not add a
paths: filter to pull_request if branch protection requires the check. A pull request that touches no matching path never runs the workflow, so the required check stays pending and the pull request cannot merge. To skip unrelated pull requests, test the paths inside the job instead.3
Establish baseline
Merge the workflow, or run it once on The action picks the most recent
main with Run workflow. That run becomes the baseline. Until one exists, pull requests pass with a no-baseline warning.completed run on the default branch with the same eval name (the experiment’s display_name) and dataset, and prefers one with the same model input. Set baseline to an experiment ID to pin a run, or to none to report scores with no comparison.4
Verify gate on pull request
Open a pull request. The action comments, for each eval, a table of each score’s baseline mean, pull request mean, and change, with counts of improved and regressed cases. It also shows cost, tokens, and latency for information, the verdict, and links to both experiments. The comment lists record IDs and scores only, never inputs, outputs, trace text, or error messages, and it is updated in place on each push.
The gate works when the check shows
pass or no-baseline on a pull request that does not change the agent. Cost, tokens, and latency never affect the verdict. If the verdict is invalid, see Eval errors.5
Tune gate (optional)
The action’s outputs,
eval-status, regression-count, experiment-ids, baseline-experiment-ids, and comment-id, let a later step act on the verdict. Scores are assumed to be 0..1, higher is better; invert a score where lower is better, such as a step count, in the scorer.For a suite too slow or costly for every push, trigger only on a label:6
Gate in other CI systems (optional)
Outside GitHub Actions, or against an Atlan deployment other than A regression prints a line such as
https://api.atlan.com, run your eval in a plain step, then compare it with a baseline by the same rule the action uses and exit non-zero on a regression.evals/gate.py
REGRESSED exact_match: 1.000 -> 0.500 (3 of 6 cases worse).To find the baseline, list the latest completed run of the same eval and dataset on your main branch. Outside the action, Eval does not record the branch, so pass it yourself, for example config={"branch": os.environ["CI_BRANCH"]}, and filter on it: client.experiments.list(config="branch:main", dataset_id=suite.id, experiment_status="completed", sort="-created_at", limit=1). config filters take a dotted path; runs made by the action carry the branch at git.branch.Troubleshooting
Gate failures include aninvalid verdict when the command has no credentials, a required check stuck pending because of a paths: filter, and no-baseline on every pull request. See Eval errors.
Next steps
- Compare two agent versions: Inspect the cases behind a regression one by one.
See also
- Configure eval runs: Config, concurrency, and resuming a stopped run.
- Set up evals with coding agents: Hand this setup to a coding agent.
- Eval options and errors: Environment variables the action sets.