ANTIGRAVITY LABJP
Articles/Agents & Manager
Agents & Manager/2026-05-08Advanced

The Self-Critique Architecture for AI Agents — Four Reflection Patterns That Make Antigravity Outputs Trustworthy

Four production-tested patterns for adding self-critique loops to Antigravity agents, with implementation code, stopping conditions, confidence calibration, and cost-control strategies.

antigravity429agents123self-critiquereflectionproduction71

Premium Article

One night, I ran my release-notes agent three times in a row and threw all three drafts away. Nothing was wrong with them. I just couldn't quite trust them. The first paragraph in each draft read like something scraped from an unrelated marketing site — technically accurate, structurally correct, and somehow not mine. The bullet points were precise. The headline was clean. But every time I read it back, my hand stopped before clicking "publish."

What I realized that night was that I didn't want a "regenerate" button. I wanted an agent that would read its own draft once, doubt itself, and then submit. A skilled writer almost never ships their first draft. They re-read, the tone shifts, weak claims get evidence, paragraphs collapse. An agent without that re-reading step seems to hit a quality ceiling no model size can lift you past. Larger models produce more polished first drafts, but the gap between "polished" and "trustworthy" never closes by scale alone — only by structure.

This article walks through four self-critique (reflection) patterns I've been running on Antigravity agents in production. The implementation, the stopping conditions, the cost controls — all included. It builds on the Reflexion line of research but is shaped to survive the realities of small, solo-built projects, where you cannot afford a separate evaluation team and every additional API call shows up on your own credit card.

Why "just regenerate" isn't enough

The most naive quality lever is to drop temperature and resample. Generate three candidates, pick the best, ship. This catches some classes of errors and is genuinely worth doing as a baseline. Resampling is cheap, requires no new architecture, and addresses the most basic kind of LLM failure: stochastic word-choice drift.

But resampling only handles variance. If the model started from a flawed assumption — misread a requirement, missed a constraint, used outdated API conventions — every sample will share that blind spot. "Three rolls and all three feel off" is rarely noise. It's almost always a structural blind spot. The samples differ in surface details but agree on the underlying mistake, and no aggregation strategy can rescue you from agreement on the wrong answer.

Self-critique loops attack this exact gap. Instead of evaluating the output as text, they evaluate the output against the requirements at one level of abstraction up, and feed that gap analysis back into the next sample. The critic isn't asking "is this paragraph well-written?" — that's the same question the generator already failed to answer correctly. The critic is asking "does this paragraph satisfy the constraints I was given?" That second question is harder to fake, harder to drift on, and crucially uses different reasoning paths than generation itself.

Public docs often summarize this as "spin up a separate sub-agent for verification." That phrasing hides the design decisions that actually decide whether your agent works. Should the critic be a separate model call or built into the same prompt? What counts as a stop condition? Which mistakes can a single critic catch and which need multiple perspectives? How do you keep the critic from becoming a perfectionist that never approves anything? Those questions are where this entire post lives.

In my experience, teams that adopt self-critique without thinking carefully about these questions end up worse off than where they started. Their pipelines become slower, more expensive, and produce outputs that are noticeably more cautious and less distinctive than what the unmodified generator would have produced. That's the failure mode to avoid.

Pattern 1: Generator-Critic split

The cleanest baseline. Two distinct prompts: a Generator that drafts, a Critic that judges. The Generator retries — informed by the Critic's findings — until the Critic returns "approve." This is the architecture most papers describe and the one most easily understood by collaborators who haven't seen the system before.

# self_critique_loop.py
from google import genai
from pydantic import BaseModel
from typing import Literal
 
client = genai.Client()
 
class CriticVerdict(BaseModel):
    """Structured critic output. Separating verdict from issues
    makes the next-step action unambiguous for the Generator."""
    verdict: Literal["approve", "revise"]
    confidence: float  # 0.0 - 1.0
    issues: list[str]  # concrete revision instructions when verdict == "revise"
 
