Research10 min read

Decision Models Lead, LLMs Review: Fast and Accurate SRE Diagnosis

Decision models lead the investigation; LLMs review the conclusions and write the report.

In this article
  1. How the agent works
  2. The agent in action
  3. Results on SREGym-Lite
  4. Can clearer questions improve the decisions?
  5. Conclusion

Site reliability engineering (SRE) agents diagnose incidents by inspecting logs, metrics, traces, and cluster state. At each step, they decide what to inspect next and which evidence supports a diagnosis. Decision models can make these repeated decisions quickly, which is especially valuable when responding to critical failures.

In our first study, the LLM agent led the investigation, with TypeSafe AI’s Jev supporting it by ranking tests and reviewing conclusions. In our second experiment, Jev handled diagnosis without an LLM: a programmatic collector gathered cluster evidence, and Jev chose which component to inspect and which observations to submit. That pipeline passed 76.2% of diagnoses on SREGym-Lite, but the collector could miss important evidence and Jev could favor the wrong clue.

In this post, we present a decision-model-led diagnosis agent, bringing the LLM back, but this time in a supporting role. The decision model chooses which tool to run on which target and uses the results to propose a root cause. After the investigation, the LLM reviews this choice against the collected evidence, either confirming it or replacing it with another supplied candidate. It cannot run tools or collect new evidence. Whether the LLM keeps or changes the cause, the decision model then selects observations supporting the final choice from the evidence already collected. The LLM uses those selected observations to write the diagnosis report.

We run two types of experiments to measure the benefit of LLM review. With review, the LLM can confirm or change the proposed root cause. Without review, we keep the decision model's choice. Both setups then select supporting observations and use the LLM to write the report.

Across 21 SREGym-Lite faults, with five attempts per fault in each setup, Jev passes 89.5% (94/105) of diagnoses with LLM review and 78.1% (82/105) without it. GPT-6 Luna Decisions passes 95.2% (100/105) with review and 79.0% (83/105) without it. Mean diagnosis time ranges from 31.9 to 41.5 seconds across these setups.

The improvements from LLM review also show us where the decision model went wrong. For each run where the LLM corrects the decision model's root-cause choice, we save the root-cause question, the evidence and possible answers shown to the decision model, and the LLM's corrected answer. We then test if clearer wording or answer choices help the decision model reach the corrected answer using the saved evidence, without rerunning the investigation.

How the agent works

We built the agent based on the pipeline presented in our last blog post. The main change is in the investigation. In our earlier pipeline, the decision model chose which component to inspect, and the pipeline followed a predefined routine to gather more evidence about it. In this new agent, the decision model also chooses which tool to run on which target at each step. Here is the implementation.

First, the programmatic collector reads the cluster state and scores each component using signals such as ongoing errors and warning events. It then checks the two highest-scoring components by reading their logs or inspecting their workload state.

Figure 1. The agent's workflow. If the LLM agrees, the original root cause is kept. If it disagrees, the agent uses the LLM's choice instead. Both paths lead to evidence selection and report writing.

Blue blocks are programmatic steps, teal blocks are decision-model steps, and orange blocks are LLM steps.

  1. Collector: Read the cluster state, looking for changes and signs of failure.
  2. Collector: Check logs or workload state for early signs of failure.
  3. Orchestration: Build the tool menu by listing the checks the agent can run next.
  4. Decision model, one call per step: Choose a check and likely cause. Decide if more evidence is needed.
  5. If a check is selected: Run the read-only tool and add its result to the notes. Loop back to build the tool menu for the next step.
  6. When a stop rule or budget ends the investigation: The LLM reviews the root cause, but cannot run tools. If it agrees, the agent keeps the decision model's choice. If it disagrees, the agent replaces the cause with the LLM's choice from the supplied candidates. Both paths continue to evidence selection.
  7. Decision model: Keep the observations that support the final root cause.
  8. LLM: Write and submit the report using the selected evidence.

The investigation then runs one step at a time. First, a list of possible checks is prepared programmatically from the evidence collected so far. One check might read the frontend's logs. Another might test whether it can reach another service. Checks linked to errors or earlier clues come first. By default, the list is built with a limit of 40 checks, plus submit_now to request an end to the investigation.

