Skip to Content
GuidesAgentic Loop

Agentic Loop (Ralph Loop Pattern)

Implement the autonomous task execution pattern where an AI agent reads a plan from disk, executes one task per iteration in a fresh context, and uses validation as backpressure.

How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ IMPLEMENTATION_PLAN.md (disk) β”‚ β”‚ ⬜ Task 1: Scaffold structure β”‚ β”‚ ⬜ Task 2: Create agent β”‚ β”‚ ⬜ Task 3: Write tests β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”‚ Iteration 1 β”‚ ← Fresh context β”‚ Execute T1 β”‚ β”‚ Mark βœ… β”‚ β”‚ Run tests β”‚ ← Backpressure β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”‚ Iteration 2 β”‚ ← Fresh context β”‚ Execute T2 β”‚ β”‚ ... β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Step 1: Create the Implementation Plan

The plan file is the shared state between iterations:

spec/implementation-plan.md
# Implementation Plan ## Tasks - [ ] Task 1: Create the project structure with fai-manifest.json - [ ] Task 2: Build the RAG ingestion pipeline - [ ] Task 3: Create the retrieval API endpoint - [ ] Task 4: Add evaluation pipeline - [ ] Task 5: Write integration tests - [ ] Task 6: Deploy to Azure Container Apps ## Context - Play: 01-enterprise-rag - Stack: Python + FastAPI + Azure AI Search ## Completion Criteria - All tasks checked βœ… - `npm run validate:primitives` exits 0 - All tests pass

Step 2: Create the Loop Runner

scripts/agentic-loop.js
const fs = require('fs'); const { execSync } = require('child_process'); const PLAN_FILE = process.argv[2] || 'spec/implementation-plan.md'; const MAX_ITERATIONS = 20; function getNextTask(plan) { const lines = plan.split('\n'); for (const line of lines) { if (line.match(/^- \[ \] /)) { return line.replace('- [ ] ', '').trim(); } } return null; } function markTaskDone(task) { const plan = fs.readFileSync(PLAN_FILE, 'utf8'); fs.writeFileSync(PLAN_FILE, plan.replace(`- [ ] ${task}`, `- [x] ${task}`)); } function runValidation() { try { execSync('node scripts/validate-primitives.js', { stdio: 'inherit' }); return true; } catch { return false; } } for (let i = 0; i < MAX_ITERATIONS; i++) { const plan = fs.readFileSync(PLAN_FILE, 'utf8'); const task = getNextTask(plan); if (!task) { console.log('βœ… All tasks complete!'); break; } console.log(`\nπŸ”„ Iteration ${i + 1}: ${task}`); // Agent executes the task with fresh context markTaskDone(task); if (!runValidation()) { console.log('❌ Validation failed β€” stopping loop'); break; } }

Step 3: Multi-Agent Routing

Assign different agents to different task types:

Task PatternAgentExpertise
”Create structure”fai-architectArchitecture, scaffolding
”Build pipeline”fai-play-01-builderPlay-specific implementation
”Write tests”fai-test-generatorTest generation
”Deploy”fai-devops-expertInfrastructure, deployment
”Evaluate”fai-play-01-reviewerQuality review

Step 4: Add Evaluation Backpressure

function runEvaluation(playId) { try { const result = execSync( `node engine/index.js solution-plays/${playId}/fai-manifest.json --eval`, { encoding: 'utf8' } ); return result.includes('passed'); } catch { return false; } }

Why Fresh Context Matters

  1. No hallucination accumulation β€” previous mistakes don’t pollute future tasks
  2. Token budget reset β€” each task gets the full context window
  3. Parallel potential β€” independent tasks could run simultaneously
  4. Reproducibility β€” same plan + same task = same result

Disk-Based State Patterns

PatternFilePurpose
Task trackingspec/implementation-plan.md- [ ] β†’ - [x]
Iteration logspec/iteration-log.jsonlAppend-only log
Artifactsspec/artifacts/Generated files
Error logspec/errors.mdFailed tasks

Best Practices

  1. One task per iteration β€” don’t batch multiple tasks
  2. Plan on disk, not in memory β€” survives crashes
  3. Validation as backpressure β€” never proceed if tests fail
  4. Log everything β€” append to iteration-log.jsonl
  5. Set MAX_ITERATIONS β€” prevent infinite loops
  6. Fresh context per iteration β€” avoid context window pollution

See Also

Last updated on