ANTIGRAVITY LABJP
Articles/AI Tools
AI Tools/2026-08-19Advanced

When Antigravity Swaps Its Default Model, Only the Jobs You Narrowed First Survive

Gemini 3.7 Flash is now the default model for Antigravity agents. The places you never configured are exactly the places that shift silently. Here is how to inventory your default-model exposure, then split your jobs into move-now and hold, scored by how much output freedom you left open.

antigravity440gemini17agents132model-migration2

Premium Article

There is a generation job I run first thing every morning. It classifies wallpaper assets for one of the apps I maintain, and it has been running on the same configuration for months.

I did not notice that its output could change by looking at my own environment. I noticed it in a changelog. Gemini 3.7 Flash, generally available since August 13, is now the default model for Antigravity agents.

I had not touched a single line of configuration. Every place where I never wrote a model name moved to the new default anyway.

Before deciding whether to migrate, there was something else to establish: which parts of my setup were sitting on a thing called "default" — a place with no name of its own.

A default model changes without waiting for your consent

Switching models is normally something you initiate. You evaluate, you compare, you move if it looks better.

A default swap runs in the opposite direction. The provider decides, and the change lands wherever your configuration is silent. Nobody asks you, so you have no memory of agreeing.

Gemini 3.7 Flash ships at an introductory price of $0.75 per million input tokens and $3.75 per million output tokens. That price holds through December 31, 2026. From January 1, 2027 it becomes $1.50 and $7.50. The context window is 1,048,576 tokens with a 65,536-token output ceiling.

Numbers like that pull you toward a cost conversation. I deliberately did not start there, for reasons I will get to.

The first move is an inventory.

Find every place that rides on the default

Reading configuration files with your eyes is less reliable than it feels. Model selection lives in at least three places — agent definition frontmatter, settings.json entries, and CLI invocations in shell scripts — and in all three, "I forgot to specify this" looks almost identical to "I deliberately delegated this."

If you can't separate those two, the inventory is worthless. A file that says inherit is a place where someone understood the default would move and chose to follow it. A file with no model key at all is a place nobody thought about. Only the second kind needs attention.

#!/usr/bin/env python3
"""Find every place that silently depends on the default model.
 
Scans:
  1. Agent definition YAML frontmatter (presence of a model key)
  2. settings.json agents.* entries
  3. Shell scripts invoking the CLI (presence of --model)
 
"inherit" and "default" count as explicit delegation, kept separate from
a missing key. Collapsing the two makes the inventory useless.
"""
import json
import pathlib
import re
import sys
 
DELEGATING = {"inherit", "default", "auto"}
 
 
def read_frontmatter(path: pathlib.Path) -> dict:
    """Read only the leading --- block, without depending on PyYAML."""
    text = path.read_text(encoding="utf-8")
    if not text.startswith("---"):
        return {}
    end = text.find("\n---", 3)
    if end == -1:
        return {}
    fm = {}
    for line in text[3:end].splitlines():
        if ":" not in line or line.strip().startswith("#"):
            continue
        key, _, value = line.partition(":")
        fm[key.strip()] = value.strip().strip("\"'")
    return fm
 
 
def scan(root: pathlib.Path) -> list:
    findings = []
 
    for path in sorted(root.glob(".antigravity/agents/*.md")):
        fm = read_frontmatter(path)
        model = fm.get("model")
        if model is None:
            state = "unpinned"      # no key at all: riding the default silently
        elif model.lower() in DELEGATING:
            state = "delegated"     # following the default on purpose
        else:
            state = "pinned"
        findings.append({"where": str(path.relative_to(root)), "kind": "agent-def",
                         "name": fm.get("name", path.stem), "state": state, "model": model})
 
    settings = root / ".antigravity" / "settings.json"
    if settings.exists():
        data = json.loads(settings.read_text(encoding="utf-8"))
        for name, cfg in (data.get("agents") or {}).items():
            model = cfg.get("model")
            state = "unpinned" if model is None else (
                "delegated" if str(model).lower() in DELEGATING else "pinned")
            findings.append({"where": "settings.json", "kind": "settings",
                             "name": name, "state": state, "model": model})
 
    for path in sorted(root.rglob("*.sh")):
        for lineno, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
            if "antigravity" not in line or " run" not in line:
                continue
            pinned = re.search(r"--model[= ]([\w.\-]+)", line)
            agent = re.search(r"--agent[= ]([\w.\-]+)", line)
            findings.append({"where": f"{path.relative_to(root)}:{lineno}", "kind": "cli-call",
                             "name": agent.group(1) if agent else "(inline)",
                             "state": "pinned" if pinned else "unpinned",
                             "model": pinned.group(1) if pinned else None})
    return findings
 
 