Then, the list of checks and the evidence collected so far are sent to the decision model together in one request. The questions include:

  • Which tool should run next, and on which component or connection? The model chooses a check from the prepared list. This answer determines both the tool and where it will run. The model can instead select submit_now to request an end to the investigation.
  • Does the previous tool's output show signs of a problem? The answer is saved alongside that output in the notes, so later steps can distinguish findings that suggest a problem from normal results. If the tool read logs, the model also identifies the kinds of errors reported.
  • Is there enough evidence to write a diagnosis? The answer can be yes or no.
  • Which root cause best fits the evidence so far? The model can answer "not yet known."

The evidence and root-cause questions are answered independently. Naming a possible cause does not mean there is enough evidence to finish.

The stopping rules then use these answers to decide whether to continue. Selecting submit_now does not submit the report. By default, the first request to stop is accepted if the model assigns it a probability of at least 0.5. If it is below 0.5, that first request is ignored. If the model selects submit_now again at the next step, the investigation can end even when it still says more evidence is needed. Step or time limits, or no remaining checks, can also end it.

If the investigation continues, the tool for the next check is run on the specified component or connection. When a request to stop is ignored, the highest-ranked available check other than submit_now is used instead. The tool's output is added to the investigation notes. A new step then begins with those updated notes and a new list of possible checks.

Once the investigation ends, the LLM reviews the proposed root cause using the collected evidence and the leading candidates. It can confirm the decision model's choice or replace it with another supplied candidate. It cannot run tools or collect new evidence.

Whether the cause was kept or changed, the decision model then uses yes/no questions to select observations from the notes that support the final cause. The LLM uses those selected observations to write the diagnosis report.

Explore the read-only tool menu · Figure 2

Figure 2. Read-only tools expose workload state, logs, traffic, metrics, backends, and cluster objects. The decision model chooses a tool and the component or connection to inspect; it does not generate shell commands.

Looks atToolWhat it shows
WorkloaddescribePod states, restarts, events, container settings
Workloadconfig_and_changesWho changed its spec and when, and the ConfigMaps and Secrets it reads
Workloadrelated_objectsVolume claims, Service accounts, policies and autoscalers around it
LogslogsOngoing and stopped error lines, and the components they name
Trafficservice_viewWhether its Services select its pods, with endpoints and ports
Trafficcall_edgesWho calls whom, and how often those calls fail
Trafficclient_checkFrom a caller's pod, whether the name resolves and the port answers
Metricsmetric_series15 minutes of CPU, memory, restarts, request rate, errors and latency
Backendsbackend_probeA read-only health command inside a database or queue
Clustercluster_objectsWebhooks, quotas, network policies, RBAC, DNS, nodes, storage
Clusterobject_viewThe content of one object, such as a ConfigMap
ClustereventsRecent Kubernetes events, warnings first

The agent in action

Let us look at a Jev run on SREGym-Lite's wrong_dns_policy_astronomy_shop fault in the Astronomy Shop application.

In this fault, the frontend Deployment's DNS settings had been changed. Its Pod sent queries to an external DNS server instead of the cluster's DNS. The frontend could no longer resolve the names of the services it called.

The programmatic collector summarized the 25 components in the cluster and ranked them by signs of failure. These were the top three:

deployment/frontend
  1/1 ready; dnsPolicy and dnsConfig.nameservers changed 134s before the first symptom
  54 ongoing error lines, e.g. Name resolution failed for target dns:product-catalog:8080
daemonset/otel-collector-agent
  3/3 ready; restarted 140s before the first symptom, no setting changed
  8 ongoing error lines, e.g. call to /stats/summary endpoint failed
deployment/postgresql
  1/1 ready; memory 90Mi of its 100Mi limit

Jev first judged that the evidence was insufficient and chose to test whether the frontend could reach product-catalog.

Figure 3. Jev first chooses a client check from frontend to product-catalog, with probability 0.62. All choice bars use a 0–1 scale; the yes/no judgments below show the probability of yes.

Step 1. One request to Jev, 0.22 S. Which tool should run next? Top 6 of 41 options.

ToolTargetProbability
client_checkfrontend → product-catalog0.62
describeproduct-catalog0.13
logsproduct-catalog0.07
config_and_changesfrontend0.05
client_checkfrontend → cart0.03
submit_now0.03

Is the last result abnormal? No, probability of yes 0.34. Is the evidence enough? No, probability of yes 0.39.

Where did the fault start?

  • cluster_object: 0.37
  • Deployment frontend: 0.30
  • Deployment product-catalog: 0.14

