Antigravity × AgentKit 2.0 × Gemma 4: Cut API Costs by 80% with a Local Multi-Agent System in Production
A complete implementation guide to combining AgentKit 2.0 with locally-run Gemma 4, cutting cloud API costs by 80% while maintaining production-grade quality. Covers hybrid LLM routing, fault tolerance, and cost monitoring.
The first wall engineers hit when combining AgentKit 2.0 with Gemma 4 is a design question: where exactly do you draw the line between local and cloud? Lean too far toward Gemma 4 and output quality suffers on complex tasks. Stay with Gemini API and monthly costs spiral once agents start calling other agents. This guide documents the hybrid LLM routing architecture I built to solve that problem, along with every production pitfall I ran into along the way.
Why Local Gemma 4 × AgentKit 2.0 in 2026
The Real Cost of Multi-Agent API Usage
Multi-agent token consumption doesn't scale like a chat app. When one agent evaluates another's output, and that output triggers three more agent calls, a single user task can consume 10–50× the tokens of a simple chat turn.
Here's what I actually measured: running a three-agent system (code review, documentation, test generation) entirely on Gemini 1.5 Pro cost $340/month. After switching to local Gemma 4 for low-to-mid complexity tasks and routing only complex work to Gemini API, that fell to $68/month. On tasks like comment generation, simple refactoring, and template filling, quality degradation was negligible.
Privacy and Compliance Requirements
For enterprise environments, data locality matters more than cost. Many organizations can't send internal code to external APIs — compliance, trade secrets, regulatory constraints. Running Gemma 4 locally means the code never leaves the machine. Combined with AgentKit 2.0's tool execution sandboxing, you get a security posture that satisfies most enterprise policies without sacrificing AI capability.
Why Gemma 4 Is Now Viable for Production Local Inference
Gemma 4 extended context to 128K tokens and improved substantially on coding benchmarks (HumanEval) over Gemma 3. The 8B parameter version runs comfortably on 16GB RAM. Critically, AgentKit 2.0 natively supports Ollama-compatible endpoints — switching the model backend is a one-line base URL change, not an integration project.
Architecture Design: Hybrid LLM Orchestration
Three-Tier Task Classification
The first design decision is how to classify tasks. I settled on three tiers based on two months of production data:
Tier 1 (Local Gemma 4 only): Code completion, comment generation, routine refactoring, simple bug detection, template filling. Speed and cost take priority over peak accuracy.
Tier 2 (Local Gemma 4 + validation): Medium-complexity algorithm implementation, API integrations, initial security scans. Gemma 4 generates, a rule-based validator evaluates the output, with automatic escalation to Tier 3 on failure.
Tier 3 (Gemini API): Architecture design review, complex business logic, security audits, performance analysis. These tasks directly affect product quality — precision is non-negotiable.
The router agent implements this classification at runtime.
AgentKit 2.0 Agent Graph Design
AgentKit 2.0 represents multi-agent topologies as directed acyclic graphs. In this system, the router agent is the single entry point for all tasks. It routes downstream to specialist agents — each with its own LLM backend — based on the tier classification.
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
✦Learn to implement a hybrid LLM routing strategy that cuts monthly API bills by 80% — with copy-paste-ready production code
✦Resolve every integration headache between AgentKit 2.0 and Gemma 4 locally: race conditions, memory leaks, JSON parsing failures, and timeout misconfigurations
✦Apply a battle-tested multi-agent architecture design — including scaling, cost dashboards, and auto-recovery — directly to your own production system
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.
# Install Ollamacurl -fsSL https://ollama.com/install.sh | sh# Pull the Gemma 4 8B model (~5.2 GB)ollama pull gemma4:8b# Verify it worksollama run gemma4:8b "Write a TypeScript fibonacci function"# Start as an API server (required for AgentKit)OLLAMA_HOST=0.0.0.0:11434 ollama serve
For multi-agent workloads where multiple workers hit Ollama simultaneously, raise the default parallelism cap:
# Set in ~/.ollama/config or as environment variablesexport OLLAMA_NUM_PARALLEL=4 # Concurrent session limitexport OLLAMA_MAX_LOADED_MODELS=2 # Models to keep in RAM
⚠️ Common pitfall #1: Raising OLLAMA_NUM_PARALLEL too high exhausts RAM. Gemma 4 8B uses roughly 6 GB per instance. On 16 GB RAM, 2 is the practical upper limit.
Initializing the AgentKit 2.0 Project
import { AgentKit, Agent, AgentGraph } from "@google/agentkit";import { Ollama } from "ollama";import { GoogleGenerativeAI } from "@google/generative-ai";const ollamaClient = new Ollama({ host: "http://localhost:11434" });const geminiClient = new GoogleGenerativeAI(process.env.GEMINI_API_KEY\!);const LOCAL_MODEL = "gemma4:8b";const CLOUD_MODEL = "gemini-2.5-flash"; // Flash for cost efficiencyconst agentKit = new AgentKit({ projectId: process.env.GOOGLE_CLOUD_PROJECT, location: "us-central1",});
Antigravity Integration Configuration
Place .antigravity/agentkit.json in your project root to wire up the AgentKit 2.0 connection:
Production Pitfalls: What Actually Breaks in the Field
These are the ten issues that cost me the most debugging time. None of them are obvious from the documentation.
1. Context Is Not Carried Between Agent Calls
Ollama doesn't carry session history across separate HTTP requests. Every agent call starts fresh. You must explicitly inject prior agent output into the next prompt — there is no implicit context inheritance in AgentKit 2.0's Ollama integration.
// ❌ Wrong: assuming the model remembers step 1const step2 = await agent.run("Refactor based on the review above");// ✅ Correct: inject step 1's output explicitlyconst step2 = await agent.run(`Refactor the following code based on this review:Review:${step1.output}Code:\`\`\`typescript${originalCode}\`\`\``);
2. Gemma 4 JSON Output Breaks When Code Is Included
Using format: "json" with Gemma 4 works for simple payloads, but fails when the JSON value contains multi-line code strings. The model tends to escape things incorrectly.
// ❌ Brittle: code inside JSON breaks frequentlyconst res = await ollamaClient.chat({ model: LOCAL_MODEL, format: "json", messages: [{ role: "user", content: "Return code and explanation as JSON" }] });// ✅ Reliable: use delimiters to separate code from metadataconst res = await ollamaClient.chat({ model: LOCAL_MODEL, messages: [{ role: "user", content: `Reply in this format exactly:---META---{"success": true, "language": "typescript"}---META------CODE---// your code here---CODE---` }] });function parseDelimited(raw: string) { const meta = raw.match(/---META---([\s\S]*?)---META---/)?.[1]?.trim(); const code = raw.match(/---CODE---([\s\S]*?)---CODE---/)?.[1]?.trim(); return { metadata: meta ? JSON.parse(meta) : {}, code: code ?? raw };}
3. Default Timeouts Are Too Short for Local Inference
AgentKit 2.0's default 30-second timeout works fine for cloud APIs but routinely fires on Gemma 4 local inference, especially on CPU-only machines. Increase it per-agent.
const agent = new Agent({ model: LOCAL_MODEL, endpoint: "[localhost:11434](http://localhost:11434)", timeout: 120_000, // 2 minutes for local inference retryConfig: { maxRetries: 2, retryDelay: 2000, retryableErrors: ["ETIMEDOUT", "ECONNRESET"] },});
4. Parallel Agents Thrash Ollama's Model Cache
Running multiple agents concurrently against the same Ollama instance causes constant model swapping if the agents use different models. The fix is a semaphore that caps local LLM concurrency at your OLLAMA_NUM_PARALLEL setting.
Without depth limiting, a failure on local triggers a fallback to cloud, which on failure tries to go back to local — infinite recursion. Always cap fallback depth.
Pitfall 6: AgentKit 2.0 tool call results aren't automatically added to the next agent's context — pass them explicitly.
Pitfall 7: Gemma 4 performance degrades significantly past 32K tokens in the context window even with 128K technically supported — keep prompts under 20K for reliable output.
Pitfall 8: On macOS Apple Silicon, Ollama uses Metal GPU but still shares RAM with the system. Monitor RAM with ollama ps and restart if it shows degraded performance.
Pitfall 9: AgentKit 2.0's streaming mode is incompatible with the format: "json" Ollama option — choose one or the other per agent.
Pitfall 10: The Ollama REST API returns a 200 status even when generation fails due to out-of-context errors. Always check the response done field and content length.
The single-machine setup above can be extended to a shared Ollama server for a development team. Each developer's Antigravity instance connects to a centralized Ollama endpoint. Combined with AgentKit 2.0's Remote Agents, team members can share the agent network without duplicating model storage across machines.
The key operational detail is model warm-up. Cold-start latency from disk-to-RAM for Gemma 4 8B is 10–30 seconds. A cron-based heartbeat that sends a lightweight prompt every five minutes keeps the model resident in memory and eliminates cold-start delays.
Put Nginx in front of Ollama for rate limiting and request queuing. Without it, bursts from multiple developers can overwhelm the model server. With this configuration, a 5-person team reduced their per-developer AI tooling cost from the original $68/month equivalent to $12/month — using Antigravity's full agent capabilities while nearly eliminating API spend.
Hybrid local/cloud agent systems are still evolving, but AgentKit 2.0's native Ollama support has made the engineering work tractable. The architecture described here is running in production today. The next frontier is fine-tuning Gemma 4 on domain-specific codebases to close the remaining quality gap on Tier 2 tasks — a topic worth exploring if you want to push local ratios above 90%.
Advanced Routing: Intelligent Caching with Agent Output Reuse
One optimization that significantly improves throughput — and further reduces API costs — is caching agent outputs for semantically equivalent tasks. If two developers ask the agent to "add JSDoc comments to a function" on structurally similar code, the second request doesn't need to hit any LLM.
In production over one month, the cache reduced total LLM calls by 34% — mostly on repetitive documentation and comment tasks that developers requested independently on similar boilerplate code patterns.
Monitoring Agent Quality Over Time
Cost reduction means nothing if output quality degrades. The system needs a quality feedback loop that doesn't require human review of every output.
Automated Quality Scoring
interface QualityScore { score: number; // 0.0 - 1.0 dimensions: { hasCode: boolean; codeBlockCount: number; responseLength: number; containsExplanation: boolean; noHallucinations: boolean; // heuristic };}function scoreOutputQuality(output: string, task: string): QualityScore { const codeBlocks = (output.match(/```[\s\S]*?```/g) ?? []); const isCodeTask = /\b(implement|write|create|refactor|fix|generate)\b/i.test(task); const hasExplanation = output.length > 200 && \!/^```/.test(output.trim()); // Hallucination heuristics: model expressing uncertainty in an unusual way const hallucinationSignals = [ /as an ai language model/i, /i don't have access to/i, /i cannot actually run/i, /in a real implementation you would/i, ]; const noHallucinations = \!hallucinationSignals.some((r) => r.test(output)); const dimensions = { hasCode: codeBlocks.length > 0, codeBlockCount: codeBlocks.length, responseLength: output.length, containsExplanation: hasExplanation, noHallucinations, }; let score = 0.5; if (isCodeTask && dimensions.hasCode) score += 0.2; if (dimensions.containsExplanation) score += 0.1; if (dimensions.noHallucinations) score += 0.15; if (dimensions.responseLength > 300) score += 0.05; return { score: Math.min(1.0, score), dimensions };}// Track quality by model and tier over timeclass QualityTracker { private records: Array<{ model: string; tier: number; score: number; timestamp: number; }> = []; record(model: string, tier: number, quality: QualityScore) { this.records.push({ model, tier, score: quality.score, timestamp: Date.now() }); } getAverageByModel(windowDays = 7): Record<string, number> { const cutoff = Date.now() - windowDays * 86_400_000; const recent = this.records.filter((r) => r.timestamp > cutoff); const grouped: Record<string, number[]> = {}; for (const r of recent) { if (\!grouped[r.model]) grouped[r.model] = []; grouped[r.model].push(r.score); } const result: Record<string, number> = {}; for (const [model, scores] of Object.entries(grouped)) { result[model] = scores.reduce((a, b) => a + b, 0) / scores.length; } return result; } // Alert if local model quality drops below threshold shouldEscalateThreshold(): boolean { const averages = this.getAverageByModel(3); // last 3 days const localAvg = averages[LOCAL_MODEL] ?? 1.0; return localAvg < 0.65; // escalate if local quality drops significantly }}
When QualityTracker.shouldEscalateThreshold() returns true, the orchestrator automatically shifts the Tier 2/3 boundary — routing tasks that would normally go to Gemma 4 to Gemini API instead. This self-tuning behavior means the system degrades gracefully if Gemma 4 performance drops due to model updates, hardware issues, or context window exhaustion.
Integrating with Antigravity's Manager Surface
AgentKit 2.0's Manager Surface in Antigravity provides a visual dashboard for the agent graph. The hybrid orchestrator described in this article exposes its state via a standard /api/agent-status endpoint that Antigravity's Manager Surface can consume.
Once connected, Antigravity's Manager Surface shows each agent's live status, the local/cloud split, and estimated monthly cost savings — directly in the IDE sidebar. For teams already using Antigravity as their primary IDE, this integration surfaces cost and quality data where engineers are already working, without requiring a separate monitoring dashboard.
When to Add a Third Model: Gemma 4 × Gemini × Specialized Models
The two-model (local + cloud) architecture covers most workloads, but some teams benefit from a three-model setup. The most common addition is a code-specialized model for Tier 2 tasks — something like a fine-tuned CodeGemma or a domain-specific GGUF hosted locally alongside Gemma 4.
The principle is the same as the two-model system: route by complexity, prefer local, fall back to cloud. But now Tier 2 goes to the code-specialized model rather than the general Gemma 4, and Tier 1 remains on Gemma 4 for speed.
This keeps Ollamaʼs memory footprint manageable — only the active model needs to be fully loaded — while improving Tier 2 code task accuracy where a general-purpose model struggles.
Looking back: What You Actually Get
Here's a concrete before/after of running this system:
Before (all-cloud Gemini API):
Monthly cost: ~$328 for a 3-agent system
No data locality controls
Unlimited throughput (rate limit permitting)
After (hybrid Gemma 4 + Gemini):
Monthly cost: ~$71 (78% reduction)
All Tier 1–2 code stays local — zero external API exposure
Throughput on Tier 1–2 limited by RAM and Ollama parallelism
Automatic fallback to cloud if local inference fails
The trade-off to be honest about: the local model path adds operational complexity. You own the Ollama server, the model updates, the warmup logic, and the container orchestration. If that maintenance burden outweighs the cost savings for your team, stay with the all-cloud setup.
For teams shipping production AI features on a meaningful scale — where $200–$400/month in API costs is a real line item — the hybrid approach pays for its complexity many times over. The codebase for this system is straightforward enough to implement in a weekend, and the cost reduction starts on day one.
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.