AI agents · OpenClaw · self-hosting · automation

Quick Answer

How to Run LLM Evals in CI/CD: A 2026 Step-by-Step Guide

Published:

The short answer

Treat prompts, model settings and retrieval code like application code: every change runs a fixed test set, and a regression blocks the merge. The recipe, as of October 25, 2026:

  1. Build a golden dataset of real inputs.
  2. Write assertions: deterministic first, model-graded second.
  3. Run them with promptfoo (YAML, Node) or DeepEval (pytest, Python) in GitHub Actions on pull requests that touch the relevant paths.
  4. Fail on thresholds, cache responses, and run the long suite nightly.

Step 1 — Build the golden dataset

Collect 30–200 inputs from production logs or support tickets, not invented ones. For each, record what a good answer must do rather than one exact answer: “mentions the refund window”, “returns valid JSON matching the schema”, “cites at least one retrieved document”, “calls lookup_order before answering”. Include the failures you have already seen — every bug fixed becomes a test case. Store the file in the repository next to the prompts so a change to one is reviewed with the other.

Done when: the dataset is versioned in git and every case has at least one checkable expectation.

Step 2 — Write assertions in two tiers

  • Deterministic checks (cheap, never flaky): JSON schema validity, regex or substring, forbidden words, length limits, the right tool called with the right arguments, latency and cost ceilings.
  • Model-graded checks (costly, noisy): relevance, faithfulness to retrieved context, tone, rubric scores. Use these where deterministic checks cannot reach, and grade with a fixed model and a written rubric.

Done when: each test case has at least one deterministic assertion wherever one is possible.

Step 3a — Run promptfoo in GitHub Actions

promptfoo (MIT; release 0.125.1 published October 25, 2026) describes test cases in a promptfooconfig.yaml. Its official action, promptfoo/promptfoo-action@v1, runs on pull requests that modify the watched paths, evaluates the before and after versions of the edited prompts and posts a link to the comparison on the pull request. Per promptfoo’s docs it needs Node.js 22.22.0 or later (Node 24 LTS recommended) on the runner, a pull-requests: write permission to comment, your provider API key as a repository secret, and optionally an actions/cache step for ~/.cache/promptfoo so unchanged cases are not re-billed.

on:
  pull_request:
    paths: ['prompts/**']
jobs:
  evaluate:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/setup-node@v6
        with: { node-version: '24' }
      - uses: actions/cache@v4
        with: { path: ~/.cache/promptfoo, key: "${{ runner.os }}-promptfoo-v1" }
      - uses: promptfoo/promptfoo-action@v1
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          github-token: ${{ secrets.GITHUB_TOKEN }}
          prompts: 'prompts/**/*.json'
          config: 'prompts/promptfooconfig.yaml'
          cache-path: ~/.cache/promptfoo

Step 3b — Or run DeepEval with pytest

DeepEval (Apache-2.0; python-v4.2.4 released September 22, 2026) plugs into pytest: you load an EvaluationDataset (in code, CSV, JSON or from Confident AI), build test cases, call assert_test() with your metrics, and run deepeval test run test_app.py — the same command locally and in a workflow .yml. It covers single-turn and multi-turn, end-to-end and component-level evaluation, and its docs include a guide to comparing runs against a baseline.

Done when: the eval job runs on a pull request and its result is visible on that pull request.

Step 4 — Set thresholds that block a merge

  • Hard rules fail the build every time.
  • Model-graded pass rate fails the build only when it falls more than a set margin (for example 5 points) below the main branch’s last run; otherwise post it as a warning.
  • Pin the grader model and temperature so a score change means your app changed, not the judge.

Step 5 — Control cost and time

Trigger on relevant paths only, cache responses, use a small model as the grader for routine checks (current API prices), and move the slow, expensive suite to a nightly schedule. Re-sample production traffic into the golden set monthly so the tests track what users actually ask.

Which tool for which team

promptfooDeepEval
LanguageNode/TypeScript, YAML configPython, pytest
LicenceMITApache-2.0
CI integrationOfficial GitHub Action, before/after PR commentdeepeval test run in any CI
StrengthsPrompt diffs, red-teaming, many providersRAG, agent and conversational metrics

For tracing and online evaluation after deployment, see how to monitor and evaluate AI agents in production and LangSmith vs Weights & Biases vs DeepEval.

Last verified: October 25, 2026. Requirements from promptfoo’s GitHub Action docs and DeepEval’s CI/CD docs; versions from GitHub releases.

Sources