AI SRE benchmark

19 Kubernetes faults. 3 agents. Every trace public.

We break a small app on a kind cluster in known ways, hand each agent only the alert, and grade the root cause against the fault we injected. A judge model scores every run. A person has checked Aurora’s verdicts; HolmesGPT’s and K8sGPT’s are the judge’s, read over by a second model, not yet checked by a person. Misses are published with the hits. Arvo builds Aurora and wrote the scenarios and the grading criteria; read the numbers with that in mind.

Auroracommit 87d22baf
89%
34 correct, 4 partial, 0 wrong or no answer, of 38 graded runs
median 154 s · $0.35 a run
bedrock/us.anthropic.claude-sonnet-5
HolmesGPT0.43.0
82%
31 correct, 6 partial, 1 wrong or no answer, of 38 graded runs
median 45 s
bedrock/us.anthropic.claude-sonnet-5
K8sGPT0.4.40
Not scored against the other two
21 partial, 5 wrong, 12 no answer, of 38 runs. 12 runs printed “No problems detected”. It takes no alert and scans the namespace; see below.
median 13 s for two analyze passes
us.anthropic.claude-sonnet-4-5 (K8sGPT sends temperature, which Bedrock rejects for Sonnet 5)

Aurora has 3 more correct runs of 38. Fisher exact test on correct against not, two-sided: p = 0.52. That gap is not significant; with 38 runs per agent and a model judge, read the two as roughly even.

#FaultAlert the agent receivesAuroraHolmesGPTK8sGPT
01Worker OOMKilled after a batch size changeKubePodCrashLooping
02Log shipper sidecar OOMKilled, app container healthyKubePodCrashLooping
03Frontend rollout stuck on a mistyped image tagKubeDeploymentRolloutStuck
04New api pods blocked on a Secret that does not existKubeDeploymentRolloutStuck
05Frontend crash loop from an invalid nginx configKubePodCrashLooping
06api restarts because the liveness probe targets the wrong portKubePodCrashLooping
07api Service selects no pods after a selector changeHighErrorRate
08Worker pod Pending, CPU request larger than any nodeKubePodNotReady
09api failing because redis is Pending on an unbindable PVCKubePodCrashLooping
10api crash loop from a wrong REDIS_HOSTKubePodCrashLooping
11frontend 5xx from a wrong api Service targetPort, next to a noisy but harmless workerHighErrorRate [critical] namespace=shop service=frontend
12Two faults at once, worker OOM and a frontend Service selecting no pods; the alert covers only the workerKubePodCrashLooping [warning] namespace=shop deployment=worker
13frontend 5xx because a NetworkPolicy blocks api to redisHighErrorRate [critical] namespace=shop service=frontend
14api rollout stuck because a ResourceQuota forbids the surge podKubeDeploymentRolloutStuck [warning] namespace=shop deployment=api
15One in three api requests fails because a stray Deployment's pods carry app=apiHighErrorRate [warning] namespace=shop service=frontend
16New api pods crash because their dnsConfig search domains are for another cluster domainKubePodCrashLooping [warning] namespace=shop deployment=api
17Worker OOMKilled every few minutes by a slow leak in its code; logs look cleanKubePodCrashLooping [warning] namespace=shop deployment=worker
18api rollout stuck on an init container waiting for a Service that does not existKubeDeploymentRolloutStuck [warning] namespace=shop deployment=api
19Half of frontend requests fail; one frontend pod loaded an edited ConfigMap, the other still runs the old configHighErrorRate [warning] namespace=shop service=frontend

How a run works

  1. kind v0.33.0, Kubernetes v1.37.0, 3 nodes. The shop app: nginx, a Python API, a worker, redis, a load generator. Synthetic, no customer code.
  2. One fault is injected with the scenario's break.sh; check.sh proves it is visible.
  3. Each agent gets the alert text. Aurora's prompt adds "Cluster: aurora-lab (kubeconfig). Investigate and find the root cause."; HolmesGPT's adds "Namespace shop, cluster kind-aurora-lab. Find the root cause and say what changed." K8sGPT has no notion of an alert and scans the namespace. All three got the same kind admin kubeconfig, each behind its own guard: Aurora's default read-only observability_only command policy, HolmesGPT's command allow-list, and K8sGPT's read-only analyze. No transcript shows a mutating command running.
  4. HolmesGPT ran through holmes ask with default toolsets and a 40-step cap it never reached; the lab has no Alertmanager, so holmes investigate was not used. Its own command allow-list blocked kubectl rollout history in 12 runs, 2 of its 7 non-correct runs among them; we did not rerun those with the command allowed. Aurora's policy had the same block in the first lab report.
  5. Correct means every must_identify item in the scenario is stated and no listed wrong answer is asserted; partial means some items. Judge: us.anthropic.claude-opus-5-5, the same vendor as every model under test. The prompt does not name the agent, though the tool names in each command list give it away.

Every tool ran twice per scenario. Aurora's 38 verdicts were checked by a person, who changed 0 of them. HolmesGPT’s and K8sGPT’s were graded by the judge model, read over by a second model (which agreed on all 76), then re-graded from scratch by a third. The third agreed on all 38 HolmesGPT verdicts and disputed 6 K8sGPT labels, where K8sGPT only restated the symptom: the judge said partial or wrong, the reviewer said no answer. We kept the judge’s labels, and every grade file carries both opinions. No person has checked these 76 yet. As a bias check, every answer was graded again with the agent’s name, its tool names and the cluster name removed from the judge’s prompt (runner/grade_blind.py). The blind verdict matched the published one for 38 of 38 Aurora, 37 of 38 HolmesGPT, 36 of 38 K8sGPT runs; blind correct counts are Aurora 34, HolmesGPT 30, K8sGPT 0. Every disagreement is listed in runs/blind-regrade.md in the repo. Aurora's runs are from commit 87d22baf, the day before the scenarios were written, so it was not tuned on them. The fixes the first lab report prompted are open pull requests on the Aurora repo; the six reruns on the fixed build are in the lab repo and not in this table.

What is not comparable: K8sGPT's row. Its analyzers flag objects and the model explains the flag, so it is scored on a criterion built for alert-driven investigators. It ran on Sonnet 4.5 because it sends a temperature parameter that Bedrock rejects for Sonnet 5; we did not try a proxy that strips it. Times: Aurora's include contention from its own background jobs in the lab stack (REPORT.md in the repo); K8sGPT's cover two analyze passes, JSON then text. Costs are recorded for Aurora only; HolmesGPT's token counts were not captured.

Rerun it, or add your agent

Everything is in Arvo-AI/aurora-lab: scenarios, the runner, every transcript and grade, and this table as results.json.

git clone https://github.com/Arvo-AI/aurora-lab && cd aurora-lab
./lab.sh up && ./lab.sh break 03-bad-image-tag
./runner/h2h.sh 03-bad-image-tag runs/mine

To put another agent on the board, open an issue titled "Benchmark: <agent>" with a script that takes a kubeconfig and the alert text and prints the root cause. We run it on all 19 faults and publish the result, whatever it is. Submit an agent.

Read the full write-up: lab report v1. Fix the faults yourself: runbooks, each with Aurora's real trace.

Results updated 2026-10-21. Scenario and tool versions are recorded with every run in the repo.