ContentsAverta
Pre-registered study

Averta

Early failure prediction for AI coding agents, evaluated on 5,976 recorded sessions. A 2.1 KB CPU model recovers about half the token savings of a 0.6B neural monitor.

0.677AUROCvs 0.500 baselines
0.191recall @ 5% FPRbar was 0.250
0.18 msCPU latency2.1 KB model
8.4%tokens savedpaper reports 14.6–20.4%

Failure turns out to be predicted by declining action novelty rather than by repeated errors, the opposite of the starting hypothesis. The bar those numbers are judged against was committed to source control before any model was trained.

The question

What this set out to test, and what it found.

A coding agent either resolves its task or it doesn't. A session heading nowhere keeps spending tokens that produce nothing, so detecting that early is worth doing. But stopping a session that would have recovered is worse than letting it run. That asymmetry is the whole problem: the value is in catching doomed sessions, the cost is in killing salvageable ones.

Fail-Fast, Restart-Smart (Wang et al., 2026) approaches this with a 0.6B neural monitor. Averta asks whether engineered trajectory features and a cheap classifier can do useful work at a fraction of that inference cost.

Verdict

The pre-registered gate was not met, across two attempts judged against identical criteria. Four of five criteria passed; recall at a 5% false-positive budget reached 0.191 against a required 0.25.

What the work does establish: a 2.1 KB linear model at 0.18 ms CPU inference recovers roughly half the token savings reported for a 0.6B neural monitor. The cost reduction is large and the capability gap is real.

Every number on this page was measured before it was written. Criteria were committed to source control before any model existed, so they could not be relaxed to fit a disappointing result.

Data

One corpus, because only one had labels.

5,976sessions
8.2%resolve rate
11repositories
237,132turn records
4,684error signatures

Training data comes from SWE-Gym/OpenHands-Sampled-Trajectories. A survey of six public trajectory corpora found it to be the only one carrying both outcome classes, the others are supervised fine-tuning sets that store the agent's patch but never whether it worked.

Two properties shape everything downstream. The positive class is rare, so metrics that tolerate imbalance are required. And session length barely separates the classes: resolved sessions average 39.86 turns against 39.66 for unresolved. Prior work describes failing agent runs as tending to run longer; that does not reproduce here.

The source carries no declared license, so this project does not redistribute it. Raw trajectories are downloaded locally and excluded from version control; only derived statistics, figures and model artifacts are published.

Method

Three constraints, each guarding against a specific way of fooling yourself.

Prefix-only features

A feature computed at turn t reads turns[0:t] and nothing else, never the total length, never the outcome. A test suite shuffles, truncates and extends the unseen tail and asserts the feature vector is byte-identical, and checks that features at turn 6 are the same whether the session runs to 12 turns or 200.

Absolute turn indices

Evaluating at “40% through the session” requires knowing the total length, which is unavailable while a session is running. Evaluation uses turns 3, 5, 10, 20 and 40. Each cut has a different population, since only sessions that reached that turn appear, and the resolve rate is reported per cut so the shift stays visible.

Repository-grouped splits

Every row from a repository lands in one fold. Rows sharing a codebase are not independent, so splitting by row would let a model memorise a repository and be rewarded for it. Confidence intervals resample repositories rather than rows for the same reason, row-level bootstrap reports intervals that are too narrow under clustering.

Polarity

The positive class is failure, so the false positive rate means “sessions that would have resolved but were flagged” - the quantity worth constraining. Average precision is reported on the minority class instead, with its polarity named. Accuracy is never reported: at a failure rate of 88.79%, always predicting failure scores 0.89 and is useless.

Results

Turn 10 · 4,381 sessions · 88.8% failure rate · 5 repository-grouped folds · out-of-fold predictions pooled

Baselines greyed. Best non-baseline model highlighted.
modelAUROC95% CIAUPRCR@5%FPRBrier
majority0.500[0.500, 0.500]0.1270.0000.2500
turn_index_only0.500[0.500, 0.500]0.1270.0000.2500
error_repeat_only0.521[0.484, 0.557]0.1150.0770.2489
logistic0.677[0.651, 0.697]0.1980.1910.2268
random_forest0.653[0.626, 0.669]0.1860.1610.1589
hist_gradient_boosting0.626[0.593, 0.646]0.1680.1620.1806
xgboost0.649[0.605, 0.672]0.1870.1540.1973

Against the pre-registered criteria

pre-registered criterionresult
auroc >= 0.65pass
auroc ci lower >= 0.6pass
auprc >= 0.18pass
recall@5% fpr >= 0.25NOT MET
beats turn-index baselinepass

The shortfall is robust: it holds at every cut point tested and under any model-selection rule. The best recall at a 5% false-positive budget anywhere on the curve is 0.191.

AUROC by cut point0.450.550.650.7535102040best model: 0.513 at 3best model: 0.650 at 5best model: 0.677 at 10best model: 0.652 at 20best model: 0.615 at 40best modelbaselines: 0.500 at 3baselines: 0.500 at 5baselines: 0.500 at 10baselines: 0.500 at 20baselines: 0.500 at 40baselinescut point (turn index)AUROC
Shaded band is the 95% interval, resampling repositories rather than rows. Cut points are spaced evenly because they are ordered labels, not a continuous axis. Each cut has a different population, only sessions that reached that turn appear, so this is not one model tracked over time.

