Best Practices

Master iterative AI task execution with these guidelines.

Agent Loop Best Practices

Master iterative AI task execution with these guidelines.

Writing Effective Tasks

Be Specific and Actionable

Vague (Avoid)Specific (Good)
"Fix the code""Fix failing tests in src/auth/"
"Improve performance""Reduce p95 latency below 100ms"
"Add tests""Add unit tests for UserService class"
"Clean up""Remove unused imports from src/"

Provide Context

Good task descriptions include:

  • What needs to be done
  • Where (which files/modules)
  • Constraints (if any)
/ralph "Migrate src/utils/*.js files to TypeScript, maintaining existing function signatures and adding explicit return types" --completion "npx tsc --noEmit passes"

Scope Appropriately

ScopeExampleRisk
Too broad"Refactor entire codebase"Will hit limits
Too narrow"Add semicolon to line 42"Overkill for Al
Just right"Convert CommonJS to ESM in src/lib/"Achievable

Writing Effective Completion Criteria

Rule: Must Be Verifiable

The completion criteria MUST be checkable by running a command. If you can't verify it programmatically, Al can't either.

Subjective (Bad)Verifiable (Good)
"Code is clean""npm run lint passes"
"Tests are good""npm test exits with code 0"
"Performance is fast""lighthouse score >90"
"Types are correct""npx tsc --noEmit passes"

Common Verification Patterns

Testing

# All tests pass
--completion "npm test passes"

# Specific test file
--completion "npm test -- auth.test.ts passes"

# With coverage threshold
--completion "npm test -- --coverage --coverageThreshold='{\"global\":{\"lines\":80}}'"

# Specific framework
--completion "jest passes"
--completion "pytest exits with code 0"
--completion "go test ./... passes"

Type Checking

# TypeScript
--completion "npx tsc --noEmit exits with code 0"

# Python
--completion "mypy . passes"

# Rust
--completion "cargo check passes"

Linting

# ESLint
--completion "npm run lint passes"
--completion "eslint src/ --max-warnings 0"

# Python
--completion "ruff check . passes"
--completion "black --check . passes"

Building

# Node
--completion "npm run build succeeds"

# Rust
--completion "cargo build --release passes"

# Go
--completion "go build ./... passes"

Compound Criteria

Combine multiple checks with AND:

--completion "npm test passes AND npm run lint passes AND npx tsc --noEmit passes"

Al will verify ALL conditions are met.

Setting Iteration Limits

Choosing Max Iterations

Task TypeTypical IterationsRecommended Max
Fix 1-3 test failures2-410
Fix lint errors2-310
Fix type errors3-815
Small migration5-1015
Large migration10-2025
Coverage improvement5-1520
Greenfield scaffold10-3040

When to Increase Limits

Increase `--max-iterations` if:

  • Task was making steady progress when it hit the limit
  • Each iteration fixes some issues but reveals more
  • Task is inherently iterative (like improving coverage)
/ralph-resume --max-iterations 25

When to Split Tasks

Split into smaller tasks if:

  • Hitting limits without meaningful progress
  • Errors are in unrelated areas
  • Task scope is too broad
# Instead of
/ralph "Fix all tests" --completion "npm test passes"

# Split into
/ralph "Fix auth tests" --completion "npm test -- auth passes"
/ralph "Fix utils tests" --completion "npm test -- utils passes"

Git Workflow

Auto-Commit (Default)

Al commits after each iteration:

ralph: iteration 1 - initial implementation
ralph: iteration 2 - fix auth test
ralph: iteration 3 - fix edge case

Benefits:

  • Easy rollback to any iteration
  • Clear progress history
  • Supports `/ralph-resume`
  • Blame-able history

Using Branches

For larger changes, use a branch:

/ralph "big refactor" --completion "..." --branch "refactor-auth"

Creates `ralph/refactor-auth` branch, preserving main.

Final Squash (Optional)

After successful completion, you can squash the commits:

git rebase -i HEAD~{N}
# Squash all "ralph: iteration" commits into one

Disabling Auto-Commit

If you prefer manual commits:

/ralph "task" --completion "..." --no-commit

Common Patterns

Test Fix Loop

/ralph "Fix all failing tests" --completion "npm test passes"

Migration Loop

/ralph "Migrate src/ from CommonJS to ESM" \
  --completion "node --experimental-vm-modules src/index.mjs runs" \
  --max-iterations 20

Coverage Loop

/ralph "Add tests to reach 80% coverage" \
  --completion "npm run coverage -- --coverageThreshold='{\"global\":{\"lines\":80}}'" \
  --max-iterations 30

Lint Cleanup Loop

/ralph "Fix all ESLint errors and warnings" \
  --completion "eslint src/ --max-warnings 0"

Type Safety Loop

/ralph "Add TypeScript types to all exported functions" \
  --completion "npx tsc --noEmit && npm run lint:types"

Dependency Update Loop

/ralph "Update all dependencies and fix breaking changes" \
  --completion "npm test passes && npm run build succeeds"

Anti-Patterns to Avoid

Subjective Criteria

# BAD - cannot verify
/ralph "Make the code better" --completion "code looks good"

Missing Completion Criteria

# BAD - no way to know when done
/ralph "Fix things"

Infinite Scope

# BAD - will never complete
/ralph "Add all missing features" --completion "product is complete"

Ignoring Limits

# BAD - if 10 didn't work, 100 probably won't either
/ralph "..." --completion "..." --max-iterations 100

External Dependencies

# RISKY - depends on external service
/ralph "Fix API integration" --completion "curl api.example.com/health returns 200"

Debugging Failed Loops

Check Iteration History

/ralph-status --verbose

Look for:

  • Is the same error repeating?
  • Is there progress between iterations?
  • Are learnings actionable?

Manual Verification

Run the verification command yourself:

npm test
echo $?  # Should be 0 for success

Examine Learnings

Read `.aiwg/ralph/current-loop.json` to see accumulated learnings.

Start Fresh with More Context

If stuck, abort and restart with more specific guidance:

/ralph-abort
/ralph "Fix auth tests - the mock for getUserById needs to return user with 'admin' role" \
  --completion "npm test -- auth passes"