agentsclimarketplace

Critic judge design

Skill Victoriakaey/build-reliable-agents/skills/critic-judge-design

Use when designing any LLM-as-Judge, Critic, or Evaluator node. Covers input structure, output schema, chain-of-thought ordering, single-pass vs multi-stage tradeoffs, and known failure modes. Prevents the most common design mistakes that cause Critic nodes to be unreliable.From its SKILL.md

Install
npx -y skills add Victoriakaey/build-reliable-agents --skill critic-judge-design

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.3 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

Critic / Judge Node Design

Terminology: This skill uses "Critic", "Judge", and "Evaluator" interchangeably. Pick one term for your codebase and use it consistently.

The Core Problem

A Critic node has one primary job: judge whether something meets a quality bar. Everything else it does (generating feedback, planning follow-ups, classifying failure types) is secondary.

The most common mistake: making the Critic do too much in one pass. When a node simultaneously judges quality AND generates structured follow-up plans, the two tasks interfere with each other — and the primary job (judgment) suffers.


Step 1: Define the Primary Job

Before designing any Critic, answer:

  1. What exactly is being judged? (evidence sufficiency, answer quality, SQL correctness, etc.)
  2. What is the binary output? (sufficient/insufficient, pass/fail, correct/incorrect)
  3. What does the Critic need to see to make this judgment?
  4. What does NOT need to be in the Critic's input?

The cleaner the primary job definition, the more reliable the Critic.


Step 2: Design the Input Structure

This is the most important decision. Input structure determines reasoning patterns more than prompt instructions do.

The Organization Problem

If you organize input by sub-question:

SQ1: "Find the patch window" → 0 rows
SQ2: "Find rollback artifacts" → 3 rows (contains patch window)

The LLM will evaluate each sub-question against its own text. It will conclude "patch window not found" from SQ1 even if SQ2's rows contain the answer. The input structure primes per-sub-question reasoning.

Flat Evidence Pool (preferred for sufficiency judgment)

Instead of organizing by sub-question, present evidence as a flat pool:

Original question: ...
Retrieved evidence:
- Row 1: {customer: "X", patch_window: "2026-03-24 02:00", ...}
- Row 2: {customer: "X", rollback_cmd: "orchestrator rollback ...", ...}

This forces the LLM to evaluate evidence against the original question, not against sub-question text.

