Give a Second Coding Agent a Review Task, Not a Vote

Drafted and reviewed using AI assistance.

On this page

When an agent finishes a change, give the second reviewer the original requirement, the exact candidate and a question it can investigate. “Another AI agrees” is less useful than a finding you can trace to the code and a concrete example.

Start by deciding what the reviewer must return: a scoped finding, the relevant artifact, the consequence and the next check or correction. GitHub's task-scoping guidance recommends a clear problem, acceptance criteria and relevant file directions. Those inputs are useful for a review request too. They do not establish that two agents have independent errors or that either has inspected the right version.

Put one requirement beside one candidate

Here is a complete fictional request, PICK-4:

Hide archived projects from the project picker.
Keep the remaining projects in their input order.
Do not rename titles or modify the input records.
Keep the change inside visible_projects.

Inputs in this exercise are lists of records with id, title and archived.
This function does not decide who has access to a project.

The original function returned every record:

def visible_projects(projects):
    return list(projects)

Candidate C1 makes this proposed change:

 def visible_projects(projects):
-    return list(projects)
+    return sorted(
+        (p for p in projects if not p["archived"]),
+        key=lambda p: p["title"],
+    )

The complete shared example is deliberately not alphabetized:

[
  {"id":"P3","title":"Zulu","archived":false},
  {"id":"P1","title":"Alpha","archived":false},
  {"id":"P2","title":"Beta","archived":true}
]

PICK-4 requires IDs P3, P1. C1 removes P2 but also sorts the two remaining records, producing P1, P3. That small counterexample can decide the ordering question without a vote about which report sounds more confident.

The candidate packages, complete patch and four-case fixture accompany the example. Candidate names are teaching labels. The identity file binds their actual file bytes; they are not Git commits or captured project history.

Give the reviewer a job it can inspect

Compare two input packets for the same C1 candidate.

Packet A leads with the implementer's verdict:

The implementer says the picker is fixed: archived projects are hidden,
the list is cleaner and the change is ready. Confirm that this is good.

Candidate: C1/visible_projects.py, supplied with this request.
Requested feature: hide archived projects.

This packet omits the input-order constraint and asks for confirmation of a conclusion. The candidate reference is useful, but the reviewer has not received the complete decision basis.

Packet B leads with the requirement and evidence:

Review C1/visible_projects.py against PICK-4 below. Do not edit files.

Requirement:
Hide archived projects. Preserve retained input order. Keep titles and
input records unchanged. This is a display helper, not an access check.

Use the supplied BASE-to-C1.patch and review-cases.json. Confirm which
candidate bytes you inspected. Compare the mixed P3/P1/P2 case with the
required P3/P1 output, then consider empty and all-archived inputs.

Return each material finding with requirement, code location, concrete
input, actual or predicted output, expected output and impact.
Separate reading/manual reasoning from checks you actually run.
State what you cannot establish about callers or the rendered picker.
If an artifact is inaccessible or belongs to another candidate, report
that gap instead of issuing an application-level acceptance.

Packet B makes the review inspectable. It is not an experimental demonstration that this wording improves a particular model. A new chat or another model also does not tell you which project instructions, memories or external references the host supplies. Verify that setup when it matters; do not call the review blind merely because its prompt omits the first report.

Resolve conflicting reports by their claims

The following two reports are entirely authored teaching examples. They are not actual model responses, observations of agent performance or results from an independent-review experiment.

Authored report R1 — accept C1:

Candidate inspected: C1/visible_projects.py.
Method: read the shown patch; no test run reported.

The generator excludes archived records. sorted returns a list, and
alphabetical titles make the picker easier to scan. I recommend accepting
the function change. I have not inspected the calling UI or rendered it.

Evidence: the archived predicate and title sort are visible in the patch.
Remaining work: check the actual picker before release.

Authored report R2 — return C1 for an ordering correction:

Candidate inspected: C1/visible_projects.py.
Method: read PICK-4 and manually evaluate the supplied mixed fixture.
No test run is claimed in this report.

Finding: sorting by title violates PICK-4's retained-input-order rule.
For P3/Zulu active, P1/Alpha active, P2/Beta archived, the predicate leaves
P3/P1 and the sort changes that to P1/P3. Required output is P3/P1.

Requested correction: filter while retaining iteration order; preserve
the function boundary and input records. Check the same case, empty
input and all-archived input against the corrected candidate.

Application limitation: no caller or actual picker view was inspected.
Do not accept the complete UI from this function-only review.

Both reports correctly notice that archived records are removed. Their disagreement is about whether the extra ordering behavior is acceptable.

