# How the Circuit Breaker Detects and Handles Runaway Agents or Infinite Loops in Munder Difflin

> Learn how the Munder Difflin circuit breaker detects and handles runaway agents or infinite loops. Discover its adaptive resource management for efficient operation.

- Repository: [Chaitanya Giri/munder-difflin](https://github.com/chaitanyagiri/munder-difflin)
- Tags: internals
- Published: 2026-08-20

---

**The Munder Difflin circuit breaker uses a periodic heartbeat to sample agent telemetry, evaluates usage against configurable thresholds for tool repetition, error storms, token velocity, and hop counts, then escalates through graduated states—steering, constraining, and finally stopping—to halt runaway agents before they consume excessive resources.**

The `chaitanyagiri/munder-difflin` repository implements a robust **circuit breaker** safety mechanism designed to prevent autonomous agents from entering infinite loops or consuming runaway resources. By monitoring real-time metrics such as tool invocation patterns, error rates, and token velocity, the system can automatically detect anomalous behavior and intervene with escalating severity. This article examines the detection architecture, intervention strategies, and source code implementation that enable the circuit breaker to protect the multi-agent environment.

## Architecture of the Circuit Breaker Detection System

### The Circuit Breaker Beat (Heartbeat)

Detection begins with a periodic sampling mechanism known internally as the **circuit-breaker beat**. Scheduled within [`src/main/index.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/index.ts), this heartbeat runs at regular intervals to pull fresh usage snapshots for every active agent.

The beat invokes `breakSample()` in [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts), which collects critical telemetry:

- **Token consumption** per agent per minute
- **Tool invocation counts** and repetition patterns
- **Consecutive error counts** (error streaks)
- **Hop counts** reflecting message routing depth between agents

This sampling strategy ensures that runaway behavior is caught within seconds rather than minutes, minimizing resource waste.

### Threshold Policies and State Machine

Once sampled, data flows into the **`CircuitBreaker`** class defined in [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts). The `checkAgent()` method evaluates four primary throttles against configuration values stored in `CircuitBreakerConfig` ([`src/main/config.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/config.ts)):

- **Repeated-tool limit**: Flags agents calling the same tool excessively within a window
- **Error-storm limit**: Detects consecutive tool failures indicating a broken logic path
- **Token-velocity ceiling**: Monitors `tokenVelocityPerMin` to catch agents generating text faster than budgeted
- **Hop-count cap**: Prevents infinite ping-pong by limiting message routing hops between agents

When a threshold is breached, the breaker transitions the agent through a state machine:

```

healthy → steering → constrained → stopped

```

Each state represents an escalating intervention level, allowing the system to attempt gentle course correction before termination.

## Intervention Strategies for Runaway Agents

### Graduated Response States

The circuit breaker employs **graduated interventions** rather than immediate termination, giving agents opportunity to self-correct:

- **Steering**: When initial thresholds are crossed, the breaker sends a summarization prompt requesting the agent explain its recent actions. This often breaks loops by forcing reflection.
- **Constrained**: If behavior persists, the system injects token-limit hints and restricts tool availability, effectively throttling the agent's operational capacity.
- **Stopped**: Upon reaching critical thresholds (severe error storms or hop-count overflow), the breaker issues a hard **STOP** command and marks the agent as blocked.

These state transitions are handled internally within `checkAgent()` in [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts), which maintains per-agent state maps tracking current status and violation history.

### Message Injection and UI Feedback

