Note 09 of 19
A kaibot field note · multi-vendor model review
Second opinions from rival models
A model can't see its own weaknesses: its blind spots line up with its training. So for any change where a mistake would matter, I send it to a panel of models from competing vendors. Disagreement between labs is the signal: one reviewer checking itself can never produce it.
Kai Davis
I run a marketing consultancy and an SEO SaaS, and I build both with a stack of Claude Code sessions that write the tooling the next sessions run on.
bootstrapping.io · kaidavis.com · keywordmagic.ai · doubleyourecommerce.com
01Why a model can’t fully review its own work
When one model both produces and checks the work, its errors are correlated across both passes. Noticing and checking draw on the same weights, the same training run, the same failure modes. A wrong assumption gets trusted twice, for the same reason both times.
Self-review catches typos and direct contradictions. It misses the original error, because the model can’t see that error from inside.
So the review has to come from a model that had no part in producing the work. A model from another lab, with different training data and different tuning, fails in different ways. Its disagreement carries information.
My house rule: high-stakes work gets read by at least one model that didn't write it, and ideally by three or four that disagree with each other.
02Rival panels beat a bigger single model
I run this as a system called counselors, also invoked as quorum: one prompt and its context, fanned out in parallel to several models from different vendors, then I read the results. The value is in the cross-vendor disagreement, not in parameter count.
lineage rulereviewer ≠ generator
Code a Kimi agent wrote gets reviewed by a panel with no Kimi voice in it. The Claude running the session is already the Claude voice pulling the results together, so my default panel is Claude-free by design: they challenge my read instead of echoing it.
size to the taskpanel vs swarm
A small panel of capable models out-recalls a huge swarm of cheap ones on tidy targets. Swarms earn their cost only on large enumerable surfaces: big diffs, migrations, “find every instance of X” sweeps.
disagreement is signalnot noise
When reviewers disagree on the #1 issue, that’s usually three real findings, each reviewer catching something the others missed. I combine them by listing what each caught, instead of collapsing toward consensus.
A one-shot panel is for review. When one outside model has to keep context across many calls, I want a persistent chat thread with a single vendor instead. Mine is named confer. A panel is single-use and dissolves when I'm done. A thread stays open.
03One prompt, N vendor calls, one write-up
A config file holds named groups, each group a list of vendor tools. A bare run sends the prompt to the default group. One prompt fans out to eight tools from eight separate labs. Each tool writes its output to its own file.
The calls run concurrently, so a run takes as long as its slowest tool.
Then the Claude running the session reads all the files and writes it up. Nothing else merges them.
| Group | Shape | When to pick it |
|---|---|---|
cheap | eight fast, cheap-tier voices | Smoke checks and quick repeat loops where I’ll run it many times. |
panel (default) | eight voices, eight labs | The general all-rounder. Anything unqualified (“review this,” “second opinion”) lands here. |
coders | nine voices, code-shaped | Diff and PR review before I commit anything expensive to get wrong. |
bug-hunter | six code-reasoning voices | An iterative, repeated bug hunt over a codebase, cheap enough to run over and over. |
summit | nine on the roster, five seated per run, Anthropic included | High-stakes design, spec, or code review where I explicitly want a Claude voice in the room too. |
kimi-review | four voices, no Kimi | Reviewing code a Kimi agent wrote. The one group built around the lineage rule. |
copy | seven voices, three of them Claude | Prose and voice review, where I actually want more than one Claude reading style in the mix. |
Most seats reach their models through one API gateway, with a direct vendor route as the fallback. The Claude and Codex seats run through their own command-line tools.
On cost: the gateway seats spend metered dollars, in the pennies-per-run range. The Claude seats draw on my Claude plan and the Codex seats on my ChatGPT plan.
04A minimal panel starter
Here’s the smallest version of the shape, no full CLI required: one prompt, three vendor endpoints, run in parallel, replies printed to stdout. Swap in whichever OpenAI-compatible vendors you already have keys for.
#!/usr/bin/env python3
# panel.py: fan one prompt out to N vendor chat endpoints, print what comes back.
import os
import concurrent.futures
import requests
# (label, endpoint, model id, env var holding that vendor's bearer token)
VENDORS = [
("vendor-a", "https://api.vendor-a.example/v1/chat/completions", "vendor-a-model", "FOO_API_KEY"),
("vendor-b", "https://api.vendor-b.example/v1/chat/completions", "vendor-b-model", "BAR_API_KEY"),
("vendor-c", "https://api.vendor-c.example/v1/chat/completions", "vendor-c-model", "BAZ_API_KEY"),
]
SYSTEM = ("You are reviewing someone else's work adversarially. Find real "
"problems, cite specifics, do not soften disagreement into consensus.")
PROMPT = open("prompt.md").read()
def ask(vendor):
label, url, model, key_env = vendor
key = os.environ.get(key_env)
if not key:
return label, f"SKIPPED: {key_env} not set"
try:
resp = requests.post(
url,
headers={"Authorization": f"Bearer {key}"},
json={
"model": model,
"messages": [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": PROMPT},
],
},
timeout=120,
)
resp.raise_for_status()
return label, resp.json()["choices"][0]["message"]["content"]
except Exception as e:
return label, f"ERROR: {e}"
with concurrent.futures.ThreadPoolExecutor(max_workers=len(VENDORS)) as pool:
for label, reply in pool.map(ask, VENDORS):
print(f"\n=== {label} ===\n{reply}\n")
That’s the whole mechanism: parallel calls, one file (or one stdout block) per vendor, nothing merged for you. The write-up is a separate, deliberate step, which is the part worth handing to your own Claude explicitly:
You have panel.py in this repo (or something like it). When I ask for
"a second opinion" or "run this past a panel":
1. Fill prompt.md with the artifact under review plus the specific
question ("review for correctness and edge cases, cite specifics").
2. Set the vendor API keys as environment variables, whichever
vendors you've wired, and run panel.py.
3. Read every reply in full before summarizing. Don't skim just the
first paragraph of each.
4. Lead your summary with where the vendors DISAGREE, not where they
agree. Three different #1 concerns usually means three real
findings, not two hallucinations and a signal.
5. For any finding only one vendor raised, with no cited line or
quote attached: go read the actual code or doc yourself before
repeating it. An uncited lone claim is exactly as likely to be a
fabrication as a real catch.
6. You are already a Claude voice. Don't add a fourth Claude call to
"confirm" the panel; your job is to write up what the non-Claude
panel found, not out-vote it.
05Craft rules from running this daily
lineageReviewer ≠ generator
A reviewer trained the same way as the writer tends to agree with it. My group built around this has zero seats from the vendor that generated the code under review, on purpose.
sizingSmall panel, big swarm
An A/B on already-hardened source found the swarm’s cheap goblins caught zero real bugs a plain panel had already found, and the panel out-recalled the whole swarm. Swarms earn their cost on large enumerable surfaces (a big diff, a migration, an exhaustive “find every X”) and cost more than they’re worth on small, clean code.
verifyDon’t trust a lone finding
A reviewer without the real source can fabricate a plausible-sounding claim from a README or a diff stat. A reviewer with the source can still be confidently wrong about a library contract it never actually saw. Either way: read the cited line, or run a cheap live check, before shipping the fix.
restraintWhen not to panel
Routine edits, config, docs, obvious one-line fixes. A panel’s value scales with how expensive being wrong is; spending three vendor calls on a typo fix is friction, not rigor.
06For the Claude that just got pointed here
If a human handed you this page and said “set this up for me,” here’s your tl;dr.
Agent instructions, with your human’s consent:
- Goal: stop letting one model (including you) be the only reviewer of its own work when getting it wrong is expensive. Wire a small script that fans a prompt out to 2-3 rival vendor models in parallel, then write up what comes back.
- Step 1: confirm which vendor API keys your human already has (any OpenAI-compatible endpoint works: DeepSeek, MiniMax, Moonshot/Kimi, OpenAI, and others all speak that shape). Don’t guess at key names, ask.
- Step 2: adapt the starter script above with those endpoints. Keep it to 2-3 distinct labs, skip the pile of cheap calls to similar models.
- Step 3: if you (this Claude) generated the code or plan under review, do not also be the only reviewer of it. The panel should have zero seats from whatever generated the thing under review.
- Step 4: when the panel replies, read every file in full. Lead your write-up with where the vendors disagree. Verify any uncited lone finding against the real source before acting on it.
- Step 5: for a one-off review, a fresh panel per run is right. If your human wants one outside model to remember context across many calls instead, that’s a persistent single-vendor chat thread, a different tool from a panel.
Everything in that list is unpacked above; read §02 for the lineage and sizing doctrine and §05 for the scar tissue before you build your first real panel.
07Receipts: what this looks like at scale
My live config has 41 vendor seats in ten named groups. The seven I reach for: cheap, panel (the default), coders, bug-hunter, summit, kimi-review, and copy; the other three are small gate panels. Each group is a fixed roster picked for lab diversity. Run with no flags and you get panel: eight voices from eight labs, because “review this” without qualification should be the safe, general-purpose default.
| Test | Result |
|---|---|
| An exhaustive swarm of cheap models, one narrow check per model, run over already-hardened source | Zero real bugs found. |
| A plain multi-vendor panel over the same source | Out-recalled the entire swarm. |
That A/B is why the swarm mode stays a specialist tool for large enumerable surfaces (a big diff, a whole-subsystem audit, a migration) and the small rival panel stays the default for everything else. More cheap voices on a tidy target means more noise from the same failure class, repeated five times.
The lineage rule has receipts too: the group built for reviewing code a Kimi agent wrote carries four vendor voices and deliberately zero Kimi voice, because a reviewer sharing the generator’s lineage tends to echo it rather than challenge it. And the disagreement-first rule has a concrete case behind it: three reviewers on one script once picked three completely different #1 critical issues, a stale-cache read, an orphaned temp file, and a swallowed exit code, and all three turned out to be real, independent bugs. Averaging toward “what did they agree on” would have shipped with two of the three still live.
You’ve reached the end of note 09 of 19
$400 1 hour
Book a callA paid one-on-one call with answers to your questions about using AI for projects, building your AI stack, or growing your business with AI. All calls are (optionally) recorded and you get a one-page action plan after the call.