agent-patterns

validator-first

flowchart TD
    Issue([Issue / task input]) --> Validator[Validator agent]
    Validator --> Parse{Valid verdict\nJSON?}
    Parse -- no --> Fault([Block + label validator-error])
    Parse -- yes --> Valid{verdict ==\nVALID?}
    Valid -- yes --> Pipeline[Main pipeline]
    Pipeline --> Done([Output])
    Valid -- no --> Block([Block + label needs-refinement])

A validation agent runs before the main pipeline is triggered. Issues that don’t pass the gate never enter the loop.

How it works

  1. The validator agent inspects the incoming issue, wrapped in <issue> tags and treated as untrusted data, and returns JSON: {"verdict": "VALID" | "NEEDS_REFINEMENT", "reason": string}.
  2. If the issue is well-specified (VALID), the pipeline continues.
  3. If the issue is under-specified (NEEDS_REFINEMENT), the pipeline is blocked and a label (e.g. needs-refinement) is applied — no code is generated.
  4. The verdict is parsed strictly (one surrounding ` ```json ` fence is tolerated). Unparseable output fails closed with its own label, validator-error: the pipeline is blocked, but the fault is the validator’s, not the issue’s, so it goes to a human instead of back to the issue author.
  5. The validator runs on every request, so it runs at low effort with a small max_tokens; the main pipeline keeps medium. Effort is a per-role decision, not a global setting.

Where it came from

When to use

When not to use

Trade-offs

   
Pro Prevents wasted compute on tasks that can’t succeed
Pro Surfaces refinement needs early, before any irreversible action
Con Adds a latency step on every request — keep the gate at low effort to bound it
Con Validator criteria must be kept current as input expectations evolve

Failure modes