Agent Arena

Continuous evaluation

arena watch — catching a model that drifted since you picked it.

A model choice decays. Providers update models silently, prompts drift, traffic shifts, prices change. arena watch re-evaluates a project and compares the fresh result against its own recent runs, so a decision made three weeks ago stays an answer rather than a snapshot.

The basic loop

arena watch --project projects/my_project
my_project — run_20260904_074818_782937:
    sim_small: first watch run — no history to compare against yet.

Run it again after another evaluation has happened, and it compares:

my_project — run_20260904_090201_9e3b1c:
  ! sim_small dropped 50 points versus its last 1 run(s) (85% -> 35%).

The ! marks a flagged model — one that moved by more than the drift threshold (5 percentage points by default), or whose status changed (a model that started clearing its constraints and stopped, or the reverse).

What counts as drift

The baseline is the mean composite over recent prior runs, not just the run immediately before. Averaging absorbs one noisy prior run instead of chasing it — a single unlucky sweep should not itself look like drift.

A model that has been steadily DISQUALIFIED across every run is not flagged again each time; only a change in status is drift. Read the sentence carefully:

  • "dropped 12 points" / "improved by 12 points" — a real accuracy move
  • "changed status: ranked -> failed" — it started failing a constraint
  • "disqualified this run" — steady-state, not new information
  • "skipped this run" — a credential problem, not a model problem
  • "first watch run" — nothing to compare against yet

Configuring it

watch:
  drift_threshold: 0.05    # composite points that count as drift
  webhook: https://hooks.example.com/agent-arena

Both are optional, and a CLI flag always overrides the config value for one run:

arena watch --project p --threshold 0.1 --webhook https://...

Options

Flag Does
--threshold Composite delta that counts as drift (default 0.05, or watch.drift_threshold)
--history N How many prior runs form the baseline (default 5)
--webhook URL POST a JSON report here when anything is flagged
--fail-on-drift Exit 1 if anything is flagged — for a CI gate
--loop --interval S Keep re-running every S seconds instead of once
--json One JSON line per tick, for piping elsewhere
--quiet Only print flagged models

Running it on a schedule

arena watch does one evaluation per tick — the same cost as arena evaluate against that project. Two ways to schedule it:

A cron entry, or a scheduled GitHub Actions workflow (the more common choice — someone else's scheduler, rather than a process you keep alive):

on:
  schedule:
    - cron: "0 9 * * *"   # daily at 09:00 UTC

jobs:
  watch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install agent-arena
      - run: arena watch --project projects/my_project --fail-on-drift

--loop, for a long-running process (a container, a small VM):

arena watch --project p --loop --interval 86400   # once a day

Prefer the scheduler when you have one. --loop reinvents what cron already does, and exists for environments where a scheduler is the harder thing to set up.

The webhook payload

{
  "project": "my_project",
  "run_id": "run_20260904_090201_9e3b1c",
  "flagged": [
    {
      "model_key": "sim_small",
      "current_composite": 0.35,
      "baseline_composite": 0.85,
      "delta": -0.50,
      "current_status": "ranked",
      "status_changed": false,
      "flagged": true,
      "sentence": "sim_small dropped 50 points versus its last 1 run(s) (85% -> 35%)."
    }
  ]
}

Fires only when something is flagged, and never raises on delivery failure — a broken webhook is reported on stderr but does not make the evaluation itself look like it failed.

Watching for pricing drift

arena models and arena validate also warn when the shipped price catalog itself is stale (past 90 days since as_of):

! pricing     catalog is 94 days old (as of 2026-06-01) — verify against your
              provider before deciding on cost

This is a different kind of drift — the catalog going stale, not a model's accuracy — but it is the same underlying concern: a number you are relying on may no longer be true.