Actual intervention delivery occurs through `sendCircuitBreakerMessage()` in [`src/main/realtimeActions.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/realtimeActions.ts). This function:

1. Injects control messages directly into the target agent's inbox
2. Logs intervention reasons via `breakerToast` for audit trails
3. Signals the renderer process to update UI status indicators

The UI reflects intervention states through CSS tokens such as `--cth-status-looping`, rendering visual badges indicating "circuit-breaker armed (runaway)" when agents enter constrained or stopped states.

## Configuration and Customization

Administrators configure breaker thresholds through the settings interface defined in [`src/renderer/src/components/SettingsModal.tsx`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/renderer/src/components/SettingsModal.tsx). The configuration persists through the `CircuitBreakerConfig` interface:

```typescript
// src/main/config.ts - Configuration shape
interface CircuitBreakerConfig {
  enabled: boolean;
  tokenVelocityPerMin?: number;
  repeatedToolLimit?: number;
  errorStormLimit?: number;
  maxHopCount?: number;
}

```

The React settings modal exposes these controls:

```tsx
// src/renderer/src/components/SettingsModal.tsx
const [brkEnabled, setBrkEnabled] = useState<boolean>(
  breakerCfg.circuitBreaker?.enabled !== false
);
const [velocityCeiling, setVelocityCeiling] = useState(
  breakerCfg.circuitBreaker?.tokenVelocityPerMin != null
    ? String(breakerCfg.circuitBreaker.tokenVelocityPerMin)
    : ''
);

// Saving configuration updates the breaker parameters
const saveConfig = () => {
  const newConfig = {
    enabled: brkEnabled,
    tokenVelocityPerMin: parseInt(velocityCeiling, 10),
    // ... additional thresholds
  };
  updateBreakerConfig(newConfig);
};

```

Programmatic inspection of breaker status is available through the `useHive` hook, which queries per-agent circuit breaker states:

```typescript
// Querying breaker status for a specific agent
const breakerStatus = agent.circuitBreaker?.enabled 
  ? 'active monitoring' 
  : 'bypassed';

```

## Implementation Details in Source Code

The core logic resides in three critical files:

**[`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts)** contains the `CircuitBreaker` class with `breakSample()` and `checkAgent()` methods. The class maintains internal counters for tool repeats and error streaks, comparing them against configuration thresholds each heartbeat cycle.

**[`src/main/index.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/index.ts)** schedules the circuit-breaker beat using Electron's main process timers, ensuring sampling continues regardless of renderer state.

**[`src/main/realtimeActions.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/realtimeActions.ts)** bridges detection to action, implementing `sendCircuitBreakerMessage()` to deliver stop commands and constraint notifications to agent processes.

## Summary

- The **circuit-breaker beat** in [`src/main/index.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/index.ts) drives periodic telemetry sampling via `breakSample()`.
- **Four threshold policies**—tool repetition, error storms, token velocity, and hop counts—detect runaway conditions in [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts).
- **Graduated state transitions** (healthy → steering → constrained → stopped) allow escalating interventions before termination.
- **Message injection** through `sendCircuitBreakerMessage()` in [`src/main/realtimeActions.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/realtimeActions.ts) halts agents and logs interventions.
- **Configuration** via [`SettingsModal.tsx`](https://github.com/chaitanyagiri/munder-difflin/blob/main/SettingsModal.tsx) and `CircuitBreakerConfig` enables customization of sensitivity thresholds.
- **Visual feedback** through CSS tokens like `--cth-status-looping` alerts users to breaker-triggered stops.

## Frequently Asked Questions

### What triggers the circuit breaker to stop an agent immediately?

An agent enters the **stopped** state immediately when it exceeds the **error-storm limit** (consecutive tool failures) or the **hop-count cap** (message routing depth), as implemented in `checkAgent()` within [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts). These conditions indicate unrecoverable logic errors or infinite ping-pong between agents, prompting the system to issue a hard STOP command via `sendCircuitBreakerMessage()`.

### How does the circuit breaker distinguish between high activity and an infinite loop?

The system relies on **pattern detection** rather than absolute volume. By tracking `toolRepeats` (frequency of identical tool calls) and `errorStreak` (consecutive failures) in the `CircuitBreaker` class, the breaker identifies repetitive, cyclical behavior characteristic of infinite loops. High but varied activity across different tools without error accumulation typically does not trigger constraints.

### Can developers customize the token velocity thresholds?

Yes. The **token-velocity ceiling** is configurable through the `tokenVelocityPerMin` property in `CircuitBreakerConfig` ([`src/main/config.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/config.ts)). The settings interface in [`src/renderer/src/components/SettingsModal.tsx`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/renderer/src/components/SettingsModal.tsx) exposes this as a numeric input, allowing administrators to set site-specific limits based on expected agent workloads and API budget constraints.

### Where is the circuit breaker state persistence handled?

While the breaker evaluates state in real-time within [`src/main/breaker.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/breaker.ts), **configuration persistence** is managed through the application's settings store, accessed via the `useHive` hook and saved through the settings modal. Current agent states (healthy, steering, constrained, stopped) are maintained in-memory during runtime but generate persistent audit logs via `breakerToast` in [`src/main/realtimeActions.ts`](https://github.com/chaitanyagiri/munder-difflin/blob/main/src/main/realtimeActions.ts) for post-hoc analysis.