Two attempts

Both reported. Identical criteria for each.

Attempt 1 used 23 aggregate counts over the prefix. AUROC 0.668, recall 0.155. Permutation importance showed one feature dominating, n_repeated_calls, a flat count of tool calls reissued with byte-identical arguments, while every error-based feature was negligible.

That pointed at ordering as the missing ingredient. A count knows an action recurred; it cannot express that the agent is cycling A-B-A-B, or how far back it reached to repeat itself.

Attempt 2 added 10 sequence-structure features. Recall rose from 0.155 to 0.191 and AUROC from 0.668 to 0.677, real movement on exactly the failing criterion, but not enough to clear it.

AUROC drop when the feature is shuffled, under the same grouped folds.
featureattempt 1attempt 2
distinct_action_ratio-0.159
novelty_rate_recent-0.153
n_errors0.0230.084
action_bigram_repeat_max-0.078
n_repeated_calls0.1980.030

n_repeated_calls collapsed once ordering was represented properly, it had been a proxy for structure it could not express. The two strongest features now both measure declining action novelty.

Modelling stopped after two attempts. The gains were real but shrinking, the mechanism is understood, and a third round of feature invention against a bar that had already failed twice would be threshold-shopping under another name.

What drives it

The expectation was wrong, and measurement is what corrected it.

Permutation importancedistinct_action_ratiodistinct_action_ratio: 0.1780.178novelty_rate_recentnovelty_rate_recent: 0.1710.171action_bigram_repeat_maxaction_bigram_repeat_max: 0.0800.080n_editsn_edits: 0.0720.072n_errorsn_errors: 0.0510.051chars_recentchars_recent: 0.0380.038max_call_repeatmax_call_repeat: 0.0370.037chars_totalchars_total: 0.0360.036n_repeated_callsn_repeated_calls: 0.0350.035action_trigram_repeat_maxaction_trigram_repeat_max: 0.0330.033
AUROC lost when each feature is shuffled within the held-out fold. One series, so one colour, the bar length already encodes magnitude.
featureAUROC drop when shuffled
distinct_action_ratio0.1777
novelty_rate_recent0.1708
action_bigram_repeat_max0.0805
n_edits0.0723
n_errors0.0510
chars_recent0.0382
max_call_repeat0.0368
chars_total0.0362
n_repeated_calls0.0348
action_trigram_repeat_max0.0327

The prior expectation was that a recurring error signature would dominate. It is close to worthless in isolation, AUROC 0.521 alone. Failure is predicted by declining action novelty: the share of actions that are distinct, and the share of recent actions never issued before. A session heading nowhere is one that has stopped trying new things, which is a different phenomenon from one that keeps hitting the same wall.

Inference cost

Single-row latency, because the monitor scores one live session per turn.

0.18 msp50 latency
2.1 KBmodel size
0.6B paramsthe neural monitor
modelp50 msp95 mssize KB
logistic0.1820.1892.1
random_forest26.80537.97311,206.9
hist_gradient_boosting10.65518.715524.1
xgboost0.1780.217489.3

The most accurate model is also the smallest and fastest by a wide margin. Plausible cause: with 33 features, 491 positives and repository-grouped evaluation, trees fit repository-specific thresholds that do not survive the group boundary.

Calibration

A bug the plot caught, kept visible because the before-curve is the lesson.

Every model is fitted with class weighting, which is correct for ranking but leaves the output on a re-balanced scale. A raw score of 0.35 corresponded to an observed failure rate near 0.82. Rank-based metrics are unaffected, but any number shown to a person has to mean what it says.

Isotonic regression fitted on out-of-fold scores corrects it, moving the Brier score from 0.2268 to 0.0948. Fitting the calibrator on training predictions would have learned the model's own overconfidence and reported it back as calibrated.

Calibration, before and after isotonic regression00.250.50.75100.250.50.751ideal: 0.000 at 0ideal: 1.000 at 1idealraw (0.227): 0.714 at 0.0621468raw (0.227): 0.789 at 0.173933raw (0.227): 0.702 at 0.250926raw (0.227): 0.822 at 0.353796raw (0.227): 0.868 at 0.445823raw (0.227): 0.905 at 0.548242raw (0.227): 0.929 at 0.633714raw (0.227): 0.938 at 0.753333raw (0.227): 0.966 at 0.825493raw (0.227): 0.975 at 0.951064raw (0.227)calibrated (0.095): 0.500 at 0.5calibrated (0.095): 0.686 at 0.685535calibrated (0.095): 0.789 at 0.789037calibrated (0.095): 0.874 at 0.874239calibrated (0.095): 0.941 at 0.940626calibrated (0.095)predicted failure probabilityobserved failure rate
Brier score in parentheses. Both curves are shown deliberately, the raw one is the instructive half, since it is what class weighting does to the output scale. Showing only the corrected version would hide why the step exists.

