Multi-Review
Overview
Multi-review is a generic review pattern: look at an artifact through several
independent lenses, preferably using more than one model family, then synthesize the
findings into concrete next actions.
This is not only an outbound-communication gate. Outbound comms are one important
case, but the same pattern works for code, skills, plans, prompts, migrations, research,
public posts, tool actions, config changes, incident reports, and decisions with real
blast radius.
The point is diversity without chaos:
- Different lenses catch different failure modes.
- Different model families catch different blind spots.
- A synthesis pass deduplicates, rejects false positives, and turns feedback into
action.
- A meta-review pass checks whether the review itself was useful or noisy before the
caller declares the artifact ready.
When to Use
Use this skill when the user says:
- "review this", "sanity check this", "second pair of eyes", "is this ready?"
- "check this before I send/post/ship/merge/run it"
- "run a multi-review", "get Grok/Gemini/GPT on this", "use multiple reviewers"
- "look over this plan", "review this PR", "review this skill/prompt"
- "is this safe?", "what am I missing?", "red-team this"
Also use it proactively before high-stakes actions:
- Code or config changes that will be committed, deployed, or rolled across machines
- Public or customer-visible writing
- Messages sent as a human/operator
- Data migrations, deletes, permission changes, or credential-handling changes
- Skill, prompt, or agent-behavior changes that future agents will follow
- Research summaries where citations, uncertainty, or omitted evidence matter
Do not use for:
- Trivial private-chat responses
- Purely read-only information gathering
- Cases where the user explicitly says not to review or says "no further action"
- Emergency containment where pausing for review would increase harm; contain first,
review the follow-up
Core Contract
A good multi-review run does these things, in order:
- Define the target. Identify the artifact or action being reviewed, the intended
audience, and the stakes.
- Choose review depth. Pick quick, balanced, or deep based on risk.
- Choose a diverse panel. Select lenses and model families appropriate to the task.
Whenever the run has two or more seats, staff for both generation and
verification — those are usually different seats, not one strong seat (see
"Verification and originality are usually different seats"). A single-seat run
cannot split the roles; it carries the generator/verifier tension inside one prompt
and is stamped degraded accordingly.
- Run reviewers independently. Keep reviewer prompts isolated so they do not anchor
on each other's conclusions.
- Synthesize. Deduplicate findings, classify each as fix / ask / defer / wontfix,
and decide whether the artifact is ready.
- Act. Apply obvious low-risk fixes when authorized; ask once for judgment calls;
defer only when scope genuinely exceeds the task.
- Meta-review. Check whether the review was useful, whether the panel missed an
obvious lens, and whether false positives were handled correctly.
- Iterate until ready. Re-run targeted reviewers after material fixes, especially
for high-stakes or public-facing artifacts.
Never claim "multi-model review" unless multiple model families actually ran. If model
routing is unavailable, say degraded: single-model and explain what still ran.
Count a reviewer only when it returned substantive review output. A seat that merely
started, printed setup or shell noise, hung, or was killed is a failed seat, not an
independent lens. A same-family external reviewer does not by itself clear a
single-model-family degradation. Report completed seats and distinct model-family
coverage separately — they are different numbers and conflating them overstates the
review.
Do not stall silently. Give each reviewer a deadline. Once the expected window
passes, poll for partial output rather than waiting indefinitely. If a seat times out or
returns empty, replace it when the selected depth still requires that coverage;
otherwise synthesize only if the completed seats still meet the depth floor for this
target. A degraded panel that drops below its floor is not a finished review — say so
instead of shipping it. Report which seats completed, which failed, and which families
are missing, and lower confidence to match what actually survived.
Execution hierarchy
Use the strongest practical isolation mechanism available, but match it to the task's
shape:
- Headless Hermes one-shots in isolated scratch homes
(
hermes -z... -t '', each with its own HERMES_HOME) — the default. This
is the only path that delivers a different prompt AND a different model per
seat ("Grok, be critical"; "Claude, be empathetic"), and the only path
where you can size the timeout to the job. Isolation is mandatory, not
optional — see "Isolate every headless reviewer" below. Use a higher timeout
than the default for real reviews; 300-600 seconds is usually reasonable, and
deep/slow model panels may need the upper end. See execution rule 3 — the
default is very likely lower than you want.
- Native subagents when every seat can run on the same model and you only
need lens diversity: prompts, context, and failures are naturally isolated.
Two tradeoffs before choosing this path. First, the delegation tool has
no per-task model parameter, and upstream has repeatedly declined to add
one (PRs #17718, #23266, #25026, #34773, #36790; maintainer on #34773: "We do
not want this"). Every child in a batch runs on the single configured
delegation model, so this path cannot staff a multi-model panel — do not plan
one around it. Second, a subagent's runtime almost certainly gives you no
per-call timeout control: the schema exposes goal, context, role, and output
schema — not a deadline. Any wall-clock cap is process-wide configuration read
at call time, so a skill cannot scale it to the artifact. If this review needs
a deadline proportional to its scope, use path 1 or 3.
- Parent-gathered I/O + reviewer one-shots for open-ended or I/O-heavy review work
(large filesystem searches, email/search crawls, binary downloads, multi-step data
collection). Do the I/O in the parent with normal tools, reduce it to a bounded
brief, then send that brief to reviewers. Do not hand an open-ended crawl to a
subagent whose deadline you do not control: if a wall-clock cap is configured, the
child is killed mid-task and its findings die with it, and if none is configured a
wedged child stalls the panel instead. Either way the review fails before synthesis.
- Same-model subagents with different lenses when only one model family is
available. Increase lens diversity, include at least one contrarian reviewer and one
meta-review, and stamp
degraded: model-diversity unavailable.
- Manual single-pass review only for quick/low-stakes work that is below every
minimum depth floor (see below). Never use this mode for money/auth/secrets/user-
data/irreversible/public/rollout targets, even if they look small. Stamp
degraded: single-reviewer and do not present it as a panel.
Privacy applies to every path. The re-injection rule in execution rule 3 below is
not specific to --ignore-rules: any isolated reviewer — native subagent, headless
one-shot, or same-model subagent — runs without the calling context's project rules. If
the artifact may contain private data, or you are in a repo with a privacy/PII policy,
copy those constraints into every reviewer prompt regardless of execution path.
Depth Scaling
Quick — 1-2 reviewers. Use for low-stakes drafts, small edits, or a simple sanity
check.
Balanced — 3 reviewers. Default for meaningful work. Cover the primary domain,
truth/correctness, and user/audience impact.
Deep — 5+ reviewers plus meta-review. Use for security-sensitive changes, public
posts, fleet/config rollouts, irreversible actions, architecture, migrations, or changes
that future agents will rely on.
If unsure, use balanced. Escalate to deep when any reviewer finds a high-severity issue
or when the artifact will be hard to undo after release.
Minimum depth floors
Certain targets should never get only a quick pass:
- Code that handles money, auth, permissions, secrets, user data, networking, or data
migration → balanced minimum; deep if public or production-bound.
- Irreversible tool actions, deletes, permission changes, or fleet/config rollouts →
deep minimum plus explicit approval/rollback review.
- Public-facing policy, docs, prompts, or skills that future agents will follow →
balanced minimum; deep if the instructions affect safety boundaries.
- Messages sent as a human/operator, legal/medical/financial statements, or sensitive
interpersonal comms → balanced minimum with empathy, evidence, and data-exposure
lenses.
Model Family Selection
Prefer a reviewer from a different model family than the calling agent. Independence
matters more than raw benchmark rank.
Use the models configured in the local Hermes profile. Do not hard-code API keys. If the
profile has aliases such as custom:grok, custom:gemini, or custom:openrouter, use
those; otherwise inspect the local config and choose equivalent provider/model pairs.
Pair each alias with the provider block the local config actually wires it to, and do
not "normalize" a reviewer onto a different provider for tidiness. When one router is
exposed through several provider blocks, they usually differ by API shape
(chat_completions vs anthropic_messages), and the better block depends on the
upstream model family: Claude models are natively Anthropic-shaped, most others (OpenAI,
xAI, Google) are natively OpenAI-shaped. The wrong block still returns HTTP 200, so this
fails silently rather than loudly. If an existing config contradicts that, assume it is
deliberate until you have checked why.
Family strengths
The notes below combine general observation with one measured data point: a
multi-model bake-off where eight models were given the same open-ended research and
ideation brief, and their outputs were scored across seven weighted dimensions
(mandate discipline, evidence quality, originality, verification, usability, and
related axes). Findings from that run are marked [measured]. Everything else is
ordinary heuristic.
Read the scope honestly: that was one task, scored once, N=1 per model, and the
task was research and ideation, not critique of an existing artifact. Behaviors
that are themselves review-shaped — adversarial pressure-testing, mandate discipline,
verification effort — transfer to reviewing with reasonable confidence. Generative
traits like originality are a hypothesis about review behavior, not an established
one. Treat the whole section as a prior to check against the artifact in front of you,
not as fixed model properties.
Claude / Anthropic — best for synthesis, nuanced tradeoffs, voice, empathy, policy
interpretation, and turning messy findings into a coherent final answer. [measured]
Also the strongest self-critic in the run: it pressure-tested its own output
adversarially, which is review behavior directly. Its limit is divergence — it
scored lowest of the frontier models on originality, and every idea it produced also
appeared on another model's list. It is a convergence engine, not a divergence engine.
A panel staffed only with Claude models will produce a well-written consensus and miss
the objection nobody else thought of. Avoid using only Claude if the calling agent is
already Claude-family.
GPT / OpenAI — strong structured reviewer: code correctness, API contracts, tests,
consistency, and concise fix recommendations. [measured] Best at building the
evaluation scaffold, weakest at then executing it. It produced the best decision
framework in the corpus — a crisp set of screening questions others should have been
measured against — and then over-filtered its own candidates and delivered almost no
verification behind them. Give GPT the job of defining the review criteria, or the job
of applying them, but do not assume one seat does both well.
Gemini / Google — strong long-context reader: large diffs, logs, docs, and
cross-file consistency checks. [measured] Do not rely on it for evidence
extraction, despite the long-context strength: its evidence was correct but generic
and thin, list-shaped with no numbers behind the claims. Operational warning: in
that run a Gemini seat silently fell back to a different underlying model mid-thread
and kept answering as if nothing had changed. A reviewer that swaps model families
without telling you breaks the independence guarantee the entire panel rests on.
Verify which model actually answered before counting it as family coverage.
Grok / xAI — strong contrarian/red-team reviewer: assumptions, edge cases, blunt
risk, adversarial misuse, policy gaps, and "what would embarrass us if true?" checks.
[measured] The best mandate discipline in the run — it was the one model willing to
answer the question actually asked rather than the more flattering adjacent question,
and it rejected the framing it had been handed when the framing was wrong. That is
precisely what a red-team seat is for. [measured] Its failure mode is delivery: it
scored worst in the run on usability, producing genuinely excellent analysis and then
leaving nearly all of it in scratch files while its actual reply led with process
commentary. Grok needs an explicit output path and a demand for the artifact more than
any other family (see rule 7). High variance is useful for surfacing issues, not for
final wording.
Grok is also the family most likely to offer native live X-graph retrieval (via
xAI's x_search server-side tool) rather than general web search, which helps when the
question is "how are people reacting right now?" — public-facing copy, launch posts,
naming, positioning, and reputational blast radius. Live retrieval applies only when
the selected route actually enables that tool; otherwise treat Grok as cutoff-bound
like any other model.
Open-weight models (Kimi, Qwen, MiniMax, DeepSeek, Llama, and similar) — the
divergence seats. [measured] In that run the open-weight models produced the
genuinely novel material: the mechanisms and framings that appeared on no frontier
model's list. If a panel needs an idea the consensus will not generate — an unlisted
failure mode, an approach nobody considered, a structurally different objection — this
is where it comes from, and it is a real reason to seat one even when a frontier model
is available. [measured] They pair novelty with almost no verification: the same
seats that generated the new material asserted it without checking, and one of them
also scored near the bottom on usability. Their output is a lead to be verified, never
a finding to be trusted as-is. Cost and privacy (local or self-hosted execution) are
secondary reasons to use them; capability diversity is the primary one.
Small or local models — useful for cheap/private quick passes, syntax/style checks,
and obvious inconsistencies. Do not rely on them alone for high-stakes judgment. This
is a size/deployment distinction, not the open-weight distinction above: a large
open-weight model run through a hosted router is a full-strength seat.
Newer is not automatically stronger. A vendor's latest flagship, including one
marketed as a reasoning improvement over the previous flagship, may not outperform the
model it supersedes on your actual work. Two Anthropic frontier models in that run
finished close together despite one being positioned as the clear successor. Check the
newer model on a task you have already scored before promoting it to a panel seat by
reputation.
These family strengths are observed heuristics, not guarantees — they shift with
model versions and prompting. Verify against the artifact in front of you rather than
treating them as fixed properties.
Verification and originality are usually different seats
The single most useful structural finding from that run: the models that verified
heavily generated almost nothing new, and the models that generated the novel material
verified almost none of it. The correlation ran in opposite directions across the
whole field, frontier and open-weight alike.
Do not fight this by asking one seat to do both. Whenever the run has two or more
seats, staff for it:
- Seat at least one generator (open-weight models are the measured pick) whose job
is to produce candidate findings, including speculative ones.
- Seat at least one verifier (frontier models, Claude and GPT in that run) whose job
is to check the generator's claims against the artifact and kill the unsupported ones.
- Let the verifiers grade the generators. An unverified novel finding is a lead, not a
result, and it should be labeled that way in synthesis until someone checks it.
A panel of only verifiers returns a tidy consensus that misses the unlisted problem. A
panel of only generators returns a pile of confident claims you cannot act on. The
review is the interaction between them.
Single-seat runs are the documented exception. A quick-depth check or the
degraded: single-reviewer fallback has one seat and cannot split these roles. Do not
try to fake a panel out of it. Instead, make the tension explicit inside the one
prompt — ask for candidate findings and a verification pass over them, in that order
— and treat its novel-but-unchecked claims as leads, exactly as you would from a
generator seat. This is weaker than two seats, which is what the degradation stamp is
telling the reader.
Demand the artifact, not the summary
[measured] In that run the single largest score gap was not analysis quality but
delivery: one model did roughly 94KB of excellent work, published about 1.2KB of it, and
opened its reply with commentary about its own tooling — leaving a reasonable reader to
conclude it had accomplished nothing. The work existed. It was simply never handed over.
This is the same failure class as rule 7 (incremental findings files), seen from the
other end, and it changes what you ask for:
- Give every reviewer an explicit output path and require the findings to land there.
- Judge a seat by the file it produced, not by the chat message it returned. A thin
reply over a substantial file is a delivery failure, not a weak review — go read the
file.
- Treat process commentary in a reviewer's response as a smell. A seat narrating its
helper scripts is usually a seat that has not yet told you what it found.
Retrieval is the weak link — paste the prior decisions in
[measured] In that run, none of the eight models consulted the existing record of
what had already been tried, and several confidently re-proposed approaches that had
already been evaluated and rejected, with the measured verdicts sitting in an accessible
store the whole time.
Assume a reviewer will not find your prior decisions on its own, even when it has the
tools and the access. A reviewer that re-raises a settled question burns a seat and adds
noise to synthesis. Paste the relevant history — the graveyard of rejected approaches,
the constraints already agreed, the decisions already made and why — directly into the
reviewer prompt as part of the bounded brief. Retrieval you did not verify is retrieval
that did not happen.
Job-to-family quick reference
Measured on one research task, N=1 per model. A starting prior, not a routing table —
and never a substitute for the different-family independence rule above.
| Job |
Start with |
| Synthesize findings into a coherent verdict |
Claude |
| Write the evaluation framework or rubric |
GPT |
| Apply a rubric and verify claims |
Claude or GPT (not the one that wrote it) |
| Generate novel objections and unlisted failures |
Open-weight (Kimi, Qwen, MiniMax,...) |
| Adversarial kill / mandate discipline |
Grok |
| Read a large diff or corpus for coverage |
Gemini |
| Extract evidence with numbers behind it |
Not Gemini — Claude or GPT |
| Anything where the deliverable itself matters |
Any seat — but give an explicit output path and check the file |
When Grok is the right pick
Grok earns a seat (or the lead reviewer slot) when the artifact needs adversarial or
socially-grounded judgment rather than careful synthesis:
- Critical / red-team review — "tear this apart", pre-mortems, threat modeling,
"what's the strongest argument this is wrong?"
- Public reaction and sentiment — how a post, product name, price change, or policy
will land publicly; what critics will seize on. Treat this as platform reaction (X
discourse skews fast, vocal, and manipulable), not a proxy for the general public.
- Current events grounding — claims that depend on what happened recently, where a
stale training cutoff produces confidently wrong review notes.
- Contrarian check on consensus — when the other reviewers agree suspiciously fast
and you want a dissent probe.
Do not default to Grok for final wording, empathetic messaging, or careful policy
synthesis; its variance is a feature for finding problems and a liability for phrasing
them. Pair it with a lower-variance synthesizer from a different configured family, and
verify its claims rather than rubber-stamping them.
Isolate every headless reviewer in its own scratch home (REQUIRED)
hermes -z boots a full agent, and the CLI path opens the calling profile's
state.db read-write (cli.py:4642 → SessionDB(), cli.py:8566 →
create_session(...), resolved by hermes_state.py:2798). Run that from an
agent whose gateway is live and you have two OS processes writing one WAL
database — each with its own lock state and its own view of the WAL index. No
pragma prevents the damage.
This is not hypothetical. On a production host the gateway (fd mode u) and a
hermes -z reviewer (fd mode u) were caught holding one state.db
simultaneously. That 3GB database took structural B-tree damage — invalid page number, 2nd reference to page, rowids out of order — and had to be rebuilt
offline from readable rows.
Give each reviewer its own scratch home. Use the bundled helper
scripts/reviewer_home.sh (the larger panel runner is
templates/parallel_reviewer_runner.sh):
source "$SKILL_DIR/scripts/reviewer_home.sh"
reviewer_pool_init # REQUIRED; never inside $( )
reviewer_run "$CRITICAL_PROMPT" -m grok &
reviewer_run "$EMPATHETIC_PROMPT" -m claude-think &
reviewer_run "$SECURITY_PROMPT" -m gpt-5.6-sol &
wait
reviewer_pool_destroy # or let the EXIT trap do it
HERMES_HOME roots config.yaml, .env, auth.json, skills, memories and
state.db, so a seeded scratch home gives working credentials plus a private
database. Nothing is registered under profiles/, so there is no namespace to
garbage-collect and no name to collide with — the scratch dies with the run.
Reviewers are anonymous. Run 2 or 10; the helper never names or enumerates
personas. The PROMPT decides what each seat is, so a panel can be whatever that
day's artifact needs. Never hardcode a role vocabulary into the tooling.
One home per reviewer, never one shared home. Measured: 6 concurrent
reviewers sharing a single home produced 6 simultaneous holders of one
database — the original bug, relocated. Per-reviewer homes measure a peak of
exactly 1. Integrity surviving one shared run proves nothing.
Measured cost: seeding a home ~1.2 ms / ~26 KB; state.db created on demand
~232 KB; 10 concurrent reviewers finished in 12.1 s using 2.7 MB of scratch,
fully removed. Creating a home is far cheaper than the model call it wraps —
never batch reviewers into one home to "save" it.
Five ways this helper can betray you (all measured, all guarded)
A reviewer panel found each of these in the first version of this helper. If you
write your own, handle all five — every one fails silently.
- Unchecked
mktemp → empty HERMES_HOME → the caller's live database.
Hermes treats an empty HERMES_HOME as unset and falls back to
~/.hermes/state.db. The isolation helper then causes exactly the corruption
it exists to prevent. Validate every scratch path and refuse to run
without one.
- Lazy auto-init inside
$(reviewer_home) self-destructs. Command
substitution runs in a subshell whose EXIT trap fires when the substitution
closes, deleting the pool and handing the reviewer an unseeded home — the
401-with-rc=0 path. $$ cannot detect a subshell (bash keeps the parent's
pid) and BASHPID is empty on bash 3.2 (macOS). Require explicit init.
- A signal handler that does not exit lets the script resume. Bash returns
control to the next statement, so a Ctrl-C'd fan-out destroys the pool and
then seeds a fresh one and keeps spending model calls. Kill live reviewers,
restore the default disposition, re-raise.
- A sourced
trap... EXIT clobbers the caller's own cleanup. Chain it.
- An exported pool variable is inherited by child shells, which skip init,
adopt the parent's pool, and delete it on their own exit while the parent's
reviewers are still running. Do not export it.
Two more that cost real seats: a trap cannot fire while bash blocks in a
foreground child (background each reviewer and wait), and auth.json must be
copied alongside config.yaml/.env or OAuth-based providers fail with
"No … OAuth credentials stored" while API-key providers succeed — a partial
credential failure that reads like a model outage.
Rejected alternatives — do not reach for these:
| Approach |
Why it fails |
bare mktemp -d, unseeded |
No credentials: HTTP 401: Missing Authentication header with exit code 0, so a fan-out silently scores dead reviewers as successful seats. |
a dedicated named profile + -p |
Works, but litters the profile namespace with entries needing sweep-on-crash and forces invented names. Nested names fail rc=2 with empty output. |
| MoA presets |
MoA broadcasts one prompt to N models. A panel needs N different prompts. Different feature. |
delegate_task per-task model |
Upstream has declined it repeatedly (PRs #17718, #23266, #25026, #34773, #36790). It will not arrive — do not design around it. |
Running reviewers as Hermes one-shots
The cleanest way to run an independent reviewer is a headless hermes -z call against a
chosen provider/model. Confirm the local profile actually has the provider before using
it: hermes config get model.providers (or read ~/.hermes/config.yaml).
Keep reviewers on the configured router path — a slow reviewer is not a broken one.
A hermes -z reviewer call pays chat-session startup (config load, memory/Cortex
prefetch, skill scan, system-prompt build) on top of the model's own latency, so a
single reviewer can take a minute or more even when everything is working. That slowness
is not a model failure and is not a reason to drop to a same-model panel or to
"optimize" by POSTing a router/provider endpoint directly. The fix for slowness is a
generous timeout plus parallelism inside the configured Hermes/provider/router path
(including a custom OpenAI-compatible router) — never a bypass. The only exceptions are
the router being genuinely unreachable (for a diagnostic) or the human explicitly
approving a different architecture. For the concrete slow-vs-broken correction that
produced this rule, see references/slow-reviewer-timeouts-router-path.md. Six
execution rules that prevent silent failures:
Mind the artifact size. A hermes -z "$PROMPT" call places the whole prompt on
the process argv, and command substitution like hermes -z "$(cat file)" does the
same — it does not dodge the limit. Normal artifacts (a function, a small diff, a
message) are fine. For large inputs — big PR diffs, full logs, multi-file dumps —
argv can hit ARG_MAX (Argument list too long). When the artifact is large, prefer
chunking into per-file/per-section reviews or gather in the parent and send a
bounded brief. Do not pretend a temp file plus $(cat...) solves this; it doesn't.
Always disable tools with -t ''. A headless reviewer that tries to call a tool
will hang waiting for an approval that never comes. -t '' keeps it a pure text-in /
text-out review. Do not remove it when customizing.
Set the timeout explicitly on every reviewer call. Never inherit the default.
Review models take longer than normal chat, especially with long prompts or
slow/deep models — but an agent terminal tool's default timeout is typically sized
for ordinary shell commands (a few minutes at most) and will cut a healthy reviewer
off long before it finishes. An omitted timeout is not "the value this skill
recommends," it is whatever the environment happens to default to. Pass it on the
tool call every time, scaled to scope:
| Scope |
Timeout |
| Single small artifact, one lens |
300s |
| Normal review, multi-file or multi-lens |
300-600s |
| Deep panel, slow/reasoning models, large brief |
600s |
| Anything you expect to exceed the foreground ceiling |
background + poll, no fg cap |
Foreground tool calls usually have a hard ceiling of their own (commonly around
600s), so a review genuinely bigger than that must run as a background process and
be polled — not squeezed into a foreground call that will be killed. Check your
runtime's actual foreground maximum rather than assuming 600s is available.
If a run still times out, first try to recover the coverage — shrink the artifact,
split the panel, or replace the seat — rather than accepting the loss. Only when
that fails does the degradation rule in the Core Contract apply: synthesize solely
if the completed seats still meet this target's depth floor, and label the gap.
Never silently fall back to a partial review.
Use --ignore-rules deliberately, and re-inject any safety rules you still need.
It stops the calling profile's persona from washing out the review lens — but it also
strips project rules. If the artifact may contain private data (real names, host
paths, ports, secrets, internal context) or you're operating in a repo with a
privacy/PII policy (for example an AGENTS.md zero-PII block), copy those
constraints into the reviewer prompt so the headless reviewer doesn't echo
sensitive data into its output or any follow-up text. Independence of lens, not loss
of safety.
Confirm the provider exists first with hermes config get model.providers (or
read ~/.hermes/config.yaml) before selecting it.
Run a cross-family panel in parallel background processes — but never with shell
&. For a genuine multi-family panel, wall time should be the slowest single
reviewer, not the sum, so run the reviewers concurrently. The Hermes terminal tool
rejects foreground commands containing & backgrounding ("Use
terminal(background=true)...") and also rejects workdir strings containing shell
metacharacters, so a one-shot cmd & cmd & wait panel will be blocked. The working
parallel pattern is: launch each reviewer with
terminal(background=true, notify_on_complete=true) writing to a distinct
/tmp/out_<lens>.txt, then read the files after all complete. Default for a
cross-family (2+ model) panel: parallel background — the whole point of a panel is
diversity, and parallelism is what makes waiting for slow-but-healthy reviewers
affordable. Fall back to sequential foreground hermes -z calls only for a
single-reviewer check or when background orchestration isn't available. Do not
stamp degraded: single-model just because a reviewer is slow — only after a
genuine failure or a blown timeout for the configured depth (300s for normal, 600s
for deep). Early-degrade on slowness is the classic bug this rule exists to prevent.
Confirmed in practice; parallel default reaffirmed after a later recurrence.
Have every reviewer write findings to a file as it goes, not only at the end.
A reviewer that is killed — by a timeout, a wedged tool call, a crashed child, a
dropped connection — takes everything it found with it if its only output channel is
the final return value. This is a real and expensive failure: a review can identify
a genuine bug and then die before reporting it, leaving no trace that the bug was
ever seen. Give each seat its own output file and have it append findings
incrementally, highest-severity first, so a partial file is still useful evidence.
Then, when a seat fails, read its partial file before declaring the seat lost.
Findings recovered this way are real findings — carry them into synthesis, attributed
to a seat marked incomplete, and let the depth floor decide whether the panel still
stands. Never discard a dead reviewer's output unread.
This applies to every execution path, but it matters most where you do not control
the deadline (path 1): a file on disk is the only thing that survives a child the
runtime decides to kill.
Never trust a reviewer's self-report about its own tool failures — stat the file.
When a reviewer says it could not read a seat's output, that its input was empty, or
that a file was 0 bytes, verify the claim against the filesystem before acting on it.
Self-reported tool failures are biased: they fail in the direction that flatters the
reporter, because "the input was missing" excuses an omission that "I did not read
it" would not. This is not theoretical — in a real panel, a synthesizing model
reported a peer's critique as "a 0-byte file" when the file on disk was over 7KB,
and the dropped objection was the one that would have caught a regulatory risk on
its own top-ranked recommendation. Check size and mtime yourself. A synthesis built
on an unverified claim of missing input is not a synthesis, and the seat it silently
dropped was usually the disagreeing one.
# Provider/model names are PLACEHOLDERS — resolve them from the local config.
# Suitable for normal-sized artifacts; for large inputs, chunk or send a bounded brief.
# When running these through an agent terminal tool, ALWAYS pass the timeout explicitly
# (see execution rule 3): ~300s normal, ~600s deep/slow panels, background+poll beyond
# the foreground ceiling. An omitted timeout inherits the environment default, which is
# usually sized for ordinary shell commands and will kill a healthy reviewer early.
hermes -z "$PROMPT_GROK" --provider <grok-provider> -m <current-grok-model> --ignore-rules -t ''
hermes -z "$PROMPT_GEMINI" --provider <gemini-provider> -m <current-gemini-model> --ignore-rules -t ''
hermes -z "$PROMPT_GPT" --provider <gpt-provider> -m <current-gpt-model> --ignore-rules -t ''
Do not copy a version number out of this document. Resolve each family's current
flagship from the local config or provider listing — hard-coded slugs go stale and
silently 404.
If the profile exposes a router combo/alias for a family, prefer the combo name over
a raw slug. A subscription-backed combo (for example an OAuth seat with a pay-per-token
fallback) prefers subscription quota, but can still fall back to metered usage — so
verify routing and cost policy rather than assuming a review is free.
If the profile routes everything through a custom multi-provider router, the providers
will instead be custom aliases (for example custom:grok, custom:gemini,
custom:openrouter) with router-qualified model IDs. Inspect the config and use
whatever families are actually wired up — the skill cares about family diversity, not
the exact alias.
Lens Selection by Scenario
Code or Pull Request
Default panel:
- Correctness / logic
- Security / data exposure
- Tests / regressions
- Error handling / reliability
- Architecture / maintainability for deep reviews
- Performance only when the code path is hot or data volume matters
Good model mix: GPT for structured code triage, Gemini for large diff/context reading,
Grok for adversarial/security assumptions, Claude for synthesis.
Skill, Prompt, or Agent Behavior
Default panel:
- Trigger clarity: will future agents load it at the right time?
- Operational truth: are commands, paths, flags, and tool semantics real?
- Procedure quality: does it tell the agent what to do next, not just describe a
concept?
- Safety/boundary handling: approvals, secrets, public/private data, irreversible
actions
- Failure modes: what happens when a tool is unavailable, output is huge, or the model
is wrong?
- Retrieval/readability: concise enough to load, structured enough to follow
Good model mix: Gemini for long-context/coverage, GPT for structure and command
specificity, Grok for adversarial prompt misuse, Claude for final synthesis and voice.
Outbound Communication
Default panel:
- Empathy / recipient experience
- Intent fidelity: does it say what the operator meant?
- Evidence: are claims true and appropriately qualified?
- Data exposure: does it leak internal, private, or wrong-person information?
- Voice and audience fit
Good model mix: Claude for tone and empathy, GPT for concise edits, Gemini for evidence
checking, Grok for blunt risk on sensitive messages.
Plan, Strategy, or Decision
Default panel:
- Assumptions and missing information
- Dependency/order-of-operations risk
- Blast radius and reversibility
- Concrete next actions and ownership
- Contrarian review: what would make this fail?
Good model mix: Grok for contrarian pressure, Gemini for context coverage, GPT for
structured plan critique, Claude for decision synthesis.
Tool Action, Config Change, Migration, or Rollout
Default panel:
- Target correctness: right host/profile/file/channel/account?
- Blast radius and rollback path
- Approval gate: does this need human go-ahead?
- Verification: how will we know it worked?
- Data exposure /
…(truncated)
1---2name: multi-review3description: Use when reviewing almost any meaningful artifact, decision, action, plan, code change, prompt, skill, research summary, outbound message, or public-facing content. Runs a small panel of diverse review lenses across model families when available, synthesizes findings into fix/ask/defer/wontfix decisions, and iterates until the result is ready.4license: MIT5---67# Multi-Review89## Overview1011Multi-review is a generic review pattern: look at an artifact through several12independent lenses, preferably using more than one model family, then synthesize the13findings into concrete next actions.1415This is **not only** an outbound-communication gate. Outbound comms are one important16case, but the same pattern works for code, skills, plans, prompts, migrations, research,17public posts, tool actions, config changes, incident reports, and decisions with real18blast radius.1920The point is diversity without chaos:2122- **Different lenses** catch different failure modes.23- **Different model families** catch different blind spots.24- **A synthesis pass** deduplicates, rejects false positives, and turns feedback into25 action.26- **A meta-review pass** checks whether the review itself was useful or noisy before the27 caller declares the artifact ready.2829## When to Use3031Use this skill when the user says:3233- "review this", "sanity check this", "second pair of eyes", "is this ready?"34- "check this before I send/post/ship/merge/run it"35- "run a multi-review", "get Grok/Gemini/GPT on this", "use multiple reviewers"36- "look over this plan", "review this PR", "review this skill/prompt"37- "is this safe?", "what am I missing?", "red-team this"3839Also use it proactively before high-stakes actions:4041- Code or config changes that will be committed, deployed, or rolled across machines42- Public or customer-visible writing43- Messages sent as a human/operator44- Data migrations, deletes, permission changes, or credential-handling changes45- Skill, prompt, or agent-behavior changes that future agents will follow46- Research summaries where citations, uncertainty, or omitted evidence matter4748Do **not** use for:4950- Trivial private-chat responses51- Purely read-only information gathering52- Cases where the user explicitly says not to review or says "no further action"53- Emergency containment where pausing for review would increase harm; contain first,54 review the follow-up5556## Core Contract5758A good multi-review run does these things, in order:59601. **Define the target.** Identify the artifact or action being reviewed, the intended61 audience, and the stakes.622. **Choose review depth.** Pick quick, balanced, or deep based on risk.633. **Choose a diverse panel.** Select lenses and model families appropriate to the task.64 Whenever the run has **two or more seats**, staff for both generation and65 verification — those are usually different seats, not one strong seat (see66 "Verification and originality are usually different seats"). A single-seat run67 cannot split the roles; it carries the generator/verifier tension inside one prompt68 and is stamped degraded accordingly.694. **Run reviewers independently.** Keep reviewer prompts isolated so they do not anchor70 on each other's conclusions.715. **Synthesize.** Deduplicate findings, classify each as fix / ask / defer / wontfix,72 and decide whether the artifact is ready.736. **Act.** Apply obvious low-risk fixes when authorized; ask once for judgment calls;74 defer only when scope genuinely exceeds the task.757. **Meta-review.** Check whether the review was useful, whether the panel missed an76 obvious lens, and whether false positives were handled correctly.778. **Iterate until ready.** Re-run targeted reviewers after material fixes, especially78 for high-stakes or public-facing artifacts.7980Never claim "multi-model review" unless multiple model families actually ran. If model81routing is unavailable, say `degraded: single-model` and explain what still ran.8283**Count a reviewer only when it returned substantive review output.** A seat that merely84started, printed setup or shell noise, hung, or was killed is a _failed_ seat, not an85independent lens. A same-family external reviewer does not by itself clear a86`single-model-family` degradation. Report completed seats and distinct model-family87coverage separately — they are different numbers and conflating them overstates the88review.8990**Do not stall silently.** Give each reviewer a deadline. Once the expected window91passes, poll for partial output rather than waiting indefinitely. If a seat times out or92returns empty, replace it when the selected depth still requires that coverage;93otherwise synthesize only if the completed seats still meet the depth floor for this94target. A degraded panel that drops below its floor is not a finished review — say so95instead of shipping it. Report which seats completed, which failed, and which families96are missing, and lower confidence to match what actually survived.9798### Execution hierarchy99100Use the strongest practical isolation mechanism available, but match it to the task's101shape:1021031. **Headless Hermes one-shots in isolated scratch homes**104 (`hermes -z... -t ''`, each with its own `HERMES_HOME`) — the default. This105 is the only path that delivers a **different prompt AND a different model per106 seat** ("Grok, be critical"; "Claude, be empathetic"), and **the only path107 where you can size the timeout to the job.** Isolation is mandatory, not108 optional — see "Isolate every headless reviewer" below. Use a higher timeout109 than the default for real reviews; 300-600 seconds is usually reasonable, and110 deep/slow model panels may need the upper end. See execution rule 3 — the111 default is very likely lower than you want.1122. **Native subagents** when every seat can run on the _same_ model and you only113 need lens diversity: prompts, context, and failures are naturally isolated.114 **Two tradeoffs before choosing this path.** First, the delegation tool has115 **no per-task model parameter**, and upstream has repeatedly declined to add116 one (PRs #17718, #23266, #25026, #34773, #36790; maintainer on #34773: _"We do117 not want this"_). Every child in a batch runs on the single configured118 delegation model, so this path cannot staff a multi-model panel — do not plan119 one around it. Second, a subagent's runtime almost certainly gives you no120 per-call timeout control: the schema exposes goal, context, role, and output121 schema — not a deadline. Any wall-clock cap is process-wide configuration read122 at call time, so a skill cannot scale it to the artifact. If this review needs123 a deadline proportional to its scope, use path 1 or 3.1243. **Parent-gathered I/O + reviewer one-shots** for open-ended or I/O-heavy review work125 (large filesystem searches, email/search crawls, binary downloads, multi-step data126 collection). Do the I/O in the parent with normal tools, reduce it to a bounded127 brief, then send that brief to reviewers. Do **not** hand an open-ended crawl to a128 subagent whose deadline you do not control: if a wall-clock cap is configured, the129 child is killed mid-task and its findings die with it, and if none is configured a130 wedged child stalls the panel instead. Either way the review fails before synthesis.1314. **Same-model subagents with different lenses** when only one model family is132 available. Increase lens diversity, include at least one contrarian reviewer and one133 meta-review, and stamp `degraded: model-diversity unavailable`.1345. **Manual single-pass review** only for quick/low-stakes work that is **below every135 minimum depth floor** (see below). Never use this mode for money/auth/secrets/user-136 data/irreversible/public/rollout targets, even if they look small. Stamp137 `degraded: single-reviewer` and do not present it as a panel.138139**Privacy applies to every path.** The re-injection rule in execution rule 3 below is140not specific to `--ignore-rules`: any isolated reviewer — native subagent, headless141one-shot, or same-model subagent — runs without the calling context's project rules. If142the artifact may contain private data, or you are in a repo with a privacy/PII policy,143copy those constraints into **every** reviewer prompt regardless of execution path.144145## Depth Scaling146147**Quick** — 1-2 reviewers. Use for low-stakes drafts, small edits, or a simple sanity148check.149150**Balanced** — 3 reviewers. Default for meaningful work. Cover the primary domain,151truth/correctness, and user/audience impact.152153**Deep** — 5+ reviewers plus meta-review. Use for security-sensitive changes, public154posts, fleet/config rollouts, irreversible actions, architecture, migrations, or changes155that future agents will rely on.156157If unsure, use balanced. Escalate to deep when any reviewer finds a high-severity issue158or when the artifact will be hard to undo after release.159160### Minimum depth floors161162Certain targets should never get only a quick pass:163164- **Code that handles money, auth, permissions, secrets, user data, networking, or data165 migration** → balanced minimum; deep if public or production-bound.166- **Irreversible tool actions, deletes, permission changes, or fleet/config rollouts** →167 deep minimum plus explicit approval/rollback review.168- **Public-facing policy, docs, prompts, or skills that future agents will follow** →169 balanced minimum; deep if the instructions affect safety boundaries.170- **Messages sent as a human/operator, legal/medical/financial statements, or sensitive171 interpersonal comms** → balanced minimum with empathy, evidence, and data-exposure172 lenses.173174## Model Family Selection175176Prefer a reviewer from a **different model family** than the calling agent. Independence177matters more than raw benchmark rank.178179Use the models configured in the local Hermes profile. Do not hard-code API keys. If the180profile has aliases such as `custom:grok`, `custom:gemini`, or `custom:openrouter`, use181those; otherwise inspect the local config and choose equivalent provider/model pairs.182183Pair each alias with the provider block the local config actually wires it to, and do184not "normalize" a reviewer onto a different provider for tidiness. When one router is185exposed through several provider blocks, they usually differ by API shape186(`chat_completions` vs `anthropic_messages`), and the better block depends on the187upstream model family: Claude models are natively Anthropic-shaped, most others (OpenAI,188xAI, Google) are natively OpenAI-shaped. The wrong block still returns HTTP 200, so this189fails silently rather than loudly. If an existing config contradicts that, assume it is190deliberate until you have checked why.191192### Family strengths193194The notes below combine general observation with one **measured** data point: a195multi-model bake-off where eight models were given the same open-ended research and196ideation brief, and their outputs were scored across seven weighted dimensions197(mandate discipline, evidence quality, originality, verification, usability, and198related axes). Findings from that run are marked **[measured]**. Everything else is199ordinary heuristic.200201Read the scope honestly: that was **one task, scored once, N=1 per model**, and the202task was _research and ideation_, not _critique of an existing artifact_. Behaviors203that are themselves review-shaped — adversarial pressure-testing, mandate discipline,204verification effort — transfer to reviewing with reasonable confidence. Generative205traits like originality are a **hypothesis** about review behavior, not an established206one. Treat the whole section as a prior to check against the artifact in front of you,207not as fixed model properties.208209- **Claude / Anthropic** — best for synthesis, nuanced tradeoffs, voice, empathy, policy210 interpretation, and turning messy findings into a coherent final answer. **[measured]**211 Also the strongest self-critic in the run: it pressure-tested its own output212 adversarially, which is review behavior directly. **Its limit is divergence** — it213 scored lowest of the frontier models on originality, and every idea it produced also214 appeared on another model's list. It is a convergence engine, not a divergence engine.215 A panel staffed only with Claude models will produce a well-written consensus and miss216 the objection nobody else thought of. Avoid using only Claude if the calling agent is217 already Claude-family.218- **GPT / OpenAI** — strong structured reviewer: code correctness, API contracts, tests,219 consistency, and concise fix recommendations. **[measured] Best at building the220 evaluation scaffold, weakest at then executing it.** It produced the best decision221 framework in the corpus — a crisp set of screening questions others should have been222 measured against — and then over-filtered its own candidates and delivered almost no223 verification behind them. Give GPT the job of defining the review criteria, or the job224 of applying them, but do not assume one seat does both well.225- **Gemini / Google** — strong long-context reader: large diffs, logs, docs, and226 cross-file consistency checks. **[measured] Do not rely on it for evidence227 extraction**, despite the long-context strength: its evidence was correct but generic228 and thin, list-shaped with no numbers behind the claims. **Operational warning:** in229 that run a Gemini seat silently fell back to a different underlying model mid-thread230 and kept answering as if nothing had changed. A reviewer that swaps model families231 without telling you breaks the independence guarantee the entire panel rests on.232 Verify which model actually answered before counting it as family coverage.233- **Grok / xAI** — strong contrarian/red-team reviewer: assumptions, edge cases, blunt234 risk, adversarial misuse, policy gaps, and "what would embarrass us if true?" checks.235 **[measured] The best mandate discipline in the run** — it was the one model willing to236 answer the question actually asked rather than the more flattering adjacent question,237 and it rejected the framing it had been handed when the framing was wrong. That is238 precisely what a red-team seat is for. **[measured] Its failure mode is delivery:** it239 scored worst in the run on usability, producing genuinely excellent analysis and then240 leaving nearly all of it in scratch files while its actual reply led with process241 commentary. Grok needs an explicit output path and a demand for the artifact more than242 any other family (see rule 7). High variance is useful for surfacing issues, not for243 final wording.244245 Grok is also the family most likely to offer **native live X-graph retrieval** (via246 xAI's `x_search` server-side tool) rather than general web search, which helps when the247 question is "how are people reacting right now?" — public-facing copy, launch posts,248 naming, positioning, and reputational blast radius. Live retrieval applies only when249 the selected route actually enables that tool; otherwise treat Grok as cutoff-bound250 like any other model.251252- **Open-weight models** (Kimi, Qwen, MiniMax, DeepSeek, Llama, and similar) — **the253 divergence seats.** **[measured]** In that run the open-weight models produced the254 genuinely novel material: the mechanisms and framings that appeared on no frontier255 model's list. If a panel needs an idea the consensus will not generate — an unlisted256 failure mode, an approach nobody considered, a structurally different objection — this257 is where it comes from, and it is a real reason to seat one even when a frontier model258 is available. **[measured] They pair novelty with almost no verification:** the same259 seats that generated the new material asserted it without checking, and one of them260 also scored near the bottom on usability. Their output is a lead to be verified, never261 a finding to be trusted as-is. Cost and privacy (local or self-hosted execution) are262 secondary reasons to use them; capability diversity is the primary one.263- **Small or local models** — useful for cheap/private quick passes, syntax/style checks,264 and obvious inconsistencies. Do not rely on them alone for high-stakes judgment. This265 is a size/deployment distinction, not the open-weight distinction above: a large266 open-weight model run through a hosted router is a full-strength seat.267268**Newer is not automatically stronger.** A vendor's latest flagship, including one269marketed as a reasoning improvement over the previous flagship, may not outperform the270model it supersedes on your actual work. Two Anthropic frontier models in that run271finished close together despite one being positioned as the clear successor. Check the272newer model on a task you have already scored before promoting it to a panel seat by273reputation.274275These family strengths are **observed heuristics, not guarantees** — they shift with276model versions and prompting. Verify against the artifact in front of you rather than277treating them as fixed properties.278279### Verification and originality are usually different seats280281The single most useful structural finding from that run: **the models that verified282heavily generated almost nothing new, and the models that generated the novel material283verified almost none of it.** The correlation ran in opposite directions across the284whole field, frontier and open-weight alike.285286Do not fight this by asking one seat to do both. Whenever the run has two or more287seats, staff for it:288289- Seat at least one **generator** (open-weight models are the measured pick) whose job290 is to produce candidate findings, including speculative ones.291- Seat at least one **verifier** (frontier models, Claude and GPT in that run) whose job292 is to check the generator's claims against the artifact and kill the unsupported ones.293- Let the verifiers grade the generators. An unverified novel finding is a lead, not a294 result, and it should be labeled that way in synthesis until someone checks it.295296A panel of only verifiers returns a tidy consensus that misses the unlisted problem. A297panel of only generators returns a pile of confident claims you cannot act on. The298review is the interaction between them.299300**Single-seat runs are the documented exception.** A quick-depth check or the301`degraded: single-reviewer` fallback has one seat and cannot split these roles. Do not302try to fake a panel out of it. Instead, make the tension explicit inside the one303prompt — ask for candidate findings _and_ a verification pass over them, in that order304— and treat its novel-but-unchecked claims as leads, exactly as you would from a305generator seat. This is weaker than two seats, which is what the degradation stamp is306telling the reader.307308### Demand the artifact, not the summary309310**[measured]** In that run the single largest score gap was not analysis quality but311delivery: one model did roughly 94KB of excellent work, published about 1.2KB of it, and312opened its reply with commentary about its own tooling — leaving a reasonable reader to313conclude it had accomplished nothing. The work existed. It was simply never handed over.314315This is the same failure class as rule 7 (incremental findings files), seen from the316other end, and it changes what you ask for:317318- Give every reviewer an explicit output path and require the findings to land there.319- Judge a seat by the file it produced, not by the chat message it returned. A thin320 reply over a substantial file is a delivery failure, not a weak review — go read the321 file.322- Treat process commentary in a reviewer's response as a smell. A seat narrating its323 helper scripts is usually a seat that has not yet told you what it found.324325### Retrieval is the weak link — paste the prior decisions in326327**[measured]** In that run, none of the eight models consulted the existing record of328what had already been tried, and several confidently re-proposed approaches that had329already been evaluated and rejected, with the measured verdicts sitting in an accessible330store the whole time.331332Assume a reviewer will not find your prior decisions on its own, even when it has the333tools and the access. A reviewer that re-raises a settled question burns a seat and adds334noise to synthesis. Paste the relevant history — the graveyard of rejected approaches,335the constraints already agreed, the decisions already made and why — directly into the336reviewer prompt as part of the bounded brief. Retrieval you did not verify is retrieval337that did not happen.338339### Job-to-family quick reference340341Measured on one research task, N=1 per model. A starting prior, not a routing table —342and never a substitute for the different-family independence rule above.343344| Job | Start with |345| ----------------------------------------------- | -------------------------------------------------------------- |346| Synthesize findings into a coherent verdict | Claude |347| Write the evaluation framework or rubric | GPT |348| Apply a rubric and verify claims | Claude or GPT (not the one that wrote it) |349| Generate novel objections and unlisted failures | Open-weight (Kimi, Qwen, MiniMax,...) |350| Adversarial kill / mandate discipline | Grok |351| Read a large diff or corpus for coverage | Gemini |352| Extract evidence with numbers behind it | Not Gemini — Claude or GPT |353| Anything where the deliverable itself matters | Any seat — but give an explicit output path and check the file |354355### When Grok is the right pick356357Grok earns a seat (or the lead reviewer slot) when the artifact needs adversarial or358socially-grounded judgment rather than careful synthesis:359360- **Critical / red-team review** — "tear this apart", pre-mortems, threat modeling,361 "what's the strongest argument this is wrong?"362- **Public reaction and sentiment** — how a post, product name, price change, or policy363 will land publicly; what critics will seize on. Treat this as _platform_ reaction (X364 discourse skews fast, vocal, and manipulable), not a proxy for the general public.365- **Current events grounding** — claims that depend on what happened recently, where a366 stale training cutoff produces confidently wrong review notes.367- **Contrarian check on consensus** — when the other reviewers agree suspiciously fast368 and you want a dissent probe.369370Do **not** default to Grok for final wording, empathetic messaging, or careful policy371synthesis; its variance is a feature for finding problems and a liability for phrasing372them. Pair it with a lower-variance synthesizer from a different configured family, and373verify its claims rather than rubber-stamping them.374375### Isolate every headless reviewer in its own scratch home (REQUIRED)376377`hermes -z` boots a full agent, and the CLI path opens the **calling profile's**378`state.db` read-write (`cli.py:4642` → `SessionDB()`, `cli.py:8566` →379`create_session(...)`, resolved by `hermes_state.py:2798`). Run that from an380agent whose gateway is live and you have **two OS processes writing one WAL381database** — each with its own lock state and its own view of the WAL index. No382pragma prevents the damage.383384This is not hypothetical. On a production host the gateway (fd mode `u`) and a385`hermes -z` reviewer (fd mode `u`) were caught holding one `state.db`386simultaneously. That 3GB database took structural B-tree damage — `invalid page387number`, `2nd reference to page`, rowids out of order — and had to be rebuilt388offline from readable rows.389390**Give each reviewer its own scratch home.** Use the bundled helper391`scripts/reviewer_home.sh` (the larger panel runner is392`templates/parallel_reviewer_runner.sh`):393394```bash395source "$SKILL_DIR/scripts/reviewer_home.sh"396reviewer_pool_init # REQUIRED; never inside $( )397398reviewer_run "$CRITICAL_PROMPT" -m grok &399reviewer_run "$EMPATHETIC_PROMPT" -m claude-think &400reviewer_run "$SECURITY_PROMPT" -m gpt-5.6-sol &401wait402reviewer_pool_destroy # or let the EXIT trap do it403```404405`HERMES_HOME` roots config.yaml, `.env`, `auth.json`, skills, memories **and**406state.db, so a seeded scratch home gives working credentials plus a private407database. Nothing is registered under `profiles/`, so there is no namespace to408garbage-collect and no name to collide with — the scratch dies with the run.409410**Reviewers are anonymous.** Run 2 or 10; the helper never names or enumerates411personas. The PROMPT decides what each seat is, so a panel can be whatever that412day's artifact needs. Never hardcode a role vocabulary into the tooling.413414**One home per reviewer, never one shared home.** Measured: 6 concurrent415reviewers sharing a single home produced **6 simultaneous holders of one416database** — the original bug, relocated. Per-reviewer homes measure a peak of417exactly **1**. Integrity surviving one shared run proves nothing.418419**Measured cost:** seeding a home ~1.2 ms / ~26 KB; state.db created on demand420~232 KB; 10 concurrent reviewers finished in 12.1 s using 2.7 MB of scratch,421fully removed. Creating a home is far cheaper than the model call it wraps —422never batch reviewers into one home to "save" it.423424#### Five ways this helper can betray you (all measured, all guarded)425426A reviewer panel found each of these in the first version of this helper. If you427write your own, handle all five — every one fails _silently_.4284291. **Unchecked `mktemp` → empty `HERMES_HOME` → the caller's live database.**430 Hermes treats an empty `HERMES_HOME` as unset and falls back to431 `~/.hermes/state.db`. The isolation helper then causes exactly the corruption432 it exists to prevent. Validate every scratch path and **refuse to run**433 without one.4342. **Lazy auto-init inside `$(reviewer_home)` self-destructs.** Command435 substitution runs in a subshell whose EXIT trap fires when the substitution436 closes, deleting the pool and handing the reviewer an _unseeded_ home — the437 401-with-rc=0 path. `$$` cannot detect a subshell (bash keeps the parent's438 pid) and `BASHPID` is empty on bash 3.2 (macOS). Require explicit init.4393. **A signal handler that does not exit lets the script resume.** Bash returns440 control to the next statement, so a Ctrl-C'd fan-out destroys the pool and441 then seeds a fresh one and keeps spending model calls. Kill live reviewers,442 restore the default disposition, re-raise.4434. **A sourced `trap... EXIT` clobbers the caller's own cleanup.** Chain it.4445. **An exported pool variable is inherited by child shells,** which skip init,445 adopt the parent's pool, and delete it on their own exit while the parent's446 reviewers are still running. Do not export it.447448Two more that cost real seats: a trap **cannot fire while bash blocks in a449foreground child** (background each reviewer and `wait`), and `auth.json` must be450copied alongside `config.yaml`/`.env` or OAuth-based providers fail with451"No … OAuth credentials stored" while API-key providers succeed — a partial452credential failure that reads like a model outage.453454**Rejected alternatives — do not reach for these:**455456| Approach | Why it fails |457| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |458| bare `mktemp -d`, unseeded | No credentials: `HTTP 401: Missing Authentication header` **with exit code 0**, so a fan-out silently scores dead reviewers as successful seats. |459| a dedicated named profile + `-p` | Works, but litters the profile namespace with entries needing sweep-on-crash and forces invented names. Nested names fail `rc=2` with empty output. |460| MoA presets | MoA broadcasts **one** prompt to N models. A panel needs N **different** prompts. Different feature. |461| `delegate_task` per-task model | Upstream has declined it repeatedly (PRs #17718, #23266, #25026, #34773, #36790). It will not arrive — do not design around it. |462463### Running reviewers as Hermes one-shots464465The cleanest way to run an independent reviewer is a headless `hermes -z` call against a466chosen provider/model. Confirm the local profile actually has the provider before using467it: `hermes config get model.providers` (or read `~/.hermes/config.yaml`).468469**Keep reviewers on the configured router path — a slow reviewer is not a broken one.**470A `hermes -z` reviewer call pays chat-session startup (config load, memory/Cortex471prefetch, skill scan, system-prompt build) on top of the model's own latency, so a472single reviewer can take a minute or more even when everything is working. That slowness473is **not** a model failure and is **not** a reason to drop to a same-model panel or to474"optimize" by POSTing a router/provider endpoint directly. The fix for slowness is a475generous timeout plus parallelism _inside_ the configured Hermes/provider/router path476(including a custom OpenAI-compatible router) — never a bypass. The only exceptions are477the router being genuinely unreachable (for a diagnostic) or the human explicitly478approving a different architecture. For the concrete slow-vs-broken correction that479produced this rule, see `references/slow-reviewer-timeouts-router-path.md`. **Six480execution rules that prevent silent failures:**4814821. **Mind the artifact size.** A `hermes -z "$PROMPT"` call places the whole prompt on483 the process argv, and command substitution like `hermes -z "$(cat file)"` does the484 same — it does **not** dodge the limit. Normal artifacts (a function, a small diff, a485 message) are fine. For large inputs — big PR diffs, full logs, multi-file dumps —486 argv can hit `ARG_MAX` (`Argument list too long`). When the artifact is large, prefer487 **chunking** into per-file/per-section reviews or gather in the parent and send a488 bounded brief. Do not pretend a temp file plus `$(cat...)` solves this; it doesn't.4892. **Always disable tools with `-t ''`.** A headless reviewer that tries to call a tool490 will hang waiting for an approval that never comes. `-t ''` keeps it a pure text-in /491 text-out review. Do not remove it when customizing.4923. **Set the timeout explicitly on every reviewer call. Never inherit the default.**493 Review models take longer than normal chat, especially with long prompts or494 slow/deep models — but an agent terminal tool's default timeout is typically sized495 for ordinary shell commands (a few minutes at most) and will cut a healthy reviewer496 off long before it finishes. **An omitted timeout is not "the value this skill497 recommends," it is whatever the environment happens to default to.** Pass it on the498 tool call every time, scaled to scope:499500 | Scope | Timeout |501 | ---------------------------------------------------- | ---------------------------- |502 | Single small artifact, one lens | 300s |503 | Normal review, multi-file or multi-lens | 300-600s |504 | Deep panel, slow/reasoning models, large brief | 600s |505 | Anything you expect to exceed the foreground ceiling | background + poll, no fg cap |506507 Foreground tool calls usually have a hard ceiling of their own (commonly around508 600s), so a review genuinely bigger than that must run as a background process and509 be polled — not squeezed into a foreground call that will be killed. Check your510 runtime's actual foreground maximum rather than assuming 600s is available.511512 If a run still times out, first try to recover the coverage — shrink the artifact,513 split the panel, or replace the seat — rather than accepting the loss. Only when514 that fails does the degradation rule in the Core Contract apply: synthesize solely515 if the completed seats still meet this target's depth floor, and label the gap.516 Never silently fall back to a partial review.5175184. **Use `--ignore-rules` deliberately, and re-inject any safety rules you still need.**519 It stops the calling profile's persona from washing out the review lens — but it also520 strips project rules. If the artifact may contain private data (real names, host521 paths, ports, secrets, internal context) or you're operating in a repo with a522 privacy/PII policy (for example an `AGENTS.md` zero-PII block), **copy those523 constraints into the reviewer prompt** so the headless reviewer doesn't echo524 sensitive data into its output or any follow-up text. Independence of lens, not loss525 of safety.5265. **Confirm the provider exists first** with `hermes config get model.providers` (or527 read `~/.hermes/config.yaml`) before selecting it.5285296. **Run a cross-family panel in parallel background processes — but never with shell530 `&`.** For a genuine multi-family panel, wall time should be the _slowest single531 reviewer_, not the sum, so run the reviewers concurrently. The Hermes terminal tool532 **rejects** foreground commands containing `&` backgrounding ("Use533 terminal(background=true)...") and also rejects `workdir` strings containing shell534 metacharacters, so a one-shot `cmd & cmd & wait` panel will be blocked. The working535 parallel pattern is: launch each reviewer with536 `terminal(background=true, notify_on_complete=true)` writing to a distinct537 `/tmp/out_<lens>.txt`, then read the files after all complete. **Default for a538 cross-family (2+ model) panel: parallel background** — the whole point of a panel is539 diversity, and parallelism is what makes waiting for slow-but-healthy reviewers540 affordable. Fall back to sequential foreground `hermes -z` calls only for a541 single-reviewer check or when background orchestration isn't available. **Do not542 stamp `degraded: single-model` just because a reviewer is slow** — only after a543 genuine failure or a blown timeout for the configured depth (300s for normal, 600s544 for deep). Early-degrade on slowness is the classic bug this rule exists to prevent.545 Confirmed in practice; parallel default reaffirmed after a later recurrence.5465477. **Have every reviewer write findings to a file as it goes, not only at the end.**548 A reviewer that is killed — by a timeout, a wedged tool call, a crashed child, a549 dropped connection — takes everything it found with it if its only output channel is550 the final return value. This is a real and expensive failure: a review can identify551 a genuine bug and then die before reporting it, leaving no trace that the bug was552 ever seen. Give each seat its own output file and have it append findings553 incrementally, highest-severity first, so a partial file is still useful evidence.554 Then, when a seat fails, **read its partial file before declaring the seat lost.**555 Findings recovered this way are real findings — carry them into synthesis, attributed556 to a seat marked incomplete, and let the depth floor decide whether the panel still557 stands. Never discard a dead reviewer's output unread.558559 This applies to every execution path, but it matters most where you do not control560 the deadline (path 1): a file on disk is the only thing that survives a child the561 runtime decides to kill.5625638. **Never trust a reviewer's self-report about its own tool failures — stat the file.**564 When a reviewer says it could not read a seat's output, that its input was empty, or565 that a file was 0 bytes, verify the claim against the filesystem before acting on it.566 Self-reported tool failures are biased: they fail in the direction that flatters the567 reporter, because "the input was missing" excuses an omission that "I did not read568 it" would not. This is not theoretical — in a real panel, a synthesizing model569 reported a peer's critique as "a 0-byte file" when the file on disk was over 7KB,570 and the dropped objection was the one that would have caught a regulatory risk on571 its own top-ranked recommendation. Check size and mtime yourself. A synthesis built572 on an unverified claim of missing input is not a synthesis, and the seat it silently573 dropped was usually the disagreeing one.574575```bash576# Provider/model names are PLACEHOLDERS — resolve them from the local config.577# Suitable for normal-sized artifacts; for large inputs, chunk or send a bounded brief.578# When running these through an agent terminal tool, ALWAYS pass the timeout explicitly579# (see execution rule 3): ~300s normal, ~600s deep/slow panels, background+poll beyond580# the foreground ceiling. An omitted timeout inherits the environment default, which is581# usually sized for ordinary shell commands and will kill a healthy reviewer early.582hermes -z "$PROMPT_GROK" --provider <grok-provider> -m <current-grok-model> --ignore-rules -t ''583hermes -z "$PROMPT_GEMINI" --provider <gemini-provider> -m <current-gemini-model> --ignore-rules -t ''584hermes -z "$PROMPT_GPT" --provider <gpt-provider> -m <current-gpt-model> --ignore-rules -t ''585```586587Do not copy a version number out of this document. Resolve each family's **current**588flagship from the local config or provider listing — hard-coded slugs go stale and589silently 404.590591If the profile exposes a router combo/alias for a family, prefer the **combo name** over592a raw slug. A subscription-backed combo (for example an OAuth seat with a pay-per-token593fallback) prefers subscription quota, but **can still fall back to metered usage** — so594verify routing and cost policy rather than assuming a review is free.595596If the profile routes everything through a custom multi-provider router, the providers597will instead be custom aliases (for example `custom:grok`, `custom:gemini`,598`custom:openrouter`) with router-qualified model IDs. Inspect the config and use599whatever families are actually wired up — the skill cares about _family diversity_, not600the exact alias.601602## Lens Selection by Scenario603604### Code or Pull Request605606Default panel:607608- Correctness / logic609- Security / data exposure610- Tests / regressions611- Error handling / reliability612- Architecture / maintainability for deep reviews613- Performance only when the code path is hot or data volume matters614615Good model mix: GPT for structured code triage, Gemini for large diff/context reading,616Grok for adversarial/security assumptions, Claude for synthesis.617618### Skill, Prompt, or Agent Behavior619620Default panel:621622- Trigger clarity: will future agents load it at the right time?623- Operational truth: are commands, paths, flags, and tool semantics real?624- Procedure quality: does it tell the agent what to do next, not just describe a625 concept?626- Safety/boundary handling: approvals, secrets, public/private data, irreversible627 actions628- Failure modes: what happens when a tool is unavailable, output is huge, or the model629 is wrong?630- Retrieval/readability: concise enough to load, structured enough to follow631632Good model mix: Gemini for long-context/coverage, GPT for structure and command633specificity, Grok for adversarial prompt misuse, Claude for final synthesis and voice.634635### Outbound Communication636637Default panel:638639- Empathy / recipient experience640- Intent fidelity: does it say what the operator meant?641- Evidence: are claims true and appropriately qualified?642- Data exposure: does it leak internal, private, or wrong-person information?643- Voice and audience fit644645Good model mix: Claude for tone and empathy, GPT for concise edits, Gemini for evidence646checking, Grok for blunt risk on sensitive messages.647648### Plan, Strategy, or Decision649650Default panel:651652- Assumptions and missing information653- Dependency/order-of-operations risk654- Blast radius and reversibility655- Concrete next actions and ownership656- Contrarian review: what would make this fail?657658Good model mix: Grok for contrarian pressure, Gemini for context coverage, GPT for659structured plan critique, Claude for decision synthesis.660661### Tool Action, Config Change, Migration, or Rollout662663Default panel:664665- Target correctness: right host/profile/file/channel/account?666- Blast radius and rollback path667- Approval gate: does this need human go-ahead?668- Verification: how will we know it worked?669- Data exposure / 670671…(truncated)