ANTIGRAVITY LABJP
Articles/AI Tools
AI Tools/2026-07-30Advanced

Half My Tasks Went to Pro — and So Did Only 61% of the Tokens

A singular model setting became a models collection, which means routing across models is now something you define yourself. Here is how I re-measured a task-type routing rule against the actual context-size distribution of 67 tasks in my own repository.

Antigravity344Model RoutingContext Design3Cost Design2Measurement2

Premium Article

I was scrolling through the morning run logs when I stopped.

The rule that splits work between Flash and Pro by task type had been in place for a while. Screens and libraries go to Pro, everything else to Flash. By task count, Pro was clearly handling less.

It should have felt lighter. It didn't.

Around the same time, the singular gemini_config was replaced by a models collection on AgentConfig and LocalAgentConfig, bringing routing, fallback, and auto-selection helpers into the configuration itself. If I was going to rewrite the settings anyway, I wanted to rewrite the reasoning behind them too.

Rewriting the reasoning meant knowing what I was actually handing over. Once I measured it, the task-type axis turned out to matter far less than I assumed.

The question the models collection puts in your hands

A single model setting leaves nothing to decide. A collection changes that. Listing several models by role means you are the one who defines which work lands on which model.

An auto-selection helper still needs an axis, and that axis is yours to pick. The common one is task type: heavier reasoning to the larger model, routine work to the fast one. It reads sensibly, and I ran with it for a long time. I wrote about a related approach in routing /effort by task class.

What I had never done was check whether that axis was doing anything for cost.

You are not billed per task. You are billed per token. Nothing guarantees that the share of tasks and the share of tokens line up.

One caveat before the numbers: field names and structure move between versions. Confirm the exact shape against the built-in antigravity_guide or the current reference for whichever build you are on. What this article covers is how to decide what to feed that configuration.

Measuring what the agent actually receives

Define one task as editing one source file. What reaches the model is not that file alone — the local modules it imports come along with it.

So I treated the target file plus one hop of local dependencies as the context for a single task, and counted tokens. I used tiktoken with o200k_base as a stand-in tokenizer because it reproduces identically on my machine. It counts differently from the model's own tokenizer, so read the output as a ruler for the shape of the distribution rather than as absolute values.

#!/usr/bin/env python3
"""Measure the real context size of agent tasks over a repository.
 
One task = editing one file. The context handed over is that file plus its
local dependencies (one hop).
"""
import os, re, sys, json
import tiktoken
 
ROOT = sys.argv[1]
SRC = os.path.join(ROOT, "src")
ENC = tiktoken.get_encoding("o200k_base")
IMPORT_RE = re.compile(r"""(?:from|import)\s+['"]([^'"]+)['"]""")
EXTS = (".ts", ".tsx")
 
def files():
    out = []
    for d, _, fs in os.walk(SRC):
        for f in fs:
            if f.endswith(EXTS):
                out.append(os.path.join(d, f))
    return sorted(out)
 
def resolve(spec, origin):
    """Resolve an import spec to a local file path, or None for externals."""
    if spec.startswith("@/"):
        base = os.path.join(SRC, spec[2:])
    elif spec.startswith("."):
        base = os.path.normpath(os.path.join(os.path.dirname(origin), spec))
    else:
        return None
    for cand in (base + ".ts", base + ".tsx",
                 os.path.join(base, "index.ts"), os.path.join(base, "index.tsx")):
        if os.path.isfile(cand):
            return cand
    return None
 
CACHE = {}
def toks(path):
    if path not in CACHE:
        with open(path, encoding="utf-8", errors="replace") as fh:
            CACHE[path] = len(ENC.encode(fh.read()))
    return CACHE[path]
 
def context(path):
    with open(path, encoding="utf-8", errors="replace") as fh:
        src = fh.read()
    deps = set()
    for spec in IMPORT_RE.findall(src):
        r = resolve(spec, path)
        if r and r != path:
            deps.add(r)
    return sorted(deps), len(ENC.encode(src))
 