The test showed that the frontend Pod could not resolve the product-catalog Service name. Checks toward cart and checkout failed in the same way, although none of those Services had been changed. After seven tool-use decisions, Jev stopped and selected cluster_object as the root cause. This catch-all option names no specific object. Jev still judged the evidence insufficient; the choice to submit and the sufficiency judgment were separate answers.

Figure 4. At the last step, submit_now is the leading tool choice at only 0.17, and cluster_object leads the root-cause choices at 0.62. The model still answers no to evidence sufficiency. The LLM review then replaces the catch-all with the frontend Deployment.

Step 7. One request to Jev, 0.16 S. Which tool should run next? Top 6 of 41 options.

ToolTargetProbability
submit_now0.17
object_viewService checkout0.14
logscart0.13
config_and_changesfrontend0.10
client_checkfrontend → product-reviews0.09
describecart0.07

Is the last result abnormal? No, probability of yes 0.11. Is the evidence enough? No, probability of yes 0.37.

Where did the fault start?

  • cluster_object: 0.62
  • Deployment frontend: 0.21

The LLM compared Jev's leading candidates and their evidence. The frontend's DNS settings had changed just before the symptoms, while the Services it called were unchanged. The reviewer used this evidence to replace cluster_object with the frontend Deployment.

Finally, the decision model chose the observations that support this root cause, and the LLM wrote the report from them. The submitted diagnosis began like this:

The root cause is the frontend Deployment, which serves the frontend Service in the astronomy-shop namespace. Its DNS settings changed shortly before symptoms began. The new dnsPolicy or dnsConfig prevents the frontend pod from resolving in-cluster Service names, so requests from the frontend fail before they can reach their targets.

The diagnosis took 44.3 seconds. LLM review and report writing took about 23 seconds; the decision model's API calls took about 1 second. The remaining roughly 20 seconds were spent outside those model calls, including startup, collecting cluster state, running tools, and coordinating the investigation.

Results on SREGym-Lite

We evaluated Jev and GPT-6 Luna Decisions on the same 21 SREGym-Lite faults used in our previous diagnosis post. Each fault had five attempts with review and five without: 105 diagnoses per setup, 420 in total. GPT-6 Sol at high reasoning effort reviews the root cause and writes the report. Without review, it only writes the report.

We scored every diagnosis with GPT-6 Astra at high reasoning effort. A diagnosis passes if its SREGym composite score is at least 0.70. End-to-end diagnosis times below are means over all attempts, excluding the fixed 120-second observation wait and judging.

What does LLM review add?

Jev
MeasureNo reviewWith review
Diagnosis passes78.1%82/10589.5%94/105
Mean time31.9 s38.4 s
Cost / diagnosis$0.017$0.033
GPT-6 Luna Decisions
MeasureNo reviewWith review
Diagnosis passes79.0%83/10595.2%100/105
Mean time36.9 s41.5 s
Cost / diagnosis$0.025$0.041
Full measurements: calls, tokens, latency and cost
MeasureGPT-6 Luna Decisions with reviewGPT-6 Luna Decisions without reviewJev with reviewJev without review
DIAGNOSIS
Judged diagnosis passes100/105 (95.2%)83/105 (79.0%)94/105 (89.5%)82/105 (78.1%)
Mean score (0–100)92.180.089.782.4
Faults passed in all five attempts17/2113/2116/2112/21
Faults failed in all five attempts0/212/211/211/21
Mean diagnosis time41.5 s36.9 s38.4 s31.9 s
DECISION MODEL
Calls1237 (11.8 per attempt)1210 (11.5 per attempt)944 (9.0 per attempt)924 (8.8 per attempt)
Mean total API time per attempt3.13 s3.08 s1.67 s1.60 s
Mean latency per call0.27 s0.27 s0.19 s0.18 s
Input tokens11.05 M (105K per attempt)10.82 M (103K per attempt)8.96 M (85K per attempt)8.82 M (84K per attempt)
Output tokens000.97 M (9.2K per attempt)0.94 M (9.0K per attempt)
Estimated cost$1.10$1.08$0.38$0.37
LLM (GPT-6 SOL, HIGH EFFORT)
Calls210 (2 per attempt)105 (1 per attempt)210 (2 per attempt)105 (1 per attempt)
Mean review/report time per attempt18.9 s13.9 s22.3 s15.8 s
Input tokens2.60 M (24.7K per attempt) 1.49 M cached (14.2K per attempt)1.14 M (10.8K per attempt) 0.73 M cached (7.0K per attempt)2.57 M (24.4K per attempt) 1.56 M cached (14.9K per attempt)1.13 M (10.8K per attempt) 0.80 M cached (7.6K per attempt)
Output tokens0.073 M (0.69K per attempt)0.057 M (0.54K per attempt)0.074 M (0.70K per attempt)0.057 M (0.54K per attempt)
Estimated cost$3.24$1.52$3.06$1.40
TOTAL
Estimated cost$4.34 ($0.041 per attempt)$2.61 ($0.025 per attempt)$3.44 ($0.033 per attempt)$1.77 ($0.017 per attempt)

