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

Prompt Caching and Context Strategy for Antigravity Agents — Cutting 60-80% Off Monthly API Costs in Long-Running Production

The longer you keep agents running, the more the monthly invoice quietly piles up. Running Antigravity agents alongside an AdMob-monetized indie app business (50M cumulative downloads), I managed to cut API costs by 60-80% by rebuilding prompt caching and context strategy. This article shares the three-layer cache, context compression, and TTL design I now run in production — with the code and numbers behind them.

Antigravity377prompt cachingcost optimizationindie developer12agent operations8

✦ Premium Article

Six months after I started running agents seriously, I sat down with my monthly API bill and realized it was time to redo the design. I've been shipping apps as an indie developer since 2014, and around the time cumulative downloads crossed 50 million, AdMob revenue started growing — and the agents I had built into my workflow were eating a noticeable share of that revenue as a fixed cost.

So I rebuilt the whole prompt caching and context strategy from scratch. The result: same functionality, but 60-80% lower monthly API spend. Specifically, average input tokens per agent request dropped from 12,400 to 4,800, and total monthly cost went from $480 to $112. This article walks through the design and the gotchas.

Why Prompt Caching Alone Doesn't Cut It

Prompt caching is the first thing the official docs recommend. I started there. But when I measured, my cache hit rate was only 30-40%, and the cost savings never matched expectations.

The reason was simple. I was mixing "cacheable" and "always-changing" pieces of context without separating them. System prompts and reference docs were static, but I was inserting dynamic user input and tool results between them. Prompt caching only works as a prefix match — the moment one byte shifts upstream, everything after it becomes a cache miss.

I needed to redesign the context itself as a cache layer.

A Three-Layer Cache Architecture

The structure I now run in production splits into three layers by TTL and expected hit rate characteristics.

  • Layer 1 — System prompt: ~24 hour TTL, ~99% expected hit rate
  • Layer 2 — Reference docs: ~6 hour TTL, ~85% expected hit rate
  • Layer 3 — Recent dialogue history: ~5 minute TTL, ~60% expected hit rate

The key is keeping layer order strict. Layer 1 always comes first, then Layer 2, then Layer 3. Dynamic content (user input, tool results) goes inside Layer 3, ideally at the tail. Here's the TypeScript I run:

import { Anthropic } from "@anthropic-ai/sdk";
 
interface CacheLayer {
  type: "system" | "reference" | "history";
  content: string;
  cacheControl: { type: "ephemeral" } | undefined;
}
 
const buildContext = (
  systemPrompt: string,
  references: string[],
  history: Array<{ role: string; content: string }>,
  userInput: string,
): CacheLayer[] => {
  const layers: CacheLayer[] = [];
 
  // Layer 1: system (intended for ~24h caching)
  layers.push({
    type: "system",
    content: systemPrompt,
    cacheControl: { type: "ephemeral" },
  });
 
  // Layer 2: reference docs (~6h caching)
  for (const ref of references) {
    layers.push({
      type: "reference",
      content: ref,
      cacheControl: { type: "ephemeral" },
    });
  }
 
  // Layer 3: history + dynamic input (short cache + no cache)
  for (let i = 0; i < history.length; i++) {
    const isRecent = i >= history.length - 2;
    layers.push({
      type: "history",
      content: `${history[i].role}: ${history[i].content}`,
      // do not cache the last 2 turns (they change fastest)
      cacheControl: isRecent ? undefined : { type: "ephemeral" },
    });
  }
 
  // final user input is never cached
  layers.push({
    type: "history",
    content: `user: ${userInput}`,
    cacheControl: undefined,
  });
 
  return layers;
};

The moment I switched to this structure, cache hit rate jumped from 38% to 78%. The whole idea reduces to "stable stuff first, changing stuff last." That sounds obvious in hindsight, but I had been embedding timestamps in my system prompt, which alone was killing every layer.

✦

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
✦How to structure a three-layer cache (system / reference / history) with separate TTLs, and the concrete code that keeps cache hit rate above 75%
✦Context compression plus summary snapshots that cut input tokens by 60% — the actual numbers from my Antigravity production setup
✦The break-even point of cost-per-request when running alongside AdMob revenue, and three traps that indie developers walk into early
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 $15 for lifetime access
View Membership →

Related Articles

◈ Agents & Manager2026-09-09
When an Antigravity Scheduled Task Never Runs: Check sidecar.json, Then enabled, Then the Logs
A checking order for Antigravity 2.0 Scheduled Tasks that quietly do nothing: where sidecar.json lives, how the directory name becomes the ID, the enabled flag in config.json, and the logs under sidecar_data.
◈ Agents & Manager2026-09-08
Before I accept what /boost says it verified, I count what its throwaway worktree never saw
Antigravity's /boost runs its tests inside an ephemeral isolated worktree. If your build reaches for files git never tracked, that verification passed on a different tree than yours. Here is how I measure the gap first.
◈ Agents & Manager2026-09-06
With scheduled agents, I now look for runs that never happened before I look for failures
My run ledger showed a 100% success rate while the evening slot had not fired for two weeks. Here is the reconciliation I now run against an expected-fire table, with measured notes on cron expansion, exit codes, and how the ledger itself gets written.
📚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