Search

Sign in to launch Copilot/Codex from the palette.

THINK IN LOOPS

2-3 iterations. Stop. Review. Update context. Repeat.

AI Workflows 2026.01.17

The Workflow

Problem: A long agent run can compound a wrong assumption before the operator sees the code. The final diff shows the damage but not the iteration where the run drifted.

Solution: Slow mode. 2-3 iterations, then stop. Review the code. Update context. Repeat. The human is the checkpoint in the loop.

Ralph runs (2-3x) → Stop
         ↓
    Review code
         ↓
    Update context
         ↓
    Repeat

What's a Ralph?

Named after Geoffrey Huntley's concept: AI models are like Ralph Wiggum from The Simpsons. No memory. No plan. No continuity. Every moment is complete and isolated.

Every message is a fresh instance that only knows what you show it right now. That makes the supplied context one of the operator's direct control surfaces.

Every message is a new Ralph.

Why Slow Mode Works

When you let Ralph run unsupervised for 50 iterations, you're hoping. Wishing. You come back to either a miracle or a mess.

When you stop every 2-3 iterations:

  • You see where Ralph is heading
  • You correct course before it compounds
  • You update the context with what you learned
  • The next iterations are better informed

Time isn't saved. Time is spent differently. Instead of typing implementation, you're writing tests. Instead of debugging your code, you're examining what Ralph could see.

The Memento Problem

There's a movie called Memento about a man who can't form new memories. Every few minutes, he forgets everything. So he tattoos the important things on his body—the facts that must persist.

Your AI is this man. The context window is his mind. Everything you don't tattoo (include explicitly) doesn't exist.

The inversion: you are not the one without memory. The AI is. You're the handler. You're the one who writes the tattoos.

In slow mode, the "code review" step is where you write new tattoos. You see what Ralph did, you update AGENTS.md or your task list, you give the next Ralph better context than the last one had.

The Context I Can Change

The context window is the part of the run I can inspect and rewrite between iterations.

The model and tooling still matter, but neither can recover a constraint that never entered the context or disappeared during compaction.

Slow mode turns review into context maintenance: inspect the diff, record the missing constraint, and start the next run with a better board.

THE SIMPLEST IMPLEMENTATION

A GitHub Action that loops:

name: ralph

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  run:
    runs-on: ubuntu-latest
    timeout-minutes: 15

    steps:
      - uses: actions/checkout@v4

      - name: Run Ralph
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          npm install -g @anthropic-ai/claude-code
          
          # The context: everything Ralph can see
          claude --dangerously-skip-permissions \
            --print \
            "$(cat AGENTS.md)"

      - name: Guardrail - Something Must Change
        run: |
          if git diff --quiet; then
            echo "Nothing changed. Loop failed."
            exit 1
          fi

      - name: Continue Loop
        run: |
          git config user.name "ralph-bot"
          git config user.email "ralph-bot@users.noreply.github.com"
          git add -A
          git commit -m "ralph: iteration"
          git push  # triggers next loop

Fresh context (checkout) → Ralph reads AGENTS.md → Ralph works → Guardrail checks for changes → Commit and push → Push triggers next iteration

The Guardrail

git diff --quiet

Did something change? Yes → continue. No → fail.

The loop enforces itself. You can't wish for a different outcome with the same inputs. If Ralph did nothing, that's not feedback—that's a broken loop.

Adding Backpressure

Tests are backpressure:

      - name: Run Tests
        run: npm test
        
      - name: Guardrail
        run: |
          if git diff --quiet; then
            echo "Nothing changed."
            exit 1
          fi

Now Ralph must change things in a way that passes tests. The tests define the shape. Ralph fills it.

Adding a Kill Switch

      - name: Check Kill Switch
        run: |
          if [ -f .ralph/PAUSED ]; then
            echo "Ralph is paused."
            exit 0
          fi

Stop Ralph: touch .ralph/PAUSED && git push
Restart: rm .ralph/PAUSED && git push

Adding Failure Memory

Ralphs forget. The filesystem remembers:

      - name: Record Outcome
        if: always()
        run: |
          mkdir -p .ralph
          
          if [ "${{ job.status }}" = "success" ]; then
            echo "0" > .ralph/failures
          else
            FAILURES=$(cat .ralph/failures 2>/dev/null || echo "0")
            echo "$((FAILURES + 1))" > .ralph/failures
            
            if [ $FAILURES -ge 5 ]; then
              touch .ralph/PAUSED
              echo "Too many failures. Pausing."
            fi
          fi
          
          git add .ralph/
          git commit -m "ralph: record state" || true
          git push || true

Five failures in a row? Ralph pauses itself.

The Core Loop

The loops in these examples share four parts:

  1. 1. Fresh context every cycle — Ralph is born again each time
  2. 2. Clear instructions — what should Ralph try to do?
  3. 3. The ability to act — Ralph must be able to change something
  4. 4. Observation — did it work?
  5. 5. A guardrail — something MUST change, or the loop failed

That last one is key: the loop must eat its own tail.

If Ralph runs and nothing changes, that's not neutral. That's failure. You can't observe without influencing. The concept validates itself.

Slow Mode vs Full Auto

Full auto:
ralph runs → ralph runs → ralph runs → ... → you check → ???

Slow mode:
ralph runs (2-3x) → you review → update context → ralph runs (2-3x) → you review → ...

Full auto is gambling. Slow mode is steering.

The right tools for proper code review don't fully exist yet. So we slow down. We stay in the loop. We use our eyes as the checkpoint until better tooling catches up.

The Inversion

Old: I write code, tests validate it.
New: I write tests, Ralph fills in the code.

Old: I am the harness.
New: Tests are the harness. I observe.

Old: Debugging means tracing my code.
New: Debugging means examining what Ralph could see.

Same features. Built backwards.

The Existing Harness

"I could just write the code."

Sure. Then write the tests to make sure it's not broken. Then the guardrails in staging. Then the cascade of other tests as you add more features. Then production monitoring. Then alerts. Then rollback procedures.

A normal delivery process already contains parts of a harness.

CI/CD is a loop. Testing is a guardrail. Code review is a checkpoint. Deployment is a gate. Monitoring is observation.

The Ralph loop makes those checkpoints explicit and gives each new run the same route through them.

What I Want to Test Next

I want to see how much of the workflow can live in the repository: scoped tasks, checks, progress, and stop conditions.

Different coding agents can modify the same repo, but model behavior and tool support still change the result. The shared part is the artifact and the checks around it.

I spend more time on checks than I used to.

The harder part is writing tests that actually specify what you want. That's not trivial. But when you can define "done" clearly enough that a test can verify it, Ralph has a shot. When Ralph fails, you learn what was missing from the context or what the test didn't cover.

Patience

The loop also changes the pacing. I have to wait for a run, inspect what happened, and decide whether the next iteration has enough information.

That resembles ordinary debugging, but the actor performing the next change is different. The review step is where I recover context and update the constraints.

I am still learning how long to let a run continue and when another iteration only repeats the same mistake.

The Wall You'll Hit

Once you start doing this, another problem appears:

Observation.

You need to see what changed, why it changed, what failed, and what reality says. Without observation, loops turn into superstition.

I'm using gateproof.dev in my projects. It's just a collection of ideas for doing this end-to-end—observing what changed and validating against constraints. Not expecting many people to use it, but it works for me.

Automation without checkpoints is just a fast way to be wrong.

Slower loops. More deliberate steering. Code review as backpressure.

That's the workflow.