Report time includes evidence selection.

Figure 5. Review improves passes for both decision models at a small additional cost. Time and estimated cost are per diagnosis; both setups use GPT-6 Sol to write the report.

With review, Jev passes 12 more diagnoses and GPT-6 Luna Decisions passes 17 more. Mean diagnosis time increases by 6.6 seconds for Jev and 4.6 seconds for Luna. Estimated cost increases by about 1.6 cents per diagnosis in both setups.

Most model time and inference cost go to the LLM, not to the decision model. With review, decision-model calls take a total of 1.67 seconds per diagnosis for Jev and 3.13 seconds for Luna, on average.

Where does review help?

Figure 6. Passes out of five attempts per fault. Blue cells mark mostly passing setups; orange cells mark mostly failing ones.

FAULTLUNA REVIEWLUNA NO REVIEWJEV REVIEWJEV NO REVIEW
admission_webhook_outage5/55/55/55/5
cronjob_sidecar_blocks_completion4/54/55/54/5
duplicate_pvc_mounts5/51/55/51/5
edge_request_filter_cpu_saturation4/55/54/54/5
env_variable_shadowing5/55/54/55/5
finalizer_deadlock_controller5/55/50/51/5
internal_traffic_policy_local5/55/55/53/5
kafka_poison_pill_hol_block5/54/55/55/5
mutating_webhook_resource_limits4/51/55/54/5
namespace_memory_limit5/55/55/55/5
network_policy_block5/55/55/55/5
readiness_probe_misconfiguration5/55/55/55/5
rolling_update_misconfigured5/54/55/55/5
search_rate_retry_collapse5/50/54/50/5
secret_rotation_stale_env_credentials5/50/55/55/5
service_dns_resolution_failure5/55/55/55/5
service_wrong_pod_selection5/55/55/55/5
unschedulable_incorrect_port_assignment5/55/55/55/5
valkey_auth_disruption3/54/52/52/5
wrong_dns_policy5/55/55/53/5
wrong_service_selector5/55/55/55/5

On the duplicate PVC mounts fault, both decision models pass 5/5 attempts with review, compared with 1/5 without it. On search-rate retry collapse, neither passes an attempt without review. With review, Luna passes 5/5 and Jev passes 4/5.

Review does not help on every fault. On the cleanup-controller fault, finalizer_deadlock_controller, Jev with review passes 0/5 attempts, while Luna passes 5/5 with or without review. On valkey_auth_disruption, Jev passes 2/5 in both setups. Luna passes 3/5 with review and 4/5 without it.

In one failed cleanup-controller run, the reviewer replaced cluster_object with deployment/cleanup-controller. The report described repeated HTTP 403 denials from the Kubernetes API, but missed the cause: a ClusterRole lacked permission to patch ConfigMaps. Naming the affected Deployment was not enough to explain the failure.

How does this compare with LLM agents?

With review, Luna matches the diagnosis pass rate of Codex with GPT-5.6 Sol (max) at roughly 15× lower estimated cost per diagnosis. Jev comes close to Claude Code with Claude Opus 5 at roughly 28× lower estimated cost.

SREGym-Lite · Sep 4 cohort · 21 faults

Diagnosis performance vs. cost

JevLuna DecisionsEarlier Jev pipelineCodexClaude Code

Scroll horizontally to see all models →

Diagnosis pass rate versus mean inference costHigher means more diagnoses passed. Farther left means lower cost. Hover or focus a point for its measurements. This compares separate experiments on the same 21 fault IDs.Diagnosis pass rate (%) ↑5060708090100$0.001$0.01$0.10$1← Mean diagnosis cost ($ / attempt, log scale)Earlier Jevwithout an LLMGPT-6 AstramaxGPT-6 AstramediumGPT-6.1 SolmaxGPT-6.1 SolmediumGPT-5.6 SolmaxClaude Opus 5GPT-5.6 TerramaxGPT-5.6 LunamaxGPT-5.6 SolmediumClaude Sonnet 5Claude Opus 4.8Jevwith reviewJevno reviewLunawith reviewLunano review