Claim Available basis Decision
C1 excludes archived P2 Predicate and supplied data Supported for the case
Alphabetical order is an improvement to accept R1's preference It conflicts with the explicit input-order requirement
C1 returns P1/P3 instead of P3/P1 Manual evaluation of the exact fixture Concrete reason to return C1
The actual UI works Neither report inspected it Unestablished

The outcome is not “R2 wins.” Return the specific violation with its evidence. If two reports both said “accept” but neither supplied the required order check, their agreement would still leave that check missing.

There is also a valid outcome without a code verdict. Suppose a reviewer is asked to inspect C3 but can open only the C1 excerpt. Its bounded reply is: “C3's complete candidate is inaccessible. I can comment on the supplied C1 excerpt, but cannot accept C3. Supply its identified files and relevant check records.” Substituting the available older patch would conceal the evidence gap.

Correct the candidate, then identify what was checked

C2 makes the narrow correction:

def visible_projects(projects):
    return [p for p in projects if not p["archived"]]

The complete C1-to-C2 patch removes sorting. The fictional owner then makes a separate request: “In notes.txt, change Project picker review example. to Project picker review teaching example. Make no code changes.” C3 includes that notes-only change; its visible_projects.py bytes are identical to C2. The separate request does not alter PICK-4. All three retain the fictional branch label picker-review, which therefore cannot identify the reviewed bytes by itself.

The accompanying local teaching run used Python 3.9.6. Four requirement cases ran against each candidate. C1 failed the two cases that distinguish input order from alphabetical order; C2 and C3 passed all four. Those are actual executions of the supplied tiny functions. They are separate from the invented reports above and do not exercise a project picker, browser or agent.

Python's fixed 3.9 unittest documentation describes assertEqual as an equality check. Here equality of the returned ID sequence is the relevant assertion; merely checking membership would miss the order change. The documented series and recorded local runtime are separate identifiers.

Keep logs, pictures and conclusions attached to their candidate

Suppose a review folder contains these materials:

Material Candidate and status What it can support for final C3
F1: “module imports” record Fictional story record for C1; not an observed log No passing order claim; the record never checked order
Actual C1 four-case log C1; two recorded requirement failures Explains the old defect; does not establish that C3 still has it
Actual C2 four-case log C2; zero failures Relevant to the unchanged function and same cases, with that narrow scope
Actual C3 four-case log C3; zero failures Directly supports the four C3 function cases
I2: expected picker picture Authored C2 illustration, not a browser capture Visual reference for desired order; no rendered-UI evidence
I0: picture without candidate identity Authored illustration with an intentionally unbound story record No basis for attributing the view to C3
R1's acceptance Invented report about C1 Does not become a C3 review by keeping the branch label

Authored expected picker illustration; not a browser capture

The unbound illustration and authored evidence ledger make the missing provenance explicit. A drawing of the expected result can help communicate an intention; it cannot establish that the application produced it.

C2's function evidence remains relevant to C3 because the named function file, fixture and checked behavior are unchanged. That reason does not extend it to the complete application. If C3 instead changed the caller's ordering, a render path or an input transformation, the old helper check would not settle that new behavior.

Choose the next check from the actual change. After the ordering correction, check the function against the order-sensitive cases. Before accepting the application, inspect the real caller and verify its rendered order in the authorized environment. Do not rerun unrelated checks just to produce a longer evidence list, and do not reuse a picture whose relationship to the candidate is unknown.

Send a scoped decision and a reusable review request

The worked decision is:

Return C1 for the PICK-4 ordering violation demonstrated by P3/P1/P2.
The C2 correction removes that extra sort. C3 changes only notes; its
function bytes match C2, and the recorded local cases pass for C3.

Accept the illustrated helper behavior for these four in-scope cases.
Keep application acceptance open: the real caller, rendered picker and
deployment were not checked. The drawn preview is a reference, not a run.

For your next task, adapt this complete reviewer request:

Review [exact candidate/artifact identity] against [current requirement].
Read the original requirement before the implementer's conclusion.
Work read-only; do not repair, merge, publish or broaden this step.

Confirm the files/bytes or other usable version identity you inspected.
For each material finding, give the requirement, location, concrete case,
expected result, observed result or clearly labeled manual prediction,
and the consequence. If there is no finding, state the checked scope.

Match each log, screenshot and prior review to the candidate it covers.
For any reused check, explain what stayed unchanged and which conclusion
still follows. Missing artifact access or provenance remains unknown.

Return a bounded accept/return/needs-evidence decision with the smallest
relevant correction or next check. Agreement with another reviewer is
not a substitute for that evidence. State actual execution separately.

The implementer can then address a concrete finding, and the reviewer can check the resulting candidate. The reports are useful because their claims can be inspected, not because there are two of them.