Skip to main content

Self-Healing Loop

A harness pattern where an autonomous agent detects its own failures, attempts bounded repair, and falls back to rollback + escalation when repair budget is exhausted. The complement to the Ralph Loop (which handles continuation past stopping points) — self-healing handles recovery from failure within each iteration.

Core Loop

The loop does not retry indefinitely. Every failure type has a retry budget (max attempts before escalation) and a failure signature (to detect when the same fix is being retried without progress).

Failure Signature Detection

Repeating the same failed patch is the most common infinite-loop failure mode. The harness tracks failure signatures:
If the same signature appears twice in the retry window → stop retrying that path, force rollback. This catches: same test failing with same error after a “fix,” same migration error after re-running, same lint error after supposedly patching. Without signature detection, the agent can spend its entire retry budget on the same broken fix.

Retry Budget by Failure Type

Different failures warrant different budgets: Destructive operations (migrations, deploys) get lower budgets than reversible ones (test patches, lint fixes).

Rollback Protocol

When retry budget is exhausted:
  1. Revert to last known-good stategit reset --hard <last_green_sha> or redeploy last passing image
  2. Write machine incident note — structured file capturing: failure type, retry count, failure signatures seen, diff that was attempted, timestamp
  3. Signal escalation — set a flag/file the outer harness monitors; stop the loop; do not continue building
The incident note format:
This is the audit trail for human review. The agent does not attempt further action after writing this.

Guardrails (Non-Negotiable)

These are enforced by the harness, not by the agent’s discretion:
  • Max retries per session: total cap across all failures (e.g., 10); prevents budget exhaustion attacks
  • Diff size cap: reject any single patch > N lines changed — forces the agent to patch incrementally, not rewrite
  • No auto-destructive migrations: schema drops, column renames, table truncations must be human-approved; the loop can propose but not execute
  • Stop on repeated same-failure signature: hook blocks execution if signature hash already seen in this session
  • Timeout per iteration: each repair attempt has a wall-clock timeout; prevents stuck builds

Composition with Ralph Loop

The ralph-loop is the outer driver; self-healing is the inner recovery mechanism:
A session can run many ralph-loop iterations, each of which may trigger self-healing cycles. The ralph-loop’s completion condition checks for a “no outstanding failures” signal, not just “agent stopped.”

Observability Requirements

The self-healing loop must produce machine-readable output the outer harness can monitor:
  • loop-state.json — current task, iteration, retry count, last failure type
  • incidents/YYYY-MM-DD-HH-MM.md — structured rollback records
  • Exit codes — 0 (success), 1 (rollback, needs human), 2 (budget exhausted, escalate immediately)
Without structured output, the outer harness cannot distinguish “agent is thinking” from “agent is stuck.”

Reference Implementations

Dagger handles the “analyze and patch” half; ArgoCD handles the “rollback on deploy failure” half; Windmill provides the retry scheduling primitive that both can use. Dagger flow (AI-driven CI layer): detect failure → agent analyzes log → patches code scoped to relevant file → reruns only the failing gate (not full suite) → posts reviewed diff to PR; agent does not auto-merge. ArgoCD rollback (deploy layer):
Two-condition check (op phase + health) prevents false positives. Rollback is re-sync to stored revision — idempotent. Windmill retry config (workflow step layer):
Per-step retry with exponential backoff + jitter; each attempt gets a fresh isolated execution context.

When Self-Healing Fails

Self-healing loops fail in predictable ways: