Skip to main content
Loop Evaluator scores how healthy a loop run was — did it converge, were iterations wasted, and did a doom-loop guard fire — on top of EvaluationLoop’s output-quality score. A loop can succeed (score ≥ 8.0) while burning max iterations, triggering doom-loop recovery, or costing 5× the expected tokens. EvaluationLoop scores output quality; LoopEvaluator scores loop health on top of it — no extra LLM calls.

Quick Start

1

Score an already-run loop

Run an EvaluationLoop, then score its health.
2

Tolerate wasted iterations

Set an explicit threshold and allow one wasted iteration.
3

Pass structured guard events

Feed doom-loop guard events. The evaluator is duck-typed — dicts or objects both work.
Compose with the full suite — add this evaluator to an EvalSuite to gate CI on Context, Loop, Harness, and Accuracy in one pass.

How It Works

LoopEvaluator derives health from a completed EvaluationLoopResult — it never re-runs the loop, so it makes zero LLM calls and is safe in CI.

Mode-Aware Convergence

Convergence is computed differently in optimize vs review mode — the health verdict never disagrees with the loop’s own verdict.
  • optimize mode: convergence = first iteration whose score ≥ threshold. wasted_iterations = num_iterations − iterations_to_success.
  • review mode: EvaluationLoop runs every iteration and derives success from the final score, so a transient earlier high score is not treated as convergence. LoopEvaluator defers to loop_result.success (or score_history[-1] >= threshold). wasted_iterations is always 0.

Configuration Options

Constructor parameters for LoopEvaluator. run(loop_result, guard_events=None) takes a completed EvaluationLoopResult (or any object exposing score_history, threshold, total_duration_seconds, mode, success) and an optional list of guard events.

Eval SDK Reference

Full auto-generated Python reference for the eval module

LoopHealthResult Fields

run() returns a LoopHealthResult. These are the fields returned by to_dict(). to_dict(), to_json(), and print_summary() are all provided.

Recognised Guard-Event Shapes

Guard events are duck-typed — the evaluator detects a doom-loop without coupling to any specific class. Accepted type / event string values (case-insensitive): doom_loop, doom-loop, doomloop, repetition, loop_detected, repeated_action, repeated_failure, no_progress, circular_plan, resource_exhaustion, repeated_output.

Common Patterns

CI Gate on Loop Health

Fail the build when a loop wastes iterations or a doom-loop fires.

Combine Quality and Health

Score output quality (EvaluationLoop) and loop health (LoopEvaluator) on the same run — they are complementary.

Wire Real Doom-Loop Guards

Plug in structured DoomLoopEvents (or loop_detection_plugin events) as guard_events.

Best Practices

0 is the strictest setting — any post-threshold iteration marks the loop unhealthy. Use it for optimize-mode CI gates; use ≥1 for exploratory review-mode runs.
That is intentional, not a bug — review mode runs all iterations by design, so post-threshold iterations are not “waste”.
A dict or an object works. type, event, loop_type, is_loop, and explicit doom_loop flags are all recognised — see the accepted string values above.
The evaluator only consumes an existing EvaluationLoopResult. No external deps, no network — safe in offline CI.

Evaluation Suite

Run all four evaluators as one CI gate

Evaluation Loop

The loop this evaluator scores

Loop Detection

The guard whose events feed this evaluator

Loop Guard

Per-turn tool-call guard, complementary safety net

Judge

The underlying judge used by EvaluationLoop

CHL Engineering

The Context / Harness / Loop rubric this evaluator scores against.