◉ANTIGRAVITY LABJP
Articles/Agents & Manager
◈ Agents & Manager/2026-05-30Advanced

Build for the Day the Agent Breaks Something: Keeping Blast Radius Small

Once you let an Antigravity agent touch production, the problem stops being how smart it is and becomes how much it wrecks when it slips. Here is a four-layer containment design that shrinks blast radius, with TypeScript and real numbers.

Antigravity386AI agents24production operations5reliability design4blast radius

✦ Premium Article

When you run a 50-million-download app business by yourself, the chores you'd love to hand off pile up fast: bulk dependency upgrades, keeping localized resource files in sync, batch-fixing the same crash class that Crashlytics keeps surfacing. The work I've been grinding by hand since 2014 is exactly the work I most want to automate.

So the first time I let an Antigravity agent do a bulk rewrite across a production repo, I froze in front of a diff that had broken 38 files at once. The agent's reasoning was wrong in exactly one place — but the design fanned that one decision out to every file, so the damage spread instantly. Tests passed. What broke was an initialization order the tests never looked at.

That day taught me that in agent operations, the thing that bites you first isn't intelligence — it's blast radius: how far a single failure spreads. Even a smart agent will be wrong sometimes. The real question is how much it drags down with it when it is. Below is a containment design for keeping that radius structurally small, with the implementation alongside.

Measure Blast Radius on Three Axes

"That feels risky" is a feeling, not a design. Before talking about containment, you need a ruler for damage. I use three axes.

  • Spread: how many files, records, or external calls a single run changes
  • Cost: the token billing that run consumes, plus the money wasted when it fails
  • MTTR: wall-clock time to roll back from broken to working

Reviewing the 38-file incident on these axes: spread was 38 (excessive), cost was about ¥120 per run (trivial), and recovery took 27 minutes of git revert plus build verification (heavy). So the real risk of that task was never money — it was excessive spread and long recovery time. Splitting the axes shows you which knob to tighten.

Start with a small helper that estimates damage before the run.

// risk-estimate.ts — estimate blast radius before an agent run
export interface RiskEstimate {
  spread: number;       // number of targets changed (files/records/API calls)
  costYen: number;      // expected token billing (yen)
  mttrMinutes: number;  // expected recovery time on failure (minutes)
}
 
export interface RiskPolicy {
  maxSpread: number;
  maxCostYen: number;
  maxMttrMinutes: number;
}
 
export function classifyRisk(est: RiskEstimate, policy: RiskPolicy) {
  const reasons: string[] = [];
  if (est.spread > policy.maxSpread) reasons.push(`spread ${est.spread} > ${policy.maxSpread}`);
  if (est.costYen > policy.maxCostYen) reasons.push(`cost ¥${est.costYen} > ¥${policy.maxCostYen}`);
  if (est.mttrMinutes > policy.maxMttrMinutes) reasons.push(`mttr ${est.mttrMinutes}m > ${policy.maxMttrMinutes}m`);
  // empty reasons → auto-approve; otherwise route to a human approval gate
  return { autoApprove: reasons.length === 0, reasons };
}

The key is keeping the logic dumb: if any one of the three axes exceeds its threshold, stop auto-execution and route to approval. Fancy scoring makes it impossible to explain later why a run was blocked. My rule is simple — I don't put unexplainable automated decisions in production.

Layer 1: See the Diff Before You Apply It

The outermost layer is a dry-run that pins down what will change before anything changes. Antigravity agents cause side effects through tool calls, so the leverage is splitting each tool into a "plan" mode and an "apply" mode.

// dry-run-wrapper.ts — split side-effecting tools into plan/apply modes
type Plan = { op: "write" | "delete"; path: string; preview: string }[];
 
interface ToolContext {
  mode: "plan" | "apply";
  plan: Plan;
}
 
export async function writeFile(ctx: ToolContext, path: string, content: string) {
  if (ctx.mode === "plan") {
    // don't write — just stage the change in the plan
    ctx.plan.push({ op: "write", path, preview: content.slice(0, 200) });
    return { staged: true };
  }
  await fs.writeFile(path, content, "utf-8");
  return { staged: false, written: true };
}
 
// run one agent turn in plan mode, measure spread, then apply
export async function runWithDryRun(agentTurn: (ctx: ToolContext) => Promise<void>, policy: RiskPolicy) {
  const ctx: ToolContext = { mode: "plan", plan: [] };
  await agentTurn(ctx);
  const spread = ctx.plan.length;
  if (spread > policy.maxSpread) {
    return { applied: false, plan: ctx.plan, blockedBy: `spread ${spread}` };
  }
  await agentTurn({ mode: "apply", plan: ctx.plan });
  return { applied: true, plan: ctx.plan };
}

The official tool-design guidance doesn't stress this, but what works in production is running the same turn twice: plan first, count spread, then apply. With a plan phase in place, the 38-file incident would have shown me "about to change 38 files" and I'd have stopped it. It costs a bit under 2x the tokens, but trading ¥120 of a run to erase a 27-minute recovery risk is cheap insurance.

One caveat: if a tool is non-deterministic (depends on time, randomness, or external state), running it twice breaks down. I snapshot tool inputs at the start of the run and feed the same values to both phases. Get sloppy here and you hit the worst betrayal — "the plan said 3, the apply changed 12."

✦

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
✦Wrap autonomous agent runs in four layers — dry-run, scoped permissions, circuit breaker, dead-letter queue — so a single runaway action can't cascade across production, with TypeScript you can drop in as-is
✦Learn from a real incident running a 50M-download app where one bulk rewrite corrupted 38 files, and how to measure blast radius along three concrete axes: file count, cost, and rollback time
✦Set circuit-breaker thresholds, dead-letter re-injection rules, and the human-approval boundary using real numbers that contain damage without strangling your own productivity
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-04-27
Antigravity Agent Product Blueprint — A 90-Day Plan Built on Gates and an Exit Line
A 90-day plan for turning an AgentKit 2.0 build into a product an indie developer can sell, organized around go/no-go gates instead of task lists. Includes an SDK-agnostic run wrapper, a D1 daily quota guard, a signature-verified Stripe webhook, and a break-even formula.
◈ Agents & Manager2026-04-27
Five Paths to Sell AI Agents Built on AgentKit 2.0 — How Indie Developers Should Pick a Distribution Channel
Where should a solo developer sell an agent built on Antigravity? Five channels — marketplace, own site, SaaS embed, consulting-to-product, subscription — compared by take-home share, customer distance and time to first revenue, with Stripe checkout code and a usage-cap check.
◈ Agents & Manager2026-10-16
Before Handing an Agent a .zip: Dropping .git Cut 29 MB to 15 MB, and 28 Secret Warnings Turned Out to Be Noise
Antigravity app v2.23.0 lets you attach a .zip. I packed my own repository to count what .git weighs and how many secret-scan warnings are false alarms, and I leave the full Python script that excludes, scans, and writes a manifest.