def main() -> int:
    root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else ".").resolve()
    findings = scan(root)
    unpinned = [f for f in findings if f["state"] == "unpinned"]
 
    width = max((len(f["where"]) for f in findings), default=10)
    for f in findings:
        mark = {"pinned": "  ", "delegated": "= ", "unpinned": "! "}[f["state"]]
        print(f"{mark}{f['where']:<{width}}  {f['kind']:<9}  {f['name']:<20}  {f['model'] or '-'}")
 
    print(f"\n{len(unpinned)} of {len(findings)} locations depend on the default (marked !)")
    return 1 if unpinned else 0
 
 
if __name__ == "__main__":
    sys.exit(main())

Run against a small sample tree, it produces this:

  .antigravity/agents/classify-wallpaper.md  agent-def  classify-wallpaper    gemini-3.7-flash
! .antigravity/agents/draft-release-note.md  agent-def  draft-release-note    -
= .antigravity/agents/summarize-crash.md     agent-def  summarize-crash       inherit
  settings.json                              settings   classify-wallpaper    gemini-3.7-flash
! settings.json                              settings   draft-release-note    -
! scripts/nightly.sh:2                       cli-call   classify-wallpaper    -
! scripts/nightly.sh:3                       cli-call   draft-release-note    -
 
4 of 7 locations depend on the default (marked !)

Line six is the one worth staring at. classify-wallpaper has a model in its definition and a model in settings.json. The nightly script still calls it without --model.

Two out of three places were filled in, which is exactly why it felt finished. Which layer actually wins at runtime can vary by version and invocation path — so it is safer to assume every path is a hole until you have watched one run.

The script exits non-zero when anything is unpinned, which makes it usable as a gate in front of a scheduled run. New agents get caught the day they are added.

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
You will be able to mechanically inventory every place in your setup that silently rides on the default model, across agent definitions, settings, and shell scripts
You will be able to freeze the jobs that would break before the format drift reaches you, instead of chasing malformed output after the fact
You will be able to decide whether to adopt a new model from the shape of your output contract rather than from a promotional price with an expiry date
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-20
Building a Business Automation Agent with Antigravity × Google Workspace API — Complete Gmail, Drive, Sheets & Docs Integration
Learn how to build AI agents that automate Gmail responses, generate documents from Drive templates, and create intelligent Sheets reports using Antigravity, Google Workspace APIs, and Gemini.
Agents & Manager2026-03-20
Six Models, One Editor — Choosing Between Gemini, Claude, and GPT-OSS in Antigravity
Learn how to strategically leverage Gemini 3.1 Pro, Claude Opus 4.6, and GPT-OSS 120B in Antigravity IDE. This advanced guide covers model characteristics, AGENTS.md configuration, cost optimization, and multi-agent workflows.
AI Tools2026-06-18
Using the v2.1.4 Quota Screen for a Weekly Reckoning: Reading Used and Remaining to Run an Indie Budget
How to turn the used/remaining display in the reworked Antigravity v2.1.4 quota screen into a weekly reckoning instead of a gut feeling. Baseline recording, burn-rate math, and allocation across multiple projects, written as an indie-dev operating routine.
📚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 →