C.W.K.
Stream
Lesson 12 of 12 · published

The Eval-Gate Pattern

~13 min · eval-gate, deploy, regression

Level 0Apprentice
0 XP0/101 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

The pattern that ties this whole track together

An eval gate is a job in your deploy pipeline that runs the eval suite against the candidate version and refuses to promote it if any agreed metric regressed.

The shape

  1. Build the candidate (model checkpoint, prompt set, code).
  2. Run eval against the candidate. Compare to the current production baseline.
  3. If candidate ≥ baseline within tolerance: promote, deploy.
  4. If candidate < baseline: fail the deploy. Surface the diff (which prompts regressed) on the PR or deploy failure.

What makes this hard

  • Baseline drift — when do you update the baseline? Auto-update on each successful deploy is fine for monotonic improvements; for behavior changes, human approval is needed.
  • Score noise — eval scores have variance. A 1% drop might be noise. Define tolerance bands.
  • Cost — full eval on every PR is expensive. Smoke gate on PRs, full gate on merge to main.
  • Slice regressions — overall score might be flat, but Korean inputs degraded by 8%. Slice metrics catch this.

The promise

An eval gate means the next time someone tweaks a prompt 'just to make this one case work', the gate will tell them what they broke. No more silent regressions in production.

Code

Full eval-gate workflow·yaml
name: eval-gate
on:
  push: { branches: [main] }
  pull_request: {}
permissions:
  contents: read
  pull-requests: write

jobs:
  eval:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v3
      - run: uv sync --all-extras --dev
      - name: Fetch baseline
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release download eval-baseline --pattern 'baseline.json' --output baseline.json
      - name: Run eval
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: uv run python -m evals.run --output candidate.json
      - name: Gate
        run: |
          uv run python -m evals.compare \
            --baseline baseline.json \
            --candidate candidate.json \
            --tolerance 0.02 \
            --report report.md
      - if: failure() && github.event_name == 'pull_request'
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          path: report.md

  promote-baseline:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    needs: eval
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          # On a successful main merge, promote the candidate to baseline
          gh release upload eval-baseline candidate.json --clobber
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

External links

Exercise

Stand up a minimal eval gate on one AI service: 10 examples, 1 scorer, a baseline stored as a release asset. Make the gate fail when scores drop more than 5%. Deliberately regress one example and confirm the PR turns red.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.