Savings against harm

What intervention buys, and what it costs.

Highlighted row is the operating point nearest a 5% false-positive budget.
thresholdrecallFPRest. tokens savedsuccesses killed
0.550.5020.24633.6%121
0.600.4230.18727.2%92
0.650.2830.09615.8%47
0.700.2410.07713.1%38
0.750.2190.06911.0%34
0.800.1830.0478.4%23
0.850.0610.0183.1%9
0.900.0500.0102.4%5
0.950.0230.0101.0%5

At a comparable budget, 4.7% against the paper's 5% target, this reaches 8.4% estimated token savings where the 0.6B neural monitor reports 14.6–20.4%. Roughly half the value, at a fraction of the size.

Tokens are estimated from content length; the corpus records no token counts. Savings count only what would have been spent after the cut. Sessions wrongly terminated are never netted off the savings, the two are not commensurable and a single “net” figure would let the harm disappear into an aggregate.

tokens saved (%) against false positive rate08.416.825.233.60.010.0180.0470.0690.0770.0960.1870.2465% budgettokens saved (%): 2.403 at 0.01tokens saved (%): 1.024 at 0.01tokens saved (%): 3.121 at 0.018tokens saved (%): 8.360 at 0.047tokens saved (%): 11.015 at 0.069tokens saved (%): 13.057 at 0.077tokens saved (%): 15.826 at 0.096tokens saved (%): 27.153 at 0.187tokens saved (%): 33.616 at 0.246tokens saved (%)false positive ratetokens saved (%)
successes killed against false positive rate030.260.590.81210.010.0180.0470.0690.0770.0960.1870.2465% budgetsuccesses killed: 5.000 at 0.01successes killed: 5.000 at 0.01successes killed: 9.000 at 0.018successes killed: 23.000 at 0.047successes killed: 34.000 at 0.069successes killed: 38.000 at 0.077successes killed: 47.000 at 0.096successes killed: 92.000 at 0.187successes killed: 121.000 at 0.246successes killedfalse positive ratesuccesses killed
Two panels rather than two y-axes on one plot. The quantities are not commensurable, one is tokens not spent, the other is work destroyed, and overlaying them on shared axes would suggest a crossing point that is purely an artefact of scaling.

Cross-scaffold transfer

Planned as an AUROC comparison. Not reported, the sample cannot support one.

The plan was to train on OpenHands trajectories and test on hand-labelled Claude Code sessions. Only 3 local sessions are long enough and none carry outcome labels, so a transfer AUROC would be noise presented as a result.

What is measurable without labels is whether the features compute comparably at all, a prerequisite for transfer rather than a substitute for measuring it.

featurecorpuslocalstd diff
n_steps18.7223.33+5.29
n_tool_calls18.8410.00-4.40
turns_since_error9.3040.00+2.74
n_distinct_errors2.960.00-1.83
error_rate0.230.00-1.77
n_errors4.210.00-1.71

The 6 largest shifts all exceed 1.7 standard deviations, and 2 of 33 features fall outside the training range entirely. Claude Code emits more assistant turns per tool call than OpenHands, because thinking blocks become their own turns, a “turn” is not the same unit across scaffolds. Cross-scaffold accuracy is therefore unmeasured, and the tool labels its output indicative in every code path.

This check caught a real bug. Two features reported exactly 0.00 on sessions full of edits, because edit detection was keyed to one tool vocabulary. Not a slightly worse score, a confident zero for something that happened dozens of times.

Limitations

Stated plainly rather than buried.

  • The operating point is not reachable here. Two attempts, the second targeting the diagnosed gap, both fell short. Closing it likely needs a genuine sequence model over the action stream rather than more engineered summaries of it.
  • One corpus, one agent scaffold, 11 repositories. Grouped folds mean 11 grouping units, which widens every interval.
  • Token savings are estimated, not counted. The corpus records no per-message token usage.
  • Cross-scaffold accuracy is unmeasured. The feature comparison above suggests it would be poor.
  • The comparison to the paper is not controlled. Different corpus, different scaffold, estimated rather than counted tokens. It is the closest like-for-like available, not a replication.

Using it

Runs entirely locally. No API keys, no network at inference time, no session data leaves the machine.

git clone <repo> && cd averta
python3 -m venv .venv
.venv/bin/python -m pip install -e .

averta explain      # analyse your most recent coding session
averta sessions     # list local sessions
averta site         # rebuild this page

Those work immediately, the trained model is committed. Reproducing the study needs the corpus, which is a 12-minute download:

averta ingest && averta features
averta train        # cross-validate and apply the gate
averta diagnose     # importance and inference cost
averta savings      # savings against harm
averta figures      # the plots on this page

averta explain separates what is measured, recurring errors, reissued calls, clustered repetition, exact token counts, from what is estimated by a model that did not clear its gate. The measured half needs no model and is as reliable as the transcript. An MCP server exposes the same analysis to a coding agent over stdio.

macOS users need brew install libomp for xgboost. On Linux, libgomp1.