Documentation
Nity Loop
Circuit Breaker

Circuit Breaker

The CircuitBreaker class detects stagnation in the autonomous loop and halts execution when progress stops.

States

┌──────────┐     no progress (3x)     ┌────────────┐
│          │ ───────────────────────→  │            │
│  CLOSED  │                           │ HALF_OPEN  │
│          │ ←───────────────────────  │            │
└──────────┘     progress resumes      └────────────┘
     │                                        │
     │           same error (5x)         still stuck
     │                                        │
     ▼                                        ▼
┌──────────────────────────────────────────────────┐
│                       OPEN                        │
│              (loop terminated)                    │
└──────────────────────────────────────────────────┘
StateMeaningLoop Action
CLOSEDNormal operationContinue iterating
HALF_OPENStagnation detectedOne more chance — monitor closely
OPENConfirmed stagnationTerminate loop immediately

Thresholds

interface CircuitBreakerConfig {
  noProgressThreshold: number    // default: 3
  sameErrorThreshold: number     // default: 5
  outputDeclineThreshold: number // default: 70 (percentage)
}
ThresholdDefaultTrigger
noProgressThreshold3Consecutive iterations with no measurable progress
sameErrorThreshold5Same error message repeated across iterations
outputDeclineThreshold70%Output quality drops below 70% of baseline

Interface

interface CircuitBreaker {
  state: 'CLOSED' | 'HALF_OPEN' | 'OPEN'
 
  recordProgress(metrics: IterationMetrics): void
  recordError(error: string): void
  check(): CircuitBreakerDecision
  reset(): void
  getStatus(): CircuitBreakerStatus
}
 
interface IterationMetrics {
  filesChanged: number
  testsPassing: number
  outputLength: number
  timestamp: Date
}
 
interface CircuitBreakerDecision {
  allowContinue: boolean
  state: CircuitBreaker['state']
  reason: string | null
}
 
interface CircuitBreakerStatus {
  state: CircuitBreaker['state']
  consecutiveNoProgress: number
  errorCounts: Record<string, number>
  outputTrend: number[]
  lastProgress: Date | null
}

State Transitions

CLOSED → HALF_OPEN

Triggered when consecutiveNoProgress reaches noProgressThreshold. The circuit enters a watchful state — one more iteration without progress will open it.

HALF_OPEN → CLOSED

If the next iteration shows measurable progress (files changed, tests passing, output quality improves), the circuit resets to CLOSED. The counter resets.

HALF_OPEN → OPEN

If the watchful iteration also shows no progress, or the same error repeats sameErrorThreshold times, the circuit opens and terminates the loop.

CLOSED → OPEN

Direct transition if the same error occurs sameErrorThreshold consecutive times, bypassing HALF_OPEN entirely.

⚠️

Once the circuit is OPEN, the loop cannot continue. The coordinator receives a circuit_open exit signal and must handle it — typically by recording the episode as a failure and escalating to the human.

Error Tracking

The circuit breaker maintains a frequency map of error messages. When any single error reaches sameErrorThreshold, it triggers an immediate circuit open:

// Error pattern detection
if (errorCounts[error] >= sameErrorThreshold) {
  state = 'OPEN'
  reason = `Same error repeated ${sameErrorThreshold} times: "${error}"`
}

This catches infinite retry loops where the agent applies the same fix repeatedly without learning.