Diagnosis results on the same 21 SREGym-Lite faults, using our own runs. For the current agent, filled markers include root-cause review and outlined markers do not. Both versions use LLM report writing. The decision-model setups ran five attempts per fault; the LLM agents ran three. Time and inference cost are means per diagnosis, including review and report writing where used. Times exclude the fixed 120-second observation wait. Repair and judging are excluded.

With review, mean diagnosis time is 41.5 seconds for Luna and 38.4 seconds for Jev. Codex with GPT-5.6 Sol (max) averaged 211 seconds per diagnosis, while Claude Code with Claude Opus 5 averaged 210.1 seconds.

Does the choice of LLM matter?

To test the choice of LLM, we replaced GPT-6 Sol with GPT-5.6 Sol at high reasoning effort and GPT-5.6 Luna at xhigh effort. For both GPT-5.6 models, we kept the recorded investigations and reran report writing with and without root-cause review. The table includes GPT-6 Sol's results from the separate runs in our main experiment. The same judge scored every diagnosis.

Figure 7. Diagnosis passes and mean scores with each LLM, with and without root-cause review. Mean rubric scores are shown on a 0–100 scale.

LLM review and report writingGPT-6 Luna Decisions decision modelJev decision model
WITH REVIEW
GPT-6 Sol, high effort100/105 (95.2%) mean score 92.194/105 (89.5%) mean score 89.7
GPT-5.6 Sol, high effort91/105 (86.7%) mean score 85.384/105 (80.0%) mean score 85.0
GPT-5.6 Luna, xhigh effort88/105 (83.8%) mean score 83.986/105 (81.9%) mean score 83.2
WITHOUT REVIEW
GPT-6 Sol, high effort83/105 (79.0%) mean score 80.082/105 (78.1%) mean score 82.4
GPT-5.6 Sol, high effort80/105 (76.2%) mean score 79.775/105 (71.4%) mean score 76.0
GPT-5.6 Luna, xhigh effort81/105 (77.1%) mean score 80.178/105 (74.3%) mean score 80.0

Review improved the results with every LLM. Each GPT-5.6 model passed 7 to 11 more diagnoses per decision model with review than with report writing alone. With review, GPT-6 Sol passed 8 to 12 more diagnoses than either GPT-5.6 model. Of the three LLMs tested, it produced the most passing diagnoses from the same recorded investigations.

Can clearer questions improve the decisions?

For each run where review changed the root cause, we compared two reports. One was the submitted report using the LLM's reviewed choice. The other was generated afterward using the decision model's original choice. Both used evidence from the same saved investigation, rather than the separate runs with and without review compared above.

Review corrected 14 of Luna's 105 diagnoses and 13 of Jev's, changing them from failing to passing. Only one changed from passing to failing. We scored each report twice and counted a correction only when the original failed both times and the reviewed report passed both times.

For each corrected case, we saved the root-cause question, its evidence and answer choices, and the LLM's corrected answer. We then tested if clearer wording or answer choices would help the decision model select that cause using the same evidence.

We tried two changes:

  • Remove a vague answer. We removed the catch-all cluster_object option when the evidence pointed to specific objects, as in the DNS example.
  • Compare two candidates directly. We asked a follow-up question containing only the original choice and another candidate supported by the evidence. We asked it twice, reversing the answer order, and changed the choice only if the model selected the alternative both times.

With these changes, the decision model selected the LLM's corrected root cause in about a third of the corrected cases. These tests reused saved questions and evidence without rerunning the investigation. They show that the model's choice can improve, not that the full agent would pass more diagnoses.

Conclusion

With LLM review, the agent passes 89.5% of diagnoses with Jev and 95.2% with GPT-6 Luna Decisions. The decision model guides the investigation, while the LLM checks the proposed cause and writes the report. The LLM can improve a diagnosis without choosing every tool the agent runs.

Next, we plan to build these question changes into the agent and measure whether they improve diagnosis results in live runs. We also want to collect evidence that makes related causes easier to distinguish. The reviewed cases could eventually help train the decision model to make better choices with less need for LLM review.