REAL/VEAL Loop Patterns¶
This guide describes autonomous loop patterns for multi-agent systems.
Overview¶
Loops are autonomous, bounded execution patterns that run without human intervention until they complete or escalate. They are inspired by the REPL (Read-Eval-Print-Loop) pattern from interactive programming environments.
Loop Hierarchy¶
REAL (abstract)
│
└── VEAL (state-driven)
├── qa-fix-loop (code state → valid code)
├── docs-fix-loop (docs state → complete docs)
└── security-fix-loop (security state → secure code)
REAL — Read Eval Act Loop¶
The generic, mission-driven loop pattern. Use for open-ended tasks where the goal is defined by a mission statement rather than specific validation checks.
REAL Loop:
R - Read (mission, requirements, goals)
E - Eval (assess situation against goals)
A - Act (take action toward goals)
L - Loop (until mission complete or escalate)
Characteristics:
- Open-ended goals
- Requirements-driven
- May involve discovery/exploration
- Single actor agent (no separate validator)
Example use cases:
- "Implement feature X"
- "Migrate from API v1 to v2"
- "Refactor authentication system"
Example definition:
name: feature-impl
type: REAL
actor: developer
mission: |
Implement user authentication with OAuth2 support.
Must include login, logout, and session management.
max_attempts: 5
escalation: human
success_criteria: |
All authentication flows work correctly.
Tests pass. Documentation updated.
VEAL — Validate Eval Act Loop¶
A specialization of REAL for state convergence. Validates current state against expected state and acts to correct deviations.
VEAL Loop:
V - Validate (check current state)
E - Eval (compare to expected state → GO/NO-GO)
A - Act (correct state if NO-GO)
L - Loop (until state valid or escalate)
Characteristics:
- Convergent (state approaches valid)
- Idempotent checks
- Bounded attempts
- Dual-agent pattern (validator + fixer)
Example use cases:
- QA validation (build, test, lint, format)
- Documentation completeness
- Security compliance
- Configuration validation
Example definition:
name: qa-fix
type: VEAL
description: QA validation and fix loop
validator: qa
actor: code-fixer
max_attempts: 3
escalation: human
success_criteria: All checks pass (GO status)
checks:
- id: build
type: command
command: go build ./...
required: true
expected: Exit code 0
- id: tests
type: command
command: go test -v ./...
required: true
expected: All tests pass
- id: lint
type: command
command: golangci-lint run
required: true
expected: No lint errors
- id: format
type: command
command: gofmt -l .
required: true
expected: No files need formatting
Loop Configuration¶
Common Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique identifier (kebab-case) |
type |
string | Yes | REAL or VEAL |
description |
string | No | Human-readable description |
actor |
string | Yes | Agent that performs actions |
max_attempts |
int | No | Maximum iterations (default: 3) |
escalation |
string | No | Policy when max reached (default: human) |
success_criteria |
string | No | Description of success conditions |
VEAL-Specific Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
validator |
string | Yes | Agent that validates state (read-only) |
checks |
array | Yes | Validation checks to run |
REAL-Specific Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
mission |
string | Yes | Goal statement for the loop |
Check Definition¶
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Check identifier (kebab-case) |
type |
string | No | command, pattern, file, or manual |
command |
string | No | Shell command (for type: command) |
pattern |
string | No | Regex pattern (for type: pattern) |
files |
string | No | Glob pattern for files to check |
file |
string | No | File path (for type: file) |
required |
bool | No | Causes NO-GO if failed (default: true) |
expected |
string | No | Description of success |
Escalation Policies¶
| Policy | Description |
|---|---|
human |
Stop and request human intervention |
abort |
Stop and fail the workflow |
continue |
Proceed despite unresolved issues |
fallback |
Invoke a fallback agent |
Using Loops in Workflows¶
Loops can be referenced as steps in team workflows:
{
"workflow": {
"type": "chain",
"steps": [
{ "name": "validate-scope", "agent": "pm" },
{ "name": "qa-fix", "loop": "qa-fix" },
{ "name": "docs-fix", "loop": "docs-fix" },
{ "name": "tag-release", "agent": "release" }
]
}
}
Go SDK Usage¶
Creating Loops Programmatically¶
import mas "github.com/plexusone/multi-agent-spec/sdk/go"
// Create a VEAL loop
qaLoop := mas.NewVEALLoop("qa-fix", "qa", "code-fixer").
WithDescription("QA validation and fix loop").
WithMaxAttempts(3).
AddCheck(mas.LoopCheck{
ID: "build",
Type: mas.CheckTypeCommand,
Command: "go build ./...",
}).
AddCheck(mas.LoopCheck{
ID: "lint",
Type: mas.CheckTypeCommand,
Command: "golangci-lint run",
})
// Create a REAL loop
featureLoop := mas.NewREALLoop(
"feature-impl",
"developer",
"Implement user authentication with OAuth2",
).WithMaxAttempts(5)
// Validate
if err := qaLoop.Validate(); err != nil {
log.Fatal(err)
}
Loading Loops from Files¶
loader := mas.NewLoader()
// Load single loop
loop, err := loader.LoadLoop("loops/qa-fix.yaml")
// Load all loops from directory
loops, err := mas.LoadLoopsFromDir("loops/")
Best Practices¶
- Keep checks idempotent — Running the same check multiple times should produce the same result
- Use specific checks — Prefer multiple small checks over one large check
- Set reasonable max_attempts — 3 is usually sufficient; more may indicate a deeper issue
- Separate concerns — Validator agents should be read-only; actor agents should fix issues
- Document success criteria — Make it clear what "done" looks like
- Use fallback agents — For complex issues that may need escalation to a specialist