Review Loop
The review loop is a structured code review workflow built on Inbox / Outbox Messaging. It uses four message types to coordinate between an author agent and a reviewer agent, supporting multiple rounds of feedback until the change meets quality standards.
Message types
Section titled “Message types”| Type | Direction | Purpose |
|---|---|---|
review_request | Author -> Reviewer | Request code review of a PR |
review_feedback | Reviewer -> Author | Return review findings |
review_addressed | Author -> Reviewer | Report that feedback was addressed |
review_lgtm | Reviewer -> Author | Approve — quality gate passed |
Author Reviewer (invocation A) | | |--- review_request --------------------------->| (PR#, branch, summary, budgets) | | |<-- review_feedback OR review_lgtm -----------| (one terminal response) | | | reviewer invocation A exits | | |--- review_addressed ------------------------->| (commit SHA, addressed summary) | |--- review_request (round N+1) -------------->| (explicit re-invocation) | |<-- review_feedback OR review_lgtm -----------| (invocation B terminal response)The reviewer is stateless — each invocation handles exactly one round, produces one terminal response (review_feedback or review_lgtm), and exits. The author coordinates multi-round progression by re-invoking the reviewer with a new review_request for round N+1.
Message schemas
Section titled “Message schemas”review_request (Author -> Reviewer)
Section titled “review_request (Author -> Reviewer)”id: "msg-20260213T1000Z-claude-001"from: claudeto: codextype: review_requestpriority: P1created_at_utc: "2026-02-13T10:00:00Z"related_pr: "86"subject: "Review: review loop protocol (#86)"body: | pr: 86 branch: claude/review-loop-protocol diff_summary: | Adds review loop protocol spec, reviewer workflow, reviewer runbook, 4 new message types in validate_message.py, tests, and CHANGELOG/inbox_outbox.md updates. max_turns_reviewer: 8 max_runtime_s_reviewer: 600Body fields:
| Field | Required | Description |
|---|---|---|
pr | Yes | Pull request number |
branch | Yes | Branch name under review |
diff_summary | Yes | Brief summary of the changes |
handoff_ref | No | Reference to a handoff packet if this review follows a handoff |
max_turns_reviewer | No | Hard turn budget for reviewer invocation (default 8) |
max_runtime_s_reviewer | No | Hard runtime budget in seconds (default 600) |
review_feedback (Reviewer -> Author)
Section titled “review_feedback (Reviewer -> Author)”id: "msg-20260213T1030Z-codex-001"from: codexto: claudetype: review_feedbackpriority: P1created_at_utc: "2026-02-13T10:30:00Z"related_pr: "86"subject: "Review feedback: round 1 (#86)"body: | findings_packet: packets/findings/20260213_review_loop_codex_r1.yaml round: 1 blocking_count: 2Body fields:
| Field | Required | Description |
|---|---|---|
findings_packet | Yes | Path to the findings packet (relative to project workspace) |
round | Yes | Current review round number (1-based) |
blocking_count | Yes | Number of blocking findings in this round |
escalation | No | Escalation marker (e.g., max_rounds_exceeded, reviewer_budget_exceeded) |
review_addressed (Author -> Reviewer)
Section titled “review_addressed (Author -> Reviewer)”id: "msg-20260213T1100Z-claude-002"from: claudeto: codextype: review_addressedpriority: P1created_at_utc: "2026-02-13T11:00:00Z"related_pr: "86"subject: "Feedback addressed: round 1 (#86)"body: | commit_sha: abc1234 changes_summary: | Fixed both blocking issues: - Added missing error handling for empty diff - Corrected max_rounds default from 5 to 2 round: 1 touched_files: - docs/protocol/review_loop.md - docs/protocol/inbox_outbox.md addressed_finding_ids: - F-001 - F-002Body fields:
| Field | Required | Description |
|---|---|---|
commit_sha | Yes | Commit SHA containing the fixes |
changes_summary | Yes | Summary of what was changed to address the feedback |
round | Yes | The round number whose feedback is being addressed |
touched_files | No | List of files edited to address findings |
addressed_finding_ids | No | List of finding IDs the author considers addressed |
review_lgtm (Reviewer -> Author)
Section titled “review_lgtm (Reviewer -> Author)”id: "msg-20260213T1130Z-codex-002"from: codexto: claudetype: review_lgtmpriority: P1created_at_utc: "2026-02-13T11:30:00Z"related_pr: "86"subject: "LGTM: review loop protocol (#86)"body: | quality_gate_result: pass merge_ready: true nits: - nit_id: NIT-001 tier: P3 summary: "Clarify timeout fallback wording in docs/protocol/review_loop.md" owner: claude next_action: "Open doc cleanup PR after merge"Body fields:
| Field | Required | Description |
|---|---|---|
quality_gate_result | Yes | pass or fail |
merge_ready | Yes | Whether the PR is ready to merge (true or false) |
nits | No | Structured list of deferred non-blocking items |
Quality gate
Section titled “Quality gate”The reviewer sends review_lgtm when the quality gate passes. The gate passes when all of the following are true:
- No unresolved P0 findings (always blocking).
- No unresolved blocking findings (P1 and blocking P2).
- Deferred non-blocking findings (P2/P3) are captured in
review_lgtm.nitswith owner and tracking. - All validation commands recorded with passing outcomes.
If any blocking item remains, the reviewer sends review_feedback instead.
Risk-tiered findings
Section titled “Risk-tiered findings”Every finding in review_feedback is tagged with a severity level:
| Severity | Merge impact | Blocking? | Examples |
|---|---|---|---|
| P0 | Always blocking | Yes | Security vulnerability, data loss, crash in production |
| P1 | Blocking | Yes | Correctness bug, missing error handling, broken API contract |
| P2 | Reviewer judgment | Depends | Performance concern, test gap, unclear naming |
| P3 | Non-blocking | No (nit) | Style preference, minor refactor suggestion, typo |
Authors must resolve all P0 and P1 items. P2 items are resolved or deferred based on reviewer judgment. P3 items can be deferred and tracked as nits in review_lgtm.
Round limits
Section titled “Round limits”The review loop enforces round limits to prevent unbounded iteration:
- Default: 2 rounds maximum.
- Configurable: Up to 3 rounds via project configuration.
After the maximum number of rounds, the reviewer must issue a final verdict regardless of remaining items.
Budget controls carried in review_request:
| Parameter | Description | Default |
|---|---|---|
max_turns_reviewer | Maximum reasoning turns per review round | 8 |
max_runtime_s_reviewer | Maximum wall-clock seconds per review round | 600 |
When a budget is exhausted before review completion, the reviewer sends review_feedback with escalation: reviewer_budget_exceeded and exits.