Tradeoff: You lose sub-question provenance (can't say "SQ2 found this"). Gain: correct holistic reasoning.

When to keep sub-question organization

Keep it when the Critic's job IS per-sub-question evaluation (e.g., "did this specific sub-question return useful data?"). Remove it when the Critic's job is holistic sufficiency (e.g., "can the original question be answered from all evidence combined?").


Step 3: Design the Output Schema

Chain-of-thought ordering matters. The LLM reasons in the order it writes. Put the reasoning BEFORE the judgment, not after.

Wrong order (judgment first):

{
  "is_sufficient": true,
  "judgment": "Evidence covers the patch window...",
  "confidence": 90
}

The LLM commits to is_sufficient before writing the reasoning. The reasoning becomes post-hoc justification.

Right order (reasoning first):

{
  "evidence_present": ["patch_window", "rollback_cmd"],
  "evidence_missing": [],
  "judgment": "Both required fields are present in the retrieved rows...",
  "confidence": 90,
  "is_sufficient": true
}

The LLM must enumerate what's present and missing before committing to a verdict. This produces more accurate judgments.

Coverage score vs binary

Use an intermediate score (1-4) and derive a binary from it:

coverage_score: 1-4
is_sufficient: derived from coverage_score >= 3

This gives the LLM room to express nuance, and keeps the routing logic deterministic (binary derived from score, not LLM-generated bool).


Step 4: Decide Single-Pass vs Multi-Stage

Single-pass Critic (judgment + feedback in one call)

Use when:

  • Feedback is simple (just a list of missing sub-questions)
  • Prompt stays under ~60 lines
  • The feedback doesn't require complex reasoning beyond what judgment already does

Risk: As feedback complexity grows, judgment quality degrades. The two tasks interfere.

Multi-stage Critic (judgment in one call, feedback in another)

Use when:

  • Feedback requires detailed planning (gap types, dependency hints, suggested tables, strategy notes)
  • Prompt is already long (>80 lines)
  • Judgment quality is inconsistent

Structure:

Stage 1 — Judgment node:
  Input: original question + flat evidence pool
  Output: is_sufficient, retrieval_outcome, confidence, brief judgment

Stage 2 — Feedback Planner node (only runs if insufficient):
  Input: original question + evidence + judgment from Stage 1
  Output: gap_type, missing_evidence, suggested_tables, dependency_hints

Stage 3 — Follow-up Parser (already exists):
  Input: feedback from Stage 2
  Output: new sub-questions

Cost: One extra LLM call on insufficient cases only. No cost on sufficient cases.


Step 5: Routing Logic

Always derive routing from deterministic fields, not LLM-generated booleans.

# Fragile — LLM generates the bool
if state["is_sufficient"]:
    route to synthesizer

# Robust — derive from score
if state["coverage_score"] >= 3:
    route to synthesizer

For multi-outcome routing (sufficient / needs_more / no_evidence / unsupported_premise):

match state["retrieval_outcome"]:
    case "sufficient": route to synthesizer
    case "needs_more_retrieval": route to follow-up parser (if rounds < max)
    case "no_evidence": route directly to synthesizer
    case "unsupported_premise": route directly to synthesizer
    case _: route to synthesizer (safe default)

Always have a safe default that prevents infinite loops.


Step 6: Loop Guard

Every Critic-driven loop MUST have a hard exit condition independent of Critic judgment:

if critic_round_count >= max_rounds:
    force route to synthesizer
    # regardless of what Critic says

Also add sub-question deduplication to prevent the Critic from requesting the same sub-question repeatedly:

seen_signatures = set()
# before adding to pending queue, check signature
if sub_question_signature not in seen_signatures:
    pending_queue.append(sub_question)
    seen_signatures.add(sub_question_signature)

Known Failure Modes

FailureSymptomRoot CauseFix
Per-sub-question reasoningCritic judges each SQ independently, misses cross-SQ evidenceInput organized by sub-questionFlatten evidence pool
Post-hoc justificationCritic commits to verdict, writes reasoning to matchJudgment field before reasoning in schemaReorder: reasoning → score → verdict
Ghost rulesCritical rules ignored, less important rules followedPrompt too long, rules competing for attentionSimplify prompt, put critical rules first
Infinite loopsCritic keeps saying insufficient even when evidence existsNo loop guard, or loop guard too permissiveHard exit at max_rounds regardless of Critic
Follow-up driftFollow-up sub-questions drift from original question scopeCritic generates follow-ups without entity anchoringRequire Critic to scan completed SQs for entity names before generating feedback

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most design frontend skills give in ~1.6k tokens

Counted across 1,179 of the 2,086 authors here whose files we hold, read 2026-09-06

  • Commit to a bold aesthetic directionin 31 of 1179, across 24 files
  • Prefer component composition over inheritancein 28 of 1179, across 14 files
  • Animate only transform and opacity propertiesin 27 of 1179, across 22 files
  • Memoize expensive computations with useMemoin 26 of 1179, across 13 files
  • Use semantic HTML elementsin 24 of 1179, across 23 files
  • Virtualize long lists for performancein 21 of 1179, across 10 files
  • Use CSS variables for design tokensin 20 of 1179, across 14 files
  • Implement loading, empty, and error statesin 20 of 1179
  • Lazy load heavy components with Suspensein 19 of 1179, across 8 files
  • Respect prefers-reduced-motion media queriesin 18 of 1179, across 10 files
  • Prioritize CSS-only animations for HTMLin 18 of 1179, across 16 files
  • Use compound components for related UI elementsin 18 of 1179, across 7 files

Said here and by no other author read

  • define the primary judgment task clearly
  • use a flat evidence pool for sufficiency judgments
  • place reasoning fields before the judgment field in schema
  • derive binary outputs from intermediate scores
  • separate judgment and feedback into multi-stage nodes
  • derive routing logic from deterministic fields

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.