def pct(sorted_vals, p):
    k = (len(sorted_vals) - 1) * p / 100
    lo, hi = int(k), min(int(k) + 1, len(sorted_vals) - 1)
    return sorted_vals[lo] + (sorted_vals[hi] - sorted_vals[lo]) * (k - lo)
 
tasks = []
for f in files():
    deps, own = context(f)
    total = own + sum(toks(d) for d in deps)
    tasks.append({"file": os.path.relpath(f, ROOT), "deps": len(deps),
                  "own": own, "ctx": total})
 
vals = sorted(t["ctx"] for t in tasks)
total_tokens = sum(vals)
print(f"tasks={len(tasks)}  total_ctx_tokens={total_tokens}")
for p in (50, 75, 90, 95, 99):
    print(f"  p{p} = {pct(vals, p):,.0f}")
print(f"  max = {vals[-1]:,}  mean = {total_tokens/len(vals):,.0f}")
top5 = max(1, round(len(vals) * 0.05))
print(f"top {top5} tasks (5%) hold {sum(vals[-top5:])/total_tokens*100:.1f}% of all context tokens")
print("\nlargest 5:")
for t in sorted(tasks, key=lambda x: -x["ctx"])[:5]:
    print(f"  {t['ctx']:>7,}  deps={t['deps']:<3} {t['file']}")
json.dump(tasks, open("tasks.json", "w"))

Pointed at the site repository I maintain as an indie developer — 67 TypeScript and TSX files — it finished in 0.6 seconds.

tasks=67  total_ctx_tokens=220556
  p50 = 2,311
  p75 = 4,618
  p90 = 7,579
  p95 = 8,106
  p99 = 15,019
  max = 23,119  mean = 3,292
top 3 tasks (5%) hold 19.2% of all context tokens
top 13 tasks (20%) hold 51.6%

largest 5:
   23,119  deps=12  src/app/[locale]/articles/[category]/[slug]/page.tsx
   10,846  deps=3   src/app/[locale]/support/page.tsx
    8,382  deps=4   src/app/[locale]/membership/page.tsx
    8,188  deps=0   src/app/[locale]/about/page.tsx
    7,915  deps=1   src/app/[locale]/support/SupportClient.tsx

A median of 2,311 tokens against a maximum of 23,119 — a tenfold spread. The top fifth of tasks carries 51.6% of everything.

That was the moment I got a bad feeling. A rule that thinks in task counts cannot see this skew at all.

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
A complete Python script that measures the context an agent actually receives, including one hop of local imports, ready to point at your own repository
The measured gap between routing axes: the same task count sends 60.9% of tokens to Pro by task type, but 84.6% when chosen by size, and exactly where that gap comes from
Why the savings from routing disappear once your retry rate passes 8-10%, and why that break-even barely moves even when the price ratio quadruples
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

AI Tools2026-07-05
Is the $100 AI Ultra Tier Worth It Solo? Measure the Break-Even from Limits and Parallelism
Whether the $100/month AI Ultra tier (5x the Pro limit) is worth it for an indie developer, framed as a break-even from how often you hit the cap and the effective throughput of parallel agents, with a calculator script.
AI Tools2026-07-01
Measure Before You Trim: A Context Ledger for Antigravity CLI Token and Latency Costs
Prompted by the ~70% token reduction reported for the Android CLI agent, I built a thin wrapper and a weekly review to measure my own agent runs. Here is how I replaced whole-file context with line ranges and cut wait times.
AI Tools2026-07-14
Routing Between Local Gemma and Cloud Gemini 3.5 Flash by How Easily You Can Verify the Output
When I split local and cloud work by whether it was sensitive, or by which was faster, my decisions wobbled every time. The axis that finally held was different: if the output is wrong, can I catch it cheaply and undo it cheaply? Here is a router that chooses a model from verifiability and recovery cost, with working code and a measurement ledger.
📚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 →