GENERATOR_PROMPT = """You are a release-notes writer.
Changes: {changes}
Past feedback: {feedback}
 
If past feedback exists, address it as the highest priority."""
 
CRITIC_PROMPT = """You are a technical editor. Decide whether the
release notes draft below is shippable.
 
Draft:
{draft}
 
Requirements:
- Reader can tell what changes mean for them
- No marketing-flavored adjectives
- Known constraints and workarounds are not omitted
 
If verdict is revise, list 1-3 concrete rewrite instructions in issues."""
 
def self_critique(changes: str, max_iterations: int = 3) -> tuple[str, list[str]]:
    feedback: list[str] = []
    history: list[str] = []
 
    for i in range(max_iterations):
        # 1. Generator drafts
        gen_resp = client.models.generate_content(
            model="gemini-2.5-pro",
            contents=GENERATOR_PROMPT.format(
                changes=changes,
                feedback="\n".join(feedback) if feedback else "(none)",
            ),
        )
        draft = gen_resp.text
        history.append(draft)
 
        # 2. Critic judges
        critic_resp = client.models.generate_content(
            model="gemini-2.5-pro",
            contents=CRITIC_PROMPT.format(draft=draft),
            config={"response_mime_type": "application/json",
                    "response_schema": CriticVerdict},
        )
        verdict: CriticVerdict = critic_resp.parsed
 
        if verdict.verdict == "approve" and verdict.confidence >= 0.8:
            return draft, history
 
        feedback = verdict.issues
 
    # Max iterations reached — return best draft for human review
    return history[-1], history

The max_iterations=3 cap is empirical but important. Beyond four iterations, quality saturates in most of my workloads while cost keeps climbing linearly. Stop early; you'll be glad you did. The intuition is straightforward: real improvements happen on the first or second pass when the critic catches something fundamental. By iteration four, the model is already chasing diminishing returns, and by iteration five it's often actively introducing regressions to satisfy a critic that has run out of legitimate complaints.

I started out assuming higher caps would help. The opposite turned out to be true: at five or seven iterations, the Critic itself starts to drift. It begins demanding "a slightly more careful tone" or "a touch more readability" without ever being satisfied, the Generator dutifully complies, and the prose loses every distinctive feature it had. The end result is generic, anodyne text that nobody would attach their name to. It looks a lot like what happens to me when I edit my own writing too long. There's such a thing as critic fatigue, and you have to design for it.

There's a second subtle issue with the split pattern: the critic can only see the final output, not the reasoning that produced it. If the generator made a wrong choice and then defensively justified that choice in the prose, the critic sees a coherent argument and approves. Solving this requires either Pattern 2 (where reflection sees the reasoning) or attaching the generator's chain-of-thought to the critic's input — which trades cost for visibility.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Move from 'I never trust the agent's first output and re-run it manually every time' to a system where self-critique loops keep quality consistent without you watching
Apply four concrete reflection patterns — with full implementation code — to your own agents today instead of just retrying with lower temperature
Avoid the cost blow-up that kills naive reflection loops by learning the stopping conditions, confidence thresholds, and budget controls that hold up in production
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Agents & Manager2026-07-05
Protecting Your Agent Stack's Known-Good State with a Single Lockfile — Change-Budget Design for an Era of Simultaneously Moving Parts
When the IDE build, CLI, model, and dependencies all move at once, you can no longer tell which one caused a regression. Here is a change-budget design that pins your known-good state to one lockfile, with working code and operational logs.
Agents & Manager2026-05-29
Supervising Long-Running Antigravity Agents — Watchdog and Tiered Recovery
Eight weeks of running AdMob revenue optimization on Antigravity background agents revealed three quiet failure modes. Here is the watchdog plus tiered recovery design I landed on.
Agents & Manager2026-05-27
Record & Replay for Antigravity Agents — A Production Pattern to Reproduce Failures in 3 Minutes
How to deterministically replay a failed Antigravity Agent run offline, drawn from a month of running it across four production sites. Covers boundary recording, R2 + KV storage costs, PII masking, and a working TypeScript harness.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →