AI-Driven Development Playbook (for Agents)
This page is a practical, case-by-case guide for AI agents (autonomous / semi-autonomous coding agents) on when and how to call River Review. In AI-driven development the agent writes and fixes the code, but the key is to let River Review gate the work and read its (JSON) output to decide the next action mechanically. What you use here is part of River Review's three axes — turning tacit knowledge into versioned, repo-owned Skills (a Skill Registry) shared as a team asset: the capability pack (usually no LLM key needed), the review skills, and a review team of perspective-based reviewers paired with a verdict-bearing critic. River Review only emits findings and a verdict as decision material; it never auto-approves (HITL).
For the minimal per-tool invocation (Claude Code / Cursor / Codex / Copilot), see Use River Review from an AI agent. This page covers case-by-case usage along the AI-driven development loop.
The agent's stance (5 principles)
- Don't review yourself. Let River Review gate. Instead of the agent's own judgement, have the deterministically-routed skills review, and act on the result.
- Read JSON, not human-facing text. Use
--output jsonand consumeriver run'sissues[]/summary.issueCountBySeverityandriver review'sfindings[]as structured data.--output markdownis for humans (PR comments) — the human-readable summary appears there; the machine-readabledecisionis also included in JSON output. - Branch on exit code and severity. With
--fail-on <severity>, finding severity becomes the exit code (1=fail / 2=warn / 0=pass) on bothriver runandriver review. The agent branches on the exit code, or onsummary.issueCountBySeveritycounts: proceed / fix / escalate to a human. - Trust deterministic routing. Which skills were selected/skipped (with reasons) is visible in
--debug(selectedSkills/skippedSkills). Selection is decided by phase, target paths, and input context, and reproduces every time. - Understand the execution model (usually no LLM key is needed). When you (the agent) load the skills / sub-agent and review with your own model, no River Review LLM key is needed. The
river run/river reviewcommands on this page are the headless path, where the agent calls River Review as an external tool — only then is an LLM key (ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_API_KEY) required (the 12 mechanical-check viewpoints still run without one, and--offlineruns rules-only explicitly). See What is River Review § Execution model.
Where River Review sits in the AI-driven development loop
River Review only emits findings and a verdict; the final GO/NO-GO decision is made by whoever calls the gate (the agent or PlanGate).
Case by stage (primary axis)
Case 1: Before work — requirements / design / plan review (pre-exec gate)
Before implementation, eliminate requirement ambiguity, missing validation in the design, and plan inconsistencies.
# Execute (produces findings / needs an LLM key). pre-exec skills are
# upstream-phase, so --phase upstream is required.
river review exec --skill-set pre-exec --phase upstream \
--artifact pbi-input=pbi-input.md \
--artifact plan=plan.md \
--artifact adr=docs/adr/001.md \
--output json
# Without a key, just preview which skills would run (the plan)
river review plan --skill-set pre-exec --phase upstream --plan-only \
--artifacts-dir ./planning
- Input:
pbi-input(requirements) /plan/todo/test-cases/adr(design). - Output: a Review Artifact (
findings[]+plan+debug). Read each finding'sseverity/message/suggestion. - Agent's next action: fold the
findingsand any open points inmessageback into the plan, then start implementing. If there is acritical, do not start implementing. - Note: the
--artifactfiles (pbi-input.md, etc.) must already exist; an unresolvable path exits 3.
Case 2: During / right after implementation — self-review and self-fix loop
Right after the agent writes code, review its own diff and self-fix from the findings.
river run . --base main --output json
- Output:
{ issues[], summary, decision }(output.schema.json). Readissues[].severity(critical/major/minor/info) andmessage/file/line. - Stop condition: use
critical + major == 0as the convergence condition. Escalate immediately whendecision == "human-review-required"or whenriver runs diffreturns non-emptyoscillated.decision === 'auto-approve'alone is not a stop condition — it can be returned even when minor / info findings remain. For the full composite formula, see Loop Convergence Contract. - Agent's next action (self-fix loop): fix
issuesby severity → re-runriver run→ repeat untilcritical + major == 0. Escalate to a human if the loop does not converge. - For large tasks use
--depth thorough; to narrow scope use--files <glob>.--baseauto-detects the default branch when omitted, so on repos whose default is notmain(master/develop), omit it or pass--base <default>.
Case 3: PR submission gate — block mechanically via exit code
Before opening a PR, gate the CI / agent pipeline by a severity threshold.
river run . --base main --fail-on critical --warn-on major --output markdown \
--output-file ./review.md
- exit code: non-zero only when
--fail-on/--warn-onis specified.0=pass /1=fail (≥--fail-on) /2=warn (≥--warn-onbut <--fail-on). Without--fail-on, River Review always exits 0 regardless of findings — for machine decisions, readingsummary.issueCountBySeveritydirectly is more reliable. The agent branches on the exit code (fail → back to fixing, pass → continue the PR). - Post the
--output markdownresult as a PR comment (for human reviewers). Use exit code for machine decisions, markdown for human presentation. --advisory-onlyreports findings but always exits 0 (observation mode).
Case 4: Verification — W-check (re-audit a review result)
Have River Review re-audit another AI's / a human's review result to detect omissions, false positives, hallucinations, and missing evidence (double review).
river review exec --artifact review-self=./self-review.md \
--artifact review-external=./external-review.md \
--artifact diff=./diff.patch --output json
- The Independent Review Synthesis skill dedups and verifies, emitting a unified verdict. See W-check / Use Independent Review Synthesis.
- Useful in multi-agent development to fold each agent's review into one.
- Note: the dedicated
river review verifysubcommand has a defined contract but execution is not implemented yet (currently exit 3). Use thereview execpath above for W-checks.
Case 5: Multi-agent / parallel roles
Start multiple reviewer roles in parallel in a single river run.
river run . --reviewers bug-hunter,security-scanner,test-gap --output json
# or auto-decide roles from the diff content
river run . --reviewers auto --output json
- Get role-divided perspectives at once; results are returned deduped. See agent-workflow for how
--reviewers autoworks.
Task type × skill-set matrix (secondary axis)
Within each stage, pick --skill-set by task type (sets: adversarial / basic / comprehensive / multitenancy / pre-exec / review-quality / typescript).
| Task type | Main stage | Recommended --skill-set | Notes |
|---|---|---|---|
| requirements/design/plan | before work (Case 1) | pre-exec (--phase upstream) | pre-implementation gate |
| feature work | after impl / PR (2,3) | comprehensive | broad coverage |
| bug fix | after impl (Case 2) | basic | light & fast |
| refactor | after impl (Case 2) | review-quality | design quality / readability |
| security-sensitive | impl / PR (2,3) | comprehensive + --reviewers security-scanner | multi-perspective |
| multi-tenant SaaS | before work / impl | multitenancy | tenant isolation |
| TypeScript-centric | after impl (Case 2) | typescript | type / null safety |
| critical / high-risk change | before PR (Case 3) | adversarial | pre-mortem / war-game |
When no set is given, skills are auto-selected by phase, target paths, and input context. Start with no flag (auto) and reach for
--skill-setonly when you want to narrow the lens.⚠️ phase trap:
comprehensive/multitenancy/adversarialbundle upstream skills (e.g.multitenancy-isolation/pre-mortem). Running them withriver rununder the default midstream silently skips those on a phase mismatch. To also apply the upstream lens, run a separate--phase upstream, or always check--debug'sskippedSkillsfor what actually ran.
Agent operations helpers
Features that keep an autonomous loop safe and efficient.
- Suppress false positives (avoid infinite loops): when a finding cannot be fixed or is an accepted risk, record it with
river suppression add --fingerprint <fp> --feedback <false_positive|accepted_risk> --rationale "...". Without this the agent re-flags the same finding every iteration and the self-fix loop never converges. - Convergence signal (run persistence): use
--saveto store under.river/runs/, thenriver runs diff <id> <id>orriver run . --baseline <prev json>to compare new-vs-fixed. Judge convergence by whether findings are decreasing, not byloop_countalone. - Cost ceiling (runaway guard): for deep reviews or large diffs use
--max-cost <usd>(abort if the estimate is exceeded) and--estimate(estimate only) to cap runaway LLM spend.
Agent implementation pattern (pseudocode)
# pre-work gate
plan_result = run("river review exec --skill-set pre-exec --phase upstream --artifact ... --output json")
if any(f.severity == "critical" for f in plan_result.findings):
resolve(plan_result.questions, plan_result.findings) # fix the plan, re-run
goto pre-work gate
implement() # the agent implements
# self-fix loop
loop:
result = run("river run . --base main --fail-on critical --output json")
if result.exit_code == 0: break # pass
fix(result.issues) # fix findings
if loop_count > N: escalate_to_human(result.summary) # escalate if it does not converge
# Render the PR comment from the JSON already obtained (re-running river run
# would duplicate the LLM call, so avoid it).
open_pr(to_markdown(result.issues))
Key points: consume JSON structurally and branch on exit code / severity (summary.issueCountBySeverity); do not parse text. Escalate to a human if it does not converge (River Review only supplies decision material; avoid infinite self-fixing).
Anti-patterns
- ❌ Regex-parsing human-facing text → use
--output json(issues/findings). - ❌ Applying every River Review finding unconditionally → triage by
severity. Routeinfo/minorto follow-ups and make onlycriticala blocking condition (review policy; whethermajoralso auto-gates depends on calibration). - ❌ Expecting real findings with no key → without a key it is heuristic / empty. Set a key in CI.
- ❌ Expecting
review verifyto execute → it is a stub (exit 3). Usereview exec --artifact review-self/externalfor W-checks. - ❌ Calling pre-exec without
--phase upstream→ upstream skills are phase-mismatched and all skipped.
Output contract quick reference
| Command | JSON schema | Main keys |
|---|---|---|
river run | schemas/output.schema.json | issues[], summary.issueCountBySeverity, summary.issueCountByPhase, decision |
river review plan/exec | schemas/review-artifact.schema.json | version, status, phase, findings[], plan, debug |
The
decisionfield inriver run --output json(auto-approve/human-review-recommended/human-review-required) is derived deterministically from findings. It is omitted when scoring fails, so check for its presence before reading it. Make machine decisions from the exit code (--fail-on),summary.issueCountBySeverity, anddecisionin combination. Forriver review plan/exec, the verdict is available as thedecisionfield